一、面向对象的特性之二:继承性
1. 为什么使用继承
①提高代码的复用性
②利于维护
③继承让类与类之间产生了关系,可以创建更加特殊的类型(多态)
2. 如何使用继承:
关键字: extends --- "扩展" 明确子类是父类的扩展
class A extends B{}
子类: A 父类(超类、基类、SuperClass):B
3. 通过继承,子类可以“继承”父类中所有的属性(包括私有的)和方法。构造器除外---不会继承,但是可以调用
注意:父类中私有的属性,可以被子类继承,但是因为 private 修饰符的作用子类不能直接访问
若要访问通过公共的 get/set 方法进行访问
4. 继承的注意:
①不能为了简化代码,获取某功能而继承,若要继承两个类之间必须满足一定的所属关系: is a
②Java 只支持单继承,不支持多继承(一个父类可以有多个子类,但是一个子类只能有一个父类)
③Java 支持多层继承
class A{
void test1(){}
void test2(){}
}
class B extends A{
//void test1(){}
//void test2(){}
}
---------------------------------
class A{
void test1(){
//11111111111111
}
}
class B{
void test1(){
//22222222222222
}
}
class C extends A, B{}
C c = new C();
c.test1();
二、方法的重写(方法的覆盖 Override) : 若父类中的方法对于子类来说不适用,子类可以对父类中方法进行重写
前提:要有继承关系
①方法名与参数列表必须相同
②子类重写方法的访问控制修饰符不能小于父类被重写方法的访问控制修饰符 访问控制修饰符要往大了去,其他要往小了去
③子类重写方法的返回值类型可以是父类被重写方法返回值类型的子类(指引用数据类型)
④子类重写的方法所抛出的异常必须和父类抛出的异常类型保持一致或是其子类
否则不构成重写
(通常应用时,使方法签名一模一样)
【面试题】 Overload 和 Override 的区别?
前提:在同一个类中
①方法名必须相同
②参数列表必须不同(参数的类型、参数的个数)
注意:与返回值类型无关
三、super 关键字: 使用方式与 this 关键字几乎一模一样
this : super()
super() 作用:调用父类无参构造器
super() 目的:使用在本类中,代表当前对象的引用
super : 使用在子类中,代表父类对象的引用
super.属性
super.方法
super(……) : 调用父类构造器
①当子类继承父类后,子类“所有”构造器中默认第一行第一句有一个隐式的:当子类继承父类后,就继承了父类中所有的属性,因此子类需要知道父类如何为对象进行初始化
②若父类中没有提供无参构造器,子类“所有”构造器必须显示调用父类的有参构造器
③super() 和 this() 必须使用在构造器的可执行代码的首行
因此,super() 和 this() 不能同时出现
一、四种访问控制修饰符:
private : 私有的,可用于修饰 属性、方法。 只能在本类中访问
default : 默认的(缺省的), 可用于修饰 属性、方法、类。 可以在 本类中、本包中
(注意:default 并不是访问控制修饰符的关键字,在什么都不加的情况下)
protected : 受保护的,可用于修饰 属性、方法。 可以在本类中、本包中、子类中
public : 公共的,可用于修饰 属性、方法、类。 可以在任何地方都能访问
一、多态:一类事物的多种表现形态。 人 -- 男人 女人
1. 多态的体现:①方法的重载与重写 ②对象的多态性
2. 对象的多态性:父类的引用指向子类的对象
Person p = new Man(); //多态
p.eat();
p.walk();
//p.smoking(); 编译? NO
Java 程序的运行分为两种状态:
在多态的情况下,编译时:“看左边”,看的是父类的引用。 (而父类中不具备子类特有的方法)
运行时:“看右边”,看的是子类的对象(实际运行的是子类重写父类的方法)
—————— “虚拟方法调用(动态绑定)”
3. 多态的前提:①要有继承关系 ②要有方法的重写(为了完成虚拟方法调用)
4. 引用数据类型之间的转换:
前提:要有继承关系
①向上转型:子类转父类。 系统自动完成
②向下转型:父类转子类。 需要使用强转符“(需要转换的类型)”
可能引发异常:ClassCastException
Person p = new Man(); //多态-向上转型
p.eat();
p.walk();
Man man = (Man)p; //向下转型
man.smoking(); //强转后可以调用子类特有的方法
Woman woman = (Woman)p; //编译?YES 运行?NO
5. Java 为上述异常提供了相应的解决办法:
instanceof 运算符:
例如:
p instanceof Man : 判断 p 引用指向的对象是不是 Man 的本类类型及 Man 的子类类型,如果是,返回 true
if(p instanceof Woman){
Woman woman = (Woman)p;
}
二、多态的应用
1. 多态数组:
Person[] persons = new Person[5];//多态数组
persons[0] = new Person();
persons[1] = new Man();
persons[2] = new Woman();
for(int i = 0; i < persons.length; i++){
/*Person p = persons[i];
p.eat();
p.walk();*/
persons[i].eat(); //虚拟方法调用
persons[i].walk();
}
for(Person p : persons){//多态:相当于 Person p = new Man()
p.eat(); //虚拟方法调用
p.walk();
}
2. 多态参数:
//需求:展示一个男人吃饭走路的功能
/*public void show(Man man){
man.eat();
man.walk();
}
//需求:展示一个女人吃饭走路的功能
public void show(Woman woman){
woman.eat();
woman.walk();
}*/
public void show(Person p){ //多态参数:调用方法时,可以传递 Person 本类类型的对象及Person 子类类型的对象
p.eat();
p.walk();
}
一、对象的关联:简单的说,一个对象中使用了另一个对象。
class Teacher{
private String name;
private int age;
private Computer computer;
public Teacher(){}
public Teacher(String name, int age, Computer computer){
this.name = name;
this.age = age;
this.computer = computer;
}
public String say(){
return name + "," + age + "," + computer.getDetails();
}
}
class Computer{
String cpu;
String ram;
String hdd;
public Computer(){}
public Computer(String cpu, String ram, String hdd){
this.cpu = cpu;
this.ram = ram;
this.hdd = hdd;
}
public String getDetails(){
return cpu + "," + ram + "," + hdd;
}
}
一、java.lang.Object 类:是所有类的父类。若一个类没有显示的继承任何类时,默认 extends java.lang.Object
java.lang 是默认包
1. 既然 Object 是所有类的父类,因此 Object 类中的内容是最具共性的
2. 既然 Object 是所有类的父类,因此子类可以继承 Object 类中所有的方法
3. 既然 Object 是所有类的父类,若 Object 类中的方法对于子类不适用,子类可以重写 Object 类中的方法
二、
1. “==”运算符:
①基本数据类型:比较两个基本数据类型的值是否相等,相等返回 true
②引用数据类型:比较两个引用数据类型的“地址值”是否相等,相等返回 true
2. public boolean equals(Object obj){}: 比较两个对象是否相等
①在 java.lang.Object 类中
②只能比较两个引用数据类型
③Object 类中的 equals(Object obj) 方法比较的是两个对象的地址值。(通过查看源代码发现,实际上使用 "==" 完成)
④若 Object 类中的 equals() 对于我们来说不适用,我们可以重写。
【面试题】 "==" 与 equals() 的区别?
三、public String toString() : 返回当前对象的字符串表现形式
①在 java.lang.Object 类中
②若直接输出对象的引用,默认调用 toString() 方法
③Object 类中的 toString 返回的格式如下:
getClass.getName() + '@' + Integer.toHexString(hashCode())
④若 Object 类中的 toString() 对于我们来说不适用,我们可以重写。
class Person/* extends java.lang.Object*/{
private String name;
private int age;
public Person(){}
public Person(String name, int age){
this.name = name;
this.age = age;
}
//重写 Object 类的 equals()
public boolean equals(Object obj){
if(this == obj){
return true;
}
if(obj instanceof Person){
Person p = (Person)obj;
if(this.name.equals(p.name) && this.age == p.age){
return true;
}
}
return false;
}
public String toString(){
return "姓名:" + name + " 年龄:" + age;
}
}
Person p1 = new Person("张三", 18);
Person p2 = new Person("张三", 18);
System.out.println(p1.toString());//Person@3fab5
System.out.println(p1); Person@3fab5
System.out.println(p1.equals(p2));//false
一、static 关键字:代表静态的,可用于修饰 属性、方法、代码块、 **内部类
1. static 修饰的属性(静态变量或类变量)
①随着类的加载而加载,随着类的消失而消失(生命周期最长)
②static 修饰的属性可以被该类所有对象所共享
③一旦某个对象修改该属性值,其他对象的该属性值也会随之改变
④静态变量的存在优先于对象
⑤可以通过 "类名.类变量" 的方式调用
2. 类变量和实例变量的区别?
①内存中的位置不同
②生命周期不同
3. static 修饰的方法(静态方法或类方法)
①随着类的加载而加载
②静态方法的存在优先于对象
③可以通过 "类名.类方法" 的方式调用
④静态方法中不能使用非静态成员,非静态方法中可以使用静态成员
⑤静态方法中不能使用 this 和 super
二、类的成员之一:代码块(属性、方法、构造器)
1. 非静态代码块(初始化块):
①格式:类中的一对 {}
②每次创建对象时执行
③非静态代码块的执行优先于构造器
④用于为对象进行初始化。(通常用于为共性内容进行初始化)
⑤非静态代码块可以有多个,依次向下的顺序执行
2. 静态代码块:
①格式: static{}
②随着类的加载而加载,并且只加载一次。
③静态代码块的执行优先于非静态代码块
④静态代码块中不能调用非静态成员
⑤静态代码块可以有多个,依次向下的顺序执行
三、为属性赋初始值的方式
①默认值(缺省值)
②直接显示赋值
③构造器赋值
④代码块
顺序:① ②④ ③
注意:②④顺序执行
四、final 修饰符:代表最终的,可用于修饰 变量、方法、类。
①final 修饰的类不能被继承
②final 修饰的方法不能被重写
③final 修饰的变量叫常量,一旦被赋值,值不能改变。
1)命名规范:所有字母都大写,每个单词之间以 "_" 隔开。 例如: XXX_YYY_ZZZ
2)常量没有默认值,在使用前必须赋值(直接显示赋值、构造器赋值、代码块赋值)
若选择使用构造器赋值,必须保证所有构造器都为常量赋值