第三章面向对象程序设计基础 OOP compaq
学习导读 掌握面向对象的程序设计的方法和Java作为面向对象序设计语言的特点 掌握构造一个类和如何创建一个对象,了解类和对象之间的关系 掌握接口的特点、结构、调用和继承 掌握Java的继承机制和实现多态的方法 掌握修饰符和构造方法的使用规则
类是Javar的核心。由于类定义了一个对象的功能和属性,因此整个Java语言建立在这个逻辑结构之上. 在一个类中程序的作用体现在方法中。 方法是Java创建一个有名字的子程序的方法
在Java中,没有类不能做任何事。 创建类有两种途径: 1。使用已有类 2。创建自己的类
3.1 类和方法 类是一类对象的共性描述 3.1.1 类 说话 人:姓名(name) 走路 身份证号(id) 思维 吃饭 人:姓名(name) 身份证号(id) 性别(sex) 身高(height) 体重(weight) 方法描述确定了对象具有的能力 状态描述表明了对象的状态特征
3.1 类和方法 一. 类:类是模板或蓝图,是用来创建对象的,它包含被创建对象的状态描述和方法定义。 类的定义包括两部分: 一. 类:类是模板或蓝图,是用来创建对象的,它包含被创建对象的状态描述和方法定义。 类的定义包括两部分: 1.声明和类体,其格式如下: [修饰符] class 类名 [extends 父类] [implements 接口名] 接口名跟在implements关键字后面,用来说明当前类中实现了哪个接口定义的功能和方法。 接口是Java语言用来实现多重继承的一种特殊机制,我们将在后面详细介绍它的使用方法。 {…… 类体 } class关键字,在它的后面,应跟随新数据类型的名称。(注意不要把class写成Class)。 类的修饰符用来说明类的特殊性质.分为三种: 访问控制符:public 公共类 抽象类说明符:abstract 最终类说明符:f inal 父类名跟在extends 关键字后面,用来说明当前类是哪个已经存在类的子类,存在继承关系。继承是类与类之间的一种非常重要的关系。
class Human {float hight,weight; String name,sex, id; void speak(String x, String y, String z) {name=x;sex=y;id=z; System.out.println(name +sex+ id); }
{float z; weight=x; hight=y; z=weight+hight; return z; } float walk(float x,float y) {float z; weight=x; hight=y; z=weight+hight; return z; } void think(){ } void eat(){ }
2.类体由两部分构成: Class Shape 一为变量定义(域) 二为方法定义 类头 {float area; int color; 一为变量定义(域) 二为方法定义 Class Shape 类头 {float area; int color; float x,y; 为变量定义(域) void draw() { } void erase(){ } void move(){ } int getColor() { } } 方法定义
成员变量: 类定义时,变量定义部分所定义的变量 上例:float hight,weight; String name,sex,id; 其中的hight,weight,name,sex,id 为成员变量 局部变量: 方法体中定义的变量和方法的参数 上例方法定义中的float f(float x,float y) {float z; …… }中的 x ,y,z 为局部变量
有效区域 成员变量在整个类内都有效; 局部变量只在定义它的方法内有效。 例:class Ex2 {int x; int f() { int a; x=a;}//X为全局变量 int g() { int y; y=a;}//a为局部变量 } 局部变量只在定义它的方法内有效。 Dfgb
成员变量的隐藏性 局部变量与成员变量名字相同时,则成员变量被隐藏,即在这个方法内暂时失效, 例:局部变量起作用 class tom {int x=98,y; void f() { int x=3; y=x; }//y=3 }
成员变量起作用 class tom {int x=98,y; void f() { int x=3; y=this.x; } //y=98
实例变量、类变量 成员变量又分为实例(成员)变量和类(成员)变量 用static修饰的成员变量为类变量,也叫静态变量,否则为实例变量。 例: calss example {float x; static int y; …… }
3. 类之间的关系 类之间最常见的关系: 依赖 (uses-a):如果一个类中的方法操作了另一个类的对象,那么这个类就依赖于另一个类 例:发动机类与汽车类 关联 (has-a) :类A的对象包含类 B 的对象 例:汽车类与制造商类 继承 (is-a) :表示一个特定的类和一个一般的类之间的关系.一般来说,如果类A扩展了类 B ,那么类A不仅继承类 B 的方法和状态,而且还有属于自己的方法和状态。 汽车与交通工具类
二是与其他的类或对象进行数据交流、消息传递等操作。 3.1.2 方法定义 类中定义的方法通常起到两种作用:一是围绕着类的属性进行各种操作; 二是与其他的类或对象进行数据交流、消息传递等操作。
1.Java中声明方法的语法如下: [修饰符] 返回值类型 方法名(参数列表) throws 例外名1,例外名2,… { 方法体:局部变量声明; 语句序列; }
例:void natural(string x, string y, string z) float f(float x,float y) 2.方法的声明:名字、类型和参数等属性的说明 例:void natural(string x, string y, string z) float f(float x,float y) 注:方法的类型描述的是返回值类型 无返回值时类型为void
3.方法体: 由局部变量定义和 java 语句组成 例1:int f(int x,int y) { int z; z=x* x+y* y+1; return z; }
例 2 :void natural(string x,string y,string z) { name=x sex=y; id=z; system.out.println;(name +sex+ id) }
一类是需要程序书写专门的调用命令来调用的方法,称为程序调用方法,例如: isPfime (); Java语言中定义的方法有两类: 一类是需要程序书写专门的调用命令来调用的方法,称为程序调用方法,例如: isPfime (); 另一类是运行过程中系统自动调用的方法,称为系统方法,例如我们前面程序中的action()、paint()、init()等。这两类方法的定义和使用原则有很大差异。
4. Static 静态方法 用static修饰的方法叫静态方法或类方法 静态方法和静态变量可通过对象或类名来调用
实例方法和类方法的区别 实例方法只能通过对象来调用 类方法还可以直接由类名来调用 class A {int x,y; static float f(int a) {……} float g(int x1,x2) {……} }
{public static void main(String args[]) {A a1=new A(); a1.f(2,3);//ok class B {public static void main(String args[]) {A a1=new A(); a1.f(2,3);//ok a1.g(2,5);//ok A.f(4,6);//ok A.g(8,9);//Error …… } } System.out.println(“*******”);
早期语言,比如C语言,不同的函数不能通明,导致 shirtWash(shirt) carWash(car) dogWash(dog) 3.1.3 方法的重载(overloading): wash the shirt wash the car wash the dog 我们通过判断被wash的物体知道该用哪种方法来wash 早期语言,比如C语言,不同的函数不能通明,导致 shirtWash(shirt) carWash(car) dogWash(dog)
例:class Wash { wash(Cloth shirt) { …… } 一个类中可以有多个方法具有 相同的名字, 相同的类型, 不同的参数, 这种情况叫 重载 例:class Wash { wash(Cloth shirt) { …… } 参数的不同体现在类型和个数上的不同 wash (Auto car) { …… } wash (Animal dog,int n) { …… } }
动态绑定: 1、编译器检查对象的声明和方法名。 例:调用wash方法,所有名字为wash的方法都会被找出来。 wash (Cloth shirt) wash (Auto car) wash (Animal dog,int n) 2、编译器根据调用时的实参值,选择所调用的方法,例:wash(benz)
也叫构造器,是一种特殊的方法,其作用是用来构造并初始化对象。 3.1.4 构造方法 也叫构造器,是一种特殊的方法,其作用是用来构造并初始化对象。 它的名字必须与它所在的类名字相同,且类型为void。 例 1:class Student { public Student (String n, double s) { name =n; score =s;} public string getName() { return name;} private double score; private String name; } }
例2:class Rock { 构造方法也常常用来为成员变量赋初值 当用某一个类创建一个对象时,这个类的构造方法将自动被执行 Rock() { // This is the constructor System.out.println("Creating Rock"); }} public class SimpleConstructor { public static void main(String[] args) { new Rock(); } } 当用某一个类创建一个对象时,这个类的构造方法将自动被执行 构造方法也常常用来为成员变量赋初值
调用另一个构造器 当成员变量与局部变量同名时,可用关键字this指向隐式参数,完成对成员变量的引用 如果构造器第一个语句为 此处表示调用此类中的另一个构造器 例:class Student { public Student (string n, double s) { name =n; score =s;} public Student ( double s) { this ("no.4: wanghong",s); }…..
当调用new Student (628) 时, Student ( double s) 构造器首先调用 Student ( string s, double n)构造器 使用关键字this很有用,只需对公共的构造方法定义一次 例:thisEx.java public class b { b(){ this(12); System.out.println("bbb"); }
执行:main => b()=>b(12)=>b()剩余部分 b(int x){ System.out.println("ccc“+x); } public static void main(String[] args){ new b(); } } 结果: ccc12 bbb 执行:main => b()=>b(12)=>b()剩余部分
3.2 对象 1.对象的定义 当使用一个类创建了一个对象时,就说给出了这个类的一个实例,只有通过对象才可以访问该类中的变量、调用该类中的方法(static变量、static方法除外) 定义对象包括对象的声明和创建对象两部分 对象的声明: 类的名字 对象名字 例:
class Student {public Student() {System.out.println(“我是学生”); } public Student (string n, double s) { name =n; score =s;} public string getName() { return name;} private double score; private String name;
Student wanghong,liwei; 声明对象: Student wanghong,liwei; 声明后内存情况: wanghong 0x367da liwei 0x746ff
创建对象即是为声明的对象分配内存 用new 运算符和构造方法为对象分配内存 例: wanghong= new Student() liwei=new Student("liwei",640) 声明和创建也可一次完成 Student wanghong= new Student() Student liwei=new Student("liwei",640)
创建后内存情况: wanghong name score liwei liwei 初始化 640 为成员变量赋初值
类定义的变量中含有静态变量时,该类中的所有对象的静态变量共享同一存贮单元 class Student {public Student (String n, double s,String c) { name =n; score =s; classno=c;} 。。。。。 private double score; private String name; Private Static String classno. } } Student wanghong= new Student(); Student liwei=new Student("liwei",640,0209);
创建后内存情况: wanghong name static score classno 0209 liwei liwei 640
例:StaticEx.java class Family { static String familyname; String name; } father=new Family(); son1=new Family(); son2=new Family(); father.familyname="我是"; father.name="父亲"; son1.name="大儿子"; son2.name="小儿子";
Father:我真的不是父亲 Son1: 我真的不是大儿子 Son2: 我真的不是小儿子 Father:我是父亲 Son1: 我是大儿子 public void paint(Graphics g) {g.drawString("father:"+father.familyname+father.name,50,50); g.drawString("son1:"+son1.familyname+son1.name,50,100); g.drawString("son2:"+son2.familyname+son2.name,50,150); Father:我真的不是父亲 Son1: 我真的不是大儿子 Son2: 我真的不是小儿子 Father:我是父亲 Son1: 我是大儿子 Son2: 我是小儿子 father.familyname="我真的不是"; g.setColor(Color.green); g.drawString("father:"+father.familyname+father.name,50,200); g.drawString("son1:"+son1.familyname+son1.name,50,250); g.drawString("son2:"+son2.familyname+son2.name,50,300);} }
2.默认字段初始化 如果在构造方法中没有明确地给某个字段赋值,那么此字段会被自动赋以一个默认值。 数值型: 0 布尔型:false 对象引用:null 例:在上例 中: wanghong的name应为:null score为:0
3 默认构造器 如果编写了一个没有构造器的类,则系统会自动为该类提供一个默认的构造器,其名字为类名,无参,方法体为空。 用该类创建对象时,实例变量将被初始化为默认值。
4. 初始化块 例:{int x=0; float pi=3.1459} 为成员变量初始化可用如下方法: *在构造器中赋初值 *声明的同时赋值 *用初始化块 初始化块就是用{ }括起的Java语句 例:{int x=0; float pi=3.1459}
放在所有函数之外 普通初始化 初始化块分为 静态初始化 class Student { private double score; private String name; // object initialization block { score=0; name=“ “; } } 普通初始化 初始化块分为 静态初始化
结果:Init Main Ccc12 bbb public class b { b(){ this(12); System.out.println("bbb"); } 结果:Init Main Ccc12 bbb 调用重载的构造 b(int x){ System.out.println("ccc“+x); } 初始化 {System.out.println(“init");} public static void main(String[] args) {System.out.println(“main"); new b(); } } 执行顺序: 初始化块; Main; b(); b(int x); b()剩余部分
静态初始化块常用来初始化静态值 例:static int nextid; static {Random gen =new Random(); nextid=gen.nextInt(1000); } 不管是哪个构造器构造了一个对象, 首先运 行静态初始化块, 然后运行初始化块, 最后构造器的主体部分被执行。 不管创建几个对象,静态初始化块只被执行一次; 每创建一个对象,初始化块就执行一次
public class ConstructerTest { this(12); System.out.println("no parameter construct");} ConstructerTest (int x){ System.out.println(" one parameter construct"); } {System.out.println("init");} static {System.out.println(" static init");} public static void main(String[] args){ new ConstructerTest (); new ConstructerTest (); }
运行结果: static init Init one parameter construct no parameter construct
总结: 1.重载的构造器 2.使用this(…)调用另一个构造器 3.默认构造器 4.初始化块 5.静态初始化块 6.实例字段初始化 例:一个关于构造器的例子Constructortest.java
class Employee { private String name = ""; private double salary; private int id; private static int nextId; // three overloaded constructors
// static initialization block { System.out.println("static initalization"); Random generator = new Random(); nextId = generator.nextInt(10000); } // object initialization block { System.out.println(" initalization"); nextId++; }
public Employee(String n, double s) { name = n; salary = s; System.out.println(" two parameters 222"); } public Employee(double s) { // calls the Employee(String, double) constructor this("Employee #" + nextId, s); System.out.println(" one parameter 111"); }
// the default constructor public Employee() { System.out.println(" no parameter 000"); } public String getName() { return name; } public double getSalary() { return salary; } public int getId() { return id; }
public class ConstructorTest { public static void main(String[] args) // fill the staff array with three Employee objects Employee[] staff = new Employee[3]; staff[0] = new Employee("Harry", 40000); staff[1] = new Employee(60000); staff[2] = new Employee();
// print out information about all Employee objects for (int i = 0; i < staff.length; i++) { Employee e = staff[i]; System.out.println("name=" + e.getName() + ",id=" + e.getId() + ",salary=" + e.getSalary()); }
3.3继承 本节导读 本节讨论面向对象的编程(OOP)及其关键技术:继承和多态、接口、包。 继承性是软件复用的一种形式,对降低软件复杂性行之有效。 继承性同时是面向对象程序设计语言的特点,采用对象但没有继承性的语言是基于对象的语言,但不是面向对象的语言,这是两者的区别。 多态性允许以统一的风格处理已存在的变量及相关的类,使增加系统中新功能变得容易。
教学重点与难点 理解继承和复用的概念 理解父类和子类 掌握扩展类编程 理解多态性是如何扩充和维护系统性能 掌握如何建立包和接口
3.3. 1 继承的概念 一.继承 类之间的继承关系是现实世界中遗传关系的直接模拟,它表示类之间的内在联系以及对属性和操作的共享,即子类可以沿用父类(被继承类)的某些特征。当然,子类也可以具有自己独立的属性和操作。 例如,飞行器、汽车和轮船可归于交通工具类,飞行器类可以继承交通工具类某些属性和操作
除遗传关系外,现实世界中还普遍存在着部分—整体关系。例如,飞机可由发动机、机身、机械控制系统、电子控制系统等构成,这就是依赖关系。 继承性是面向对象程序设计语言的最主要的特点,是其他语言(如面向过程语言)所没有的。
二、继承定义 继承性是软件复用的一种形式。新类由已存在的类生成,通过保留它们的属性和行为,并且根据新类的要求对性能加以修改,添加新的属性和行为。 class Student { public Student() { System.out.println(“我是学生”); } private double score; private String name;
class Graduate extends Student { String Major; String tutor; int paper; void involving(){ /*实施方案*/ } void Java() {/*正在学习Java*/ } /*还可以定义其它方法*/ }
如果子类只从一个父类继承,则称为单继承;如果子类从一个以上父类继承,则称为多继承。注意 Java不支持多重继承,但它支持“接口”概念。接口使Java获得了多重继承的许多优点,摒弃了相应的缺点
1.继承定义 例:已有一个human类,现在要定义一 个教师类 Class Human {float hight,weight; String name,sex, id; void speak(String x, String y, String z) {name=x;sex=y;id=z; System.out.println(name +sex+ id); }
Class Teacher extends Human {String major; String profession; void course(int num,int classno) { …….. }
当通过扩展一个超类来定义子类时,只需说明子类和超类的区别。 继承可定义如下: class 新类名 extends 已有类名 extends 表明你用已有类构建了一个新类,或 新类继承了已有类 已有类称为:超类、基类或父类 而新类称作子类或者派生类 子类通常比它们的超类具有更多的功能 当通过扩展一个超类来定义子类时,只需说明子类和超类的区别。
设计类时,一般把最通用的方法放进超类中而更具体和专门的方法应该放在子类中 子类中也可以重写超类中的方法,但是,继承不能去除超类中的任何变量和方法
固定工资雇员类:SalariedEmployee 计时工雇员类:HourlyEmployee 业绩雇员类:CommissionEmployee 56
class SalariedEmployee extends Employee { int m_ManagerNo ; // 代表雇员上司的编号 } class HourlyEmployee extends Employee : { int hour; //代表工作时间 } class Commission Employee extends Employee : { int commission; //代表销售额}
2.继承的执行 结果:aaa bbb class a{ public a(){ System.out.println("aaa");} } public class Extends extends a { Void Extends(){ System.out.println("bbb"); } public static void main(String[] args) {new Extends();} 结果:aaa bbb
a.当一个类继承了其父类时,当用该类构造对象时,首先执行父类的无参构造方法,然后再执行该类的构造方法。 例:继承的例子Extends.java
例:chess2.java class Game { Game(int i) { System.out.println("Game constructor"+i); } Game() { System.out.println("no parameter Game constructor" );
class BoardGame extends Game { BoardGame(int i) { System.out.println("BoardGame constructor"+i); } BoardGame( ) { System.out.println("no parameter BoardGame constructor" );
public class Chess2 extends BoardGame { System.out.println("Chess2 constructor"); } public static void main(String[] args) { Chess2 x = new Chess2(); no parameter Game constructor no parameter BoardGame constructor Chess2 constructor
b.在子类中显性调用父类的方法和变量 例: public Graduate( ) {super.getName(); …… } 例:Chess.java class Game { Game(int i) { System.out.println("Game constructor"); }
class BoardGame extends Game { BoardGame(int i) { super(i); System.out.println("BoardGame constructor"); }
public class Chess extends BoardGame { super(11); System.out.println("Chess constructor"); } public static void main(String[] args) { Chess x = new Chess(); Game constructor BoardGame constructor Chess constructor
3.3.2 多态 多态是面向对象程序设计中的一个重要概念,是指在程序中使用相同的名字表示不同的含义。 多态是面向对象程序设计中的一个重要概念,是指在程序中使用相同的名字表示不同的含义。 利用多态,调用同一个方法会执行不同的操作,这取决于调用该文法的对象
Animal----move Bird Turtle Fish
对象变量是多态的 例:Student liwei,wanghai; liwei=new Student(…..); wanghai=new Graduate(…..); 例:Music.java(c07)
class Note { private int value; private Note(int val) { value = val; } public static final Note MIDDLE_C = new Note(0), C_SHARP = new Note(1), B_FLAT = new Note(2); } class Instrument { public void play(Note n) { System.out.println("Instrument.play()"); }}
class Wind extends Instrument { public void play(Note n) { System.out.println("Wind.play()"); } } public class Music { public static void tune(Instrument i) { // ... i.play(Note.MIDDLE_C); } public static void main(String[] args) { Wind flute = new Wind(); tune(flute); // Upcasting } Wind.play();
重写是运行时的一种多态形式,即可以在子类中重写父类的方法。 例:Rewrite.java 3.3.3 重写(overriding) 重写是运行时的一种多态形式,即可以在子类中重写父类的方法。 例:Rewrite.java import java.applet.*; import java.awt.*; class Father {private int money; float weight,height; String head; String speak(String s) {return s;} }
public class Rewrite extends Applet {Son boy; public void init() {boy=new Son(); boy.weight=1.80f; boy.height=120f; boy.head="一个头"; boy.hand="两只手"; boy.foot="两只脚"; } class Son extends Father {String hand,foot; String speak(String s) {s="谁说"+s; return s;}} public void paint(Graphics g) {g.drawString(boy.speak( “我是男孩"),5,20); g.drawString(boy.hand+ boy.foot+boy.head+ boy.weight+boy.height,5,40); }}
当在子类中重写了父类中的方法时,就意味着在源程序中存在两个名字、类型 、参数都一样的方法,一个属于父类,一个属于子类。此时,编译程序会自动 识别所要执行的方法。 执行的应是子类中的方法 要执行父类中的方法应用super 谁说我是男孩 两只手两只脚一个头1.80f 120f
3.3.4 造型转换 如果要把一个超类对象赋给一个子类对象变量,就必须进行类型转换 格式: 子类 对象=(子类)(父类对象) 例:Human p1=new Human(); Teacher t1=(Teacher) p1; Object--所有类的超类
3.4 包(package) 包是相关的类和接口的集合 包的主要用途:减少命名混乱问题 、方便程序组织 classn class1 interface3
1.使用包 一个类可以使用它所在包中的所有类,也可以使用来自其它包中的所有public类 访问其它包中的类有两种方式: a.类名前加上完整的包名 例:Java.awt.Button button1; Java.util.Date today;
import java.awt.Button ; 再使用这些包中的类时就不必指明包名 上例可改为: Button button; b.利用import语句导入特定的类 例:import java.util.* import java.awt.Button ; 再使用这些包中的类时就不必指明包名 上例可改为: Button button; Date today; 包 import 程序
如果源文件中不使用package语句指明包名,源文件的类将属于默认包,默认包中的类文件系统会自动存放在当前目录下。 2 .向包中添加类 要把类放入一个包中,首先用package语句指明包的名字,且该语句应为程序的第一条语句,然后才是定义类的语句 例:package com.horstmann.corejava; public class Employee { ………… } 如果源文件中不使用package语句指明包名,源文件的类将属于默认包,默认包中的类文件系统会自动存放在当前目录下。
当一个源文件中使用了package语句时,那么这个包中所有的类文件都必须放在与包名相匹配的子目录中。也就是说:包名反映了文件系统中的目录层次 上例中,Employee.class文件必须位于 com\horstmann\corejava\子目录下 当程序中所使用的类位于不同包时,这点特别重要。 例:PackageTest类属于默认包;Employee类属于com.horstmann.corejava 其源文件和类文件必须如下组织:
import com.horstmann.corejava.*; // the Employee class is defined in that package public class PackageTest { public static void main(String[] args) Employee harry = new Employee("Harry Hacker", 50000); System.out.println("name=" + harry.getName() + ",salary=" + harry.getSalary()); }
当前目录 com PackageTest.java PackageTest.class Classpath指定的目录 Employee.java Employee.class horstman 例:package.java corejava
为了使包可以在多个程序中共享,可以如下组织类文件系统: a.把类放在一个或多个特定目录中 b. 设置类路径 3.虚拟机如何定位类 类文件的组织:包和存档文件(一个JAR存档文件可以包含多个类文件以及子目录,JAR文件采用ZIP格式来组织文件和子目录,这种方式可以节省空间并减少访问时间。) 为了使包可以在多个程序中共享,可以如下组织类文件系统: a.把类放在一个或多个特定目录中 b. 设置类路径 CLASSPATH环境变量 在编译器和解释器指定CLASSPATH选项
Java的核心类包含在运行库jre/lib/rt.jar中,系统将自动对其进行检索,以查找所需要类文件 Set classpath=.;c:\classes;c:\archeves\archeves.jar Java的核心类包含在运行库jre/lib/rt.jar中,系统将自动对其进行检索,以查找所需要类文件 编译时设置类路径: Javac -Classpath .;c:\classes;c:\archeves\archeves.jar MyProg.java
为虚拟机时设置类路径: Java -Cp .;c:\classes;c:\archeves\archeves.jar MyProg
私有变量或私有方法只能在定义它的类中使用 3.5修饰符 一.访问权限 我是自私的 ,别碰我!!! a.private 私有变量或私有方法只能在定义它的类中使用 class Sundae { private Sundae() { } static Sundae makeASundae() { return new Sundae(); } }
public static void main(String[] args) { public class IceCream { public static void main(String[] args) { Sundae x = new Sundae();//error Sundae x = Sundae.makeASundae();} }
class Sundae { private Sundae() {} static Sundae makeASundae() { return new Sundae(); } public static void main(String[] args) { Sundae x = new Sundae(); Sundae x = Sundae.makeASundae();
公有变量或公有方法在任何其它 类 中都可以访问 同一个包、不同的包中的类 我有,你有,全都有!!! b.public 公有变量或公有方法在任何其它 类 中都可以访问 package c05.dessert; public class Cookie { public Cookie() { System.out.println("Cookie constructor");} void bite() { System.out.println("bite");} }
import c05.dessert.*; public class Dinner { public Dinner() { System.out.println("Dinner constructor"); } public static void main(String[] args) { Cookie x = new Cookie(); //! x.bite(); // Can't access } }
不用修饰符修饰的变量和方法称为友好变量和友好方法,可以在同一包中的不同类之间访问 有事您call我,谁让咱们是朋友呢!!! c.friendly 不用修饰符修饰的变量和方法称为友好变量和友好方法,可以在同一包中的不同类之间访问 package c05.dessert; public class Cookie { public Cookie() { System.out.println("Cookie constructor");} void bite() { System.out.println("bite");} }
package c05.dessert; public class Dinner { public Dinner() { System.out.println("Dinner constructor"); } public static void main(String[] args) { Cookie x = new Cookie(); x.bite(); // Can access
d.protected 当子类和父类不在同一个包时,子类可以访问父类中的protect成员 package c05.dessert; 我真想独立,摸 摸兜里没有多少钱!!! d.protected 当子类和父类不在同一个包时,子类可以访问父类中的protect成员 package c05.dessert; public class Cookie { public Cookie() { System.out.println("Cookie constructor");} void bite() { System.out.println("bite");} }
import c05.dessert.*; public class ChocolateChip extends Cookie { public ChocolateChip() { System.out.println("ChocolateChip constructor"); } public static void main(String[] args) { ChocolateChip x = new ChocolateChip(); //! x.bite(); // Can't access bite } }
Protected void bite() package c05.dessert; public class Cookie { public Cookie() { System.out.println("Cookie constructor");} Protected void bite() {System.out.println("bite");} }
import c05.dessert.*; public class ChocolateChip extends Cookie { public ChocolateChip() { System.out.println("ChocolateChip constructor"); } public static void main(String[] args) { ChocolateChip x = new ChocolateChip(); x.bite(); // Can access bite } }
例:class Tom{ public String name; private float wage; int age;…………} class Jerry{ void g() { Tom cat=new Tom(); cat.name=“jitty”;//合法// cat.wage=4300.00f;//不合法// cat.age=34;//若Tom和Jerry的 在同一包中是合法的// 方法和变量是一样的
访问控制符总结 同一个类中 子类 同一个包中 不同包中 Public √ Protected √(*) Private friendly
SmallBrain x = new SmallBrain(); void f() {} } 二. 与继承相关的修饰符 1. final—可用于变量、方法和类的说明 A.如果类的定义上有final修饰,那么,这个类就是不可扩展,即不能有子类的。 例: class SmallBrain { } final class Dinosaur { int i = 7; int j = 1; SmallBrain x = new SmallBrain(); void f() {} }
public class Jurassic { public static void main(String[] args) { class Further extends Dinosaur { }//error! public class Jurassic { public static void main(String[] args) { Dinosaur n = new Dinosaur();//ok n.f(); n.i = 40; n.j++; } }
B.如果方法定义的前面用final修饰,那么子类就不能重写该方法 c.如果变量定义前面用final 修饰,就定义了一个不可再次更改的量 private final int Max=100; Final变量的赋值只能在构造方法或者声明的时候进行,只能赋值一次 如果一个变量被说明成static和final的,那它将有一块无法改变的存贮空间,定义了一个常量
//正确 //错误 //定义了一个常量 //错误 //错误 Class FinalExample{ Static final int a; Static final int b; public static final TOTAL=10; Public FinalExample(int a) { this.a=10; } Public static void main(String[] args){ FinalExample example=new FinalExample(1); Example.a=10; Example.b=1; } } //正确 //错误 //定义了一个常量 //错误 //错误
2.abstract--抽象类和方法 从下往上看继承图时,越往上,类变得更通用,也更抽象 通常把祖先类看作是其它类的基础,而不是一个需要使用它的几个实例的类 Class Human {float hight,weight; String name,sex, id; void speak(String x, String y, String z) {name=x;sex=y;id=z; System.out.println(name +sex+ id); } abstract void speak(String x, String y, String z) { }
一个具有一个或多个抽象方法的类,必须被说明成abstract Abstract Class Human abstract类不能创建对象,只能产生子类,再由其子类创建对象,且子类必须实现父类的abstract方法 abstract方法,只能声明,不能实现 抽象方法实际上就是接口 抽象类里除抽象方法以外,也可以有具体的数据和方法
3.6 接口 1。接口定义 Java不支持多继承性,即一个类只能有一个父类。为了克服单继承的缺点,Java使用了接口,一个类可以使用多个接口。 接口的声明: interface 接口名 例:interface printable {….. }
接口不是类,而是对符合接口需求的类的一套规范 2。接口体 接口体中包含常量定义和方法定义 接口中只进行方法的声明,不提供方法的实现。如: interface printable {int final max=100; void add(); float sum(float x,float y); } 接口不是类,而是对符合接口需求的类的一套规范
3。接口的使用 在类声明时用implements关键字声明使用一个或多个接口 class A implements Printable {………………. } 一个类使用了某个接口,那么这个类必须实现该接口的所有方法,即为这些方法提供方法体 例:
class A implements Printable {………………. void add() {………. } float sum(float x,float y) {……….. } ……………… }
在下一章介绍的事件驱动编程中,对发生事件的响应就是通过使用接口来实现的 主要用法: 在下一章介绍的事件驱动编程中,对发生事件的响应就是通过使用接口来实现的 例:public class InterfaceTest implements ActionListener {Button button=new Button(); ……. button.addActionListener(this) …… public void actionPerformed (ActionEvent e) {………..} }