继承
this和super
- this - -> 表示本类的对象
- super --> 表示父类的对象
继承常见问题
继承中构造方法的关系
-
子类继承父类,默认加载,调用父类的构造方法(即使使用this.调用构造方法也必须先加载父类) *
- 子类调用父类的过程中,可能使用父类的数据==>子类在初始化的前,先初始化父类
- 子类不能继承父类的无参构造函数,但是可以调用
-
每一个子类构造方法的第一条语句默认都是:super(), Object类最顶层的父类
-
在不同一包下(没有这个前提的话,就报错),只有public修饰的类才能被继承
- (修饰类的关键字public ,default[权限-同一包下],final(无法被继承))
-
在不同一包下(没有这个前提的话,就报错),public,default(不修饰)修饰的类能被继承
继承的初始化–方法一直初始化到object为止
继承中私有的情况
- 属性|方法
- 父类中私有的属性|方法,子类无法访问
继承中的初始化顺序
- 静态优先 父类优先,静态优先 成员变量----构造代码块 ----- 构造方法
-
案例
-
class B extends Object { static { System.out.println("Load B"); } public B() { System.out.println("Create B"); } } class A extends B { static { System.out.println("Load A"); } public A() { System.out.println("Create A"); } } public class Testclass { public static void main(String[] args) { new A(); } }
答案:Load B -> Load A ->Create B ->Create A
extends(继承) 和implements(实现)的区别
- extend是类的继承,每个子类只可以继承一个父类
- implements是接口的实现,每个接口可以实现单继承或多继承
多态
定义
- 一个事物的多种形态
多态的条件(如何判断多态)
- 存在继承关系
- 存在方法 的重写
- 父类引用指向子类的对象
多态出现的两种方法**
- 父类引用子类对象 例:父类 对象=new 子类();
- 实现类实现接口 例:接口 对象=new 实现类();
多态成员访问的特点
1>成员变量
package com.qianfeng.poly;
public class Demo05 {
public static void main(String[] args) {
Computer computer01 = new Computer();
computer01.power();
System.out.println(computer01.name);
System.out.println("====================");
Computer computer02 = new ASUS();//向上转型->子类转父类
// 在多态中,写代码的时候要看父类中是否有这个方法,但是运行的结果是子类重写之后的内容
computer02.power();
// computer02.sleep(); 因为父类中没有sleep方法
// 在多态中,写代码的时候要看父类中有没有这个属性,运行的结果是父类中的属性
System.out.println(computer02.name);
// System.out.println(computer02.type); 因为父类中没有type属性
// 对于静态方法,子类无法重写父类的静态方法,所以编译和运行全是父类的内容
computer02.start();
}
}
class Computer{
String name = "电脑";
int price = 2000;
public void power() {
System.out.println("通过电源键开机");
}
public static void start() {
System.out.println("电脑正在初始化。。。");
}
}
class ASUS extends Computer{
String name = "笔记本电脑";
int price = 3000;
String type = "S700";
@Override
public void power() {
System.out.println("我的电脑可以通过遥控器开机");
}
public void sleep() {
System.out.println("我的电脑有休眠的功能");
}
// 子类无法重写父类的静态方法,所以多态对静态方法没有影响
// @Override
public static void start() {
System.out.println("电脑initing...");
}
}
运行结果
通过电源键开机
电脑
====================
我的电脑可以通过遥控器开机
电脑
电脑正在初始化。。。
2>成员方法
package com.qianfeng.poly;
public class Demo06 {
public static void main(String[] args) {
A a = new B();
a.show();//==a.show2()//爱 a的对象为B
B b = new C();
b.show();//b.show2()//你
}
}
class A {
public void show() {
show2();
}
public void show2() {
System.out.println("我");
}
}
class B extends A {
public void show2() {
System.out.println("爱");
//System.out.println(this.getClass());
}
}
class C extends B {
public void show() {
super.show();
}
public void show2() {
System.out.println("你");
}
}
运行结果
爱
你
总结–在多态的前提下------多态成员访问的特点
-
在多态中,写代码的时候要看 父类 中是否有这个 方法 ,运行的(但是) 结果是子类重写之后的内容
-
在多态中,写代码的时候要看 父类 中有没有这个 属性 ,运行的 结果是父类中的属性
-
在多态中,子类无法重写父类的静态方法,所以多态对静态方法没有影响(使用的是父类的静态方法)
逻辑图
#### 向上转型与向下转型
-
向上按照上述逻辑进行判断 (子类 —> 父类)
-
向下相反,但要主意申请的对象,防止出现java.lang.ClassCastException (类型转换异常, 属于运行时异常)
-
public static void main(String[] args) { // 多态中的向上转型,自动转,不会有风险 // Auto auto = new Car(); // start(auto); //AC //Car car = new Car(); // 传入的对象为子类,car本来就是Car类型的对象,所以强转不会报错 //carryMan(car); //WA // auto2本身不是Car类型(子类),强转会报ClassCastException //Auto auto2 = new Auto(); // carryMan(auto2); } public static void carryMan(Auto auto) { // 向下转型,需要强制转换,有风险 ((Car) auto).carryMan(); } public static void start(Auto auto) { auto.start(); }
多态成员变量方法概述[编译看左边(父类) , 运行看左边(父类) ]
-
当使用多态方式调用方法时,首先检查父类中是否有该方法
-
如果没有,则编译错误;
-
如果有,再去调用子类的同名方法。