Java 中继承的特点
- 只支持单继承
- 子类只能继承父类的非私有的成员和方法
- 子类不能继承父类的构造方法,但是可以通过super关键字去访问父类构造方法
this与super的区别
this代表本类对应的引用
super代表父类存储空间的表示
怎么用?
- 调用成员变量
- this.成员变量 调用本类的成员变量
- super.成员变量 调用父类的成员变量
- 调用构造方法
- this(...):调用本类的构造方法
- super(...):调用父类的构造方法
- 调用成员方法
- this.成员方法:调用本类的成员方法
- super.成员方法:调用父类的成员方法
继承中构造方法的关系
子类中所有的构造方法默认都会访问父类中的空参数的构造方法
为什么呢?
- 因为子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化
- 每一个构造方法的第一条语句默认都是:super()
如果父类中没有无参构造方法,该怎么办呢?
- 子类通过super去显示调用父类其他的带参的构造方法
- 一定要注意:
- super(...)或者this(...)必须出现在第一条语句上
- 否则,就会有父类数据的多次初始化
final关键字
final的特点
- final可以修饰类,该类不能被继承
- final可以修饰方法,那么该方法就不能被子类所重写
- final可以修饰变量,该变量不能被重新赋值
被final修饰的变量只能赋值一次
final int num;num = 10或者
final int num = 10;
多态
同一个对象,在不同的时刻体现出来的不同状态
多态的前提:
A:要有继承关系
B:要有方法重写
C:要有父类指向子类对象
父类 f = new 子类()
f调用的方法只能是被子类重写的方法
多态体现在表面上调用父类的方法,其实调用的是子类的方法!
多态的成员访问特点:
A:成员变量
编译看左边,运行看左边
B:构造方法
创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化
C:成员方法
编译看左边,运行看右边
D:静态方法
编译看左边,运行看左边(静态和类相关,算不上重写,所以,访问还是看左边的)
多太的弊端,不能使用子类的新功能(即没有重写的方法)
解决方法:可以借助向下转型
子类 z = (子类)f
class KongZiDad{
int age = 40;
public void teach(){
System.out.println("教Java");
}
}
class KongZi extends KongZiDad{
int age = 20;
public void teach(){
System.out.println("教论语");
}
public void playGame(){
System.out.println("英雄联盟");
}
}
class HelloWorld{
public static void main(String[] args) {
KongZiDad kzd = new KongZi();
System.out.println(kzd.age); // 40
kzd.teach(); // 教论语
// kzd.playGame(); 无法调用
KongZi kz = (KongZi)kzd;
System.out.println(kz.age); // 20
kz.teach(); // 教论语
kz.playGame(); // 英雄联盟
}
}
如何更好的理解多态呢?
多态类的内存图
抽象类
定义了抽象方法的类是抽象类
abstract class Animal{
public abstract void eat();
}
抽象类有构造方法,但抽象类不能实例化。抽象类中的构造方法是子类访问父类的初始化数据。
抽象类的子类问题:
- 抽象类的子类没有重写抽象方法,扔是一个抽象类,不能实例化
- 如果重写了抽象类中的所有抽象方法,就是普通的子类,可以实例化
- 可以通过多态的方式对抽象类进行实例化
抽象类 obj = new 子类()
抽象类的成员
- 成员变量:既可以是变量,也可以是常量
- 成员方法:既可以是抽像的,也可以是非抽像的
- 构造方法:有
接口
格式:interface 接口名 {}
实现:class 类名 implement 接口名 {}
注意:
- 接口不能实例化
- 如果要实例化,按照多态的方式,由具体的子类实例化。其实这也是多态的一种,接口多态
接口的子类: - 要么是抽样类
- 要么重写接口中的所有抽象方法
接口中成员的特点:
- 成员变量默认是 public static final
- 接口没有构造方法(所有类默认继承Object类)
- 成员方法默认是 public abstract
抽象类和接口区别
抽象类:被继承,体现的是“is a”的关系,抽象类中定义的是该继承体系的共性功能
接口:被实现,体现的是“li'ke a”的关系,接口中定义的是该继承体系的扩展功能
类名,抽象类名,接口名做为参数传递问题
1.类名作为形参和返回值类型,跟不同类型一样
2.抽象类名:因为抽象类不能实例化,必须借助多态实现
- 抽象类名作为形参传递
abstract class Person {
public abstract void study();
}
class PersonDemo {
public void method(Person p) {//p; p = new Student(); Person p = new Student(); //多态
p.study();
}
}
//定义一个具体的学生类
class Student extends Person {
public void study() {
System.out.println("Good Good Study,Day Day Up");
}
}
class PersonTest {
public static void main(String[] args) {
//目前是没有办法的使用的
//因为抽象类没有对应的具体类
//那么,我们就应该先定义一个具体类
//需求:我要使用PersonDemo类中的method()方法
PersonDemo pd = new PersonDemo();
Student p = new Student();
pd.method(p);
}
}
- 抽象类名作为返回值类型
abstract class Person {
public abstract void study();
}
class PersonDemo {
public Person getPerson() {
//Person p = new Student();
//return p;
return new Student();
}
}
class Student extends Person {
public void study() {
System.out.println("Good Good Study,Day Day Up");
}
}
class PersonTest {
public static void main(String[] args) {
PersonDemo pd = new PersonDemo();
Person p = pd.getPerson(); //new Student(); Person p = new Student();
p.study();
}
}
3.接口名同上
权限修饰符
权限修饰符:
本类 同一个包下(子类和无关类) 不同包下(子类) 不同包下(无关类)
private Y
默认 Y Y
protected Y Y Y
public Y Y Y Y
修饰符:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
抽象修饰符:abstract
类:
权限修饰符:默认修饰符,public
状态修饰符:final
抽象修饰符:abstract
用的最多的就是:public
成员变量:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
用的最多的就是:private
构造方法:
权限修饰符:private,默认的,protected,public
用的最多的就是:public
成员方法:
权限修饰符:private,默认的,protected,public
状态修饰符:static,final
抽象修饰符:abstract
用的最多的就是:public
除此以外的组合规则:
成员变量:public static final
成员方法:public static
public abstract
public final
内部类
把类定义在其他类的内部,这个类就被称为内部类
内部类的访问特点:
- 内部类可以直接访问外部类的成员,包括私有
- 外部类要访问内部类的成员,必须创建对象
内部类的详细介绍:Java内部类详解
当我们编译的时候,不仅会生成外部类的class文件,还会生成内部类的class文件,格式是外部类名$内部类名.class