2、继承
1. 继承
- 关键字 extends
- Java中只有单继承
- final修饰的类无法被继承
- 静态方法(类方法)不能被继承,静态成员不能被子类访问
- 子类可以创建新的方法,父类无法调用
- 子类在被加载前父类先被加载,也就是子类构造时父类先被构造了
2. 修饰符和使用技巧
| 同一个类内 | 同包不同类 | 不同包子类 | 不同包非子类 | |
|---|---|---|---|---|
| public | √ | √ | √ | √ |
| protected | √ | √ | √ | × |
| 默认 | √ | √ | × | × |
| private | √ | × | × | × |
- 凡是打算让子类继承的成员和方法,都用protected修饰
- 不打算让包外引用的成员和方法,不写任何修饰符
3. 构造方法的执行顺序
JVM对于有继承关系的类的构造方法,先从当前类开始,根据继承关系,追溯到最开始的祖先类,然后再沿着继承关系向下,逐个执行构造方法。子类的所有构造方法都会默认执行父类无参构造方法,如果父类不存在无参构造,则需要我们自己调用其它构造方法
public class Son extends Father {
public Son(){
//这句话是执行父类的无参构造方法,实际上默认是存在的,可以不写,但是如果父类没有无参构造方法,就需要我们自己写上去并且调用相应的构造方法,比如:super(1,1)双参构造
super();
}
}
注意:super();语句必须是构造方法的第一句,且其只能出现在构造方法中。
4. 成员的覆盖语法和规则
父类:
public class Parent {
public int i = 0;
public Parent() {
}
}
在子类中调用i:

我们发现这个i此时是父类的i
当我们在子类中定义同名i时:

我们发现此时的i变成了当前类的i
其实父类中用int定义的i只是被隐藏了,我们想要去调用它可以用super.i

这时的两个i分别是子类和父类的
当我们再建一个新类Me去继承Son类

我们发现此时Parent类中被隐藏的i出现了,因为Son类中的i是private的,无法被继承,那么我们的Me会自动寻找更高层是否有存在的可继承的同名属性(i)
5. 方法的重写——主要的覆盖手段
- 方法覆盖只存在于有继承关系的类之间
- 子类中覆盖父类方法的方法里,返回值类型,方法名,参数列表必须相同,否则,若方法名相同其他的不完全相同,就是方法重载
- 子类方法修饰符不能低于父类方法(否则重写的意义何在,我们调用时会调用不到它)
5.1 重写和重载的区别
区别:
-
重载实现的是编译时的多态性,而重写实现的是运行时的多态性。
-
重载发生在一个类中,同名的方法的参数列表要不同;而重写发生在子类与父类之间,重写方法的重写方法要相同。
-
重载方法的返回类型可以修改,而重写方法不能。
-
重载方法的异常可以修改,重写方法的异常可以减少或删除,一定不能抛出新的或者更广的异常。
-
重载方法的访问可以修改,而重写方法的访问一定不能做更严格的限制
6. 基类与派生类之间的强制类型转换
public class Parent {
public int i = 0;
public Parent() {
}
void hello() {
System.out.println("I am father");
}
}
public class Son extends Parent {
private double i = 0;
public Son() {
}
void hello() {
System.out.println("I am son");
}
}
public class Test {
public static void main(String[] args) {
Son son = new Son();
Parent parent = (Parent)son;
parent.hello();
Parent parent2 = new Son();
parent2.hello();
}
}
输出结果:

对象类型约束对象所能引用的成员和方法,但是不能更改成员和方法的本质内容;对于方法,强转不能改变其所实际指向的代码的首地址(son.hello()这个方法本质上指向的是Son这个类里面定义的hello方法,即使改变了其类型,方法指向不变,所以运行的代码是Son里面的代码,并非Parent)
注意:基类对象无法强转为派生的,JVM会在运行时报错,原因自己想
7. 重写toString()方法
诸如System.out.println()等方法,其在对非八大基本类型的对象处理时,对自动调用对象里面的toString方法,就拿这个方法举例:
System.out.println(cat) 等价于 System.out.println(cat.toString())
所以我们在覆盖toString()方法后,就能实现我们要的输出或者其他操作了,若我们不覆盖,JVM会自动调用默认的toString()方法,就是 ''类类型全程@首地址'' 字符串的样式
8. 重写equals()方法
8.1 对象比较方式
八大基本类型外的类对象的比较有两种方式:
-
用 == 比较
==在Java中比较的是对象首地址
-
对象1.equals(对象2)的方法比较
默认实现也是比较对象首地址,我们可以重写这个方法
8.2 重写步骤
-
判断条件是否是null,return false
-
是否为同一个对象(指的是自己,比如:a.equals(a)),return true
-
是否为除了这两个之外的其他类,return false
-
然后再将参数里面的obj强转为我们当前类
-
return 比较条件
比如:
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Son other = (Son) obj;
return Double.doubleToLongBits(i) == Double.doubleToLongBits(other.i);
}
9. final关键字
- 修饰类,这个类不允许被继承
- 修饰方法,这个方法不能被子类重写
- 修饰成员,让成员的空间变为''只读'',即“常变量”

浙公网安备 33010602011771号