继承
- 继承是面向对象编程的三大特征之一,是一种基于已有类来创建新类的机制。由继承而得到的类称为子类(或派生类),被继承的类称为父类(或超类)。
- Java中每个类只允许有一个父类。语法如下:class <子类> extends <父类>
- Object类是所有类的直接父类或间接父类。
- 根据访问权限修饰符的不同,子类可以继承父类中某些成员变量和方法,提高了代码的重用性,子类也可以添加新的成员变量和方法 :
public class Son extends Father {
public static void main(String[] args){
Son son = new Son();
son.name="Tom";
son.test(son.name);
}
}
public class Father {
private String id;
public String name;
public void test(String name){
System.out.println(name+":父类方法");
}
private void test(){
System.out.println(name+":父类方法");
}
}
执行Son中的main方法:
Tom:父类方法
尽管Son中没有name属性,或是test方法,但是继承了Father类,Father类中有name和test,且为public修饰,所以可以使用。
直接调用父类私有方法会报错。
- 如果类被final修饰,则该类不能被继承:
- Java中已有的类(诸如Void、String、Class、Scanner、System、8种基本数据类型对应包装类等类)已经被final修饰,所以这些类不能被继承。
- 如果父类有无参构造方法(不管是隐式还是显式),那么在子类在调用自己的构造方法时,若此方法没有指定调用父类的哪一个构造方法或是调用哪一个子类的构造方法,则该子类构造方法会隐式调用父类无参构造方法。
public class Son extends Father {
public static void main(String[] args){
new Son();
}
}
public class Father {
Father(){
System.out.println("父类无参构造方法");
}
}
执行结果:
父类无参构造方法
- 如果父类没有无参构造方法(无论隐式的还是显式的),则要求子类构造方法必须直接或间接指定调用父类哪个构造方法并且放在有效代码第一行。
- 当子类中的新的成员变量与父类中的成员变量同名时,在子类中就不能直接使用父类的成员变量,必须使用super。
public class Father {
String name = "father";
}
public class Son extends Father {
String name = "son";
public void getName(){
System.out.println(name);
System.out.println(super.name);
}
public static void main(String[] args){
new Son().getName();
}
}
执行结果:
son
father
多态
有如下场景:
public class Father {
public void eat(){
System.out.println("父亲用筷子吃饭");
}
}
public class Daughter extends Father {
public void eat(){
System.out.println("女儿用刀叉吃饭");
}
}
public class Son extends Father {
public void eat(){
System.out.println("儿子用勺子吃饭");
}
}
测试代码:
public class Test {
public static void main(String[] args){
Father obj1 = new Son();
Father obj2 = new Daughter();
obj1.eat();
obj2.eat();
}
}
执行结果:
儿子用勺子吃饭
女儿用刀叉吃饭
- 父类类型的变量obj1 指向子类创建的对象new Son(),使用该变量调用父类中一个被子类重写的方法(比如eat方法),则父类中的方法呈现出不同的行为特征,这就是多态。
- Java引用变量有两种类型,分别是编译时类型和运行时类型:编译时类型由声明该变量时使用的类型决定;运行时类型由实际赋给该变量的对象。如果编译时类型和运行时类型不一致,就可能出现所谓多态。
- 如果子类没有重写父类的方法,那么子类调用的还是父类的方法,此时没有出现多态。
上转型对象
发生多态一般会有上传型对象存在,例如上面的Father obj1 = new Son();obj1就是一个上传型对象。
- 上转型对象不能操作子类新增的成员变量;不能调用子类新增的方法
//在Son类中添加方法,和属性
public class Son extends Father {
String name;
public void eat(){
System.out.println("儿子用勺子吃饭");
}
public void study(){
System.out.println("学习");
}
}
- 使用上转型对象调用成员变量,无论该成员变量是否已经被子类覆盖,使用的都是父类中的成员变量:
public class Father {
String name= "父亲";
}
public class Son extends Father {
String name = "儿子";
}
public class Test {
public static void main(String[] args){
Father obj1 = new Son();
System.out.println(obj1.name);
}
}
执行结果:
父亲
- 可以将上转型对象再强制转换为创建该对象的子类类型的对象,即将上转型对象还原为子类对象,对应于数据类型转换中的强制类型转换。
- 还原后的对象又具备了子类所有属性和功能,即可以操作子类中继承或新增的成员变量,可以调用子类中继承或新增的方法。
注意:不可以将父类创建的对象通过强制类型转换赋值给子类声明的变量。