Java 继承
本质:某一批类的抽象,从而实现对现实世界更好的建模
Java中类只有单继承,没有多继承
子类是父类的扩展
在中,所有的类都默认直接或者间接继承object
//Person 人:父类
public class Person {
//public
//protected
//default int money = 10_000_000;
//private 不可子类继承
public int money = 10_000_000;
public void say(){
System.out.println("说了一句话");
}
}
//学生 is 人 :派生类/子类
//子类继承父类,就会拥有父类的全部方法!
public class Student extends Person {
//ctr + h
}
ublic class Application {
public static void main(String[] args) {
Student student = new Student();
student.say();
System.out.println(student.money);
}
}
super详解
1. 案例一
父类
//Person 人:父类
public class Person {
protected String name = "lqy";
}
子类
//学生 is 人 :派生类/子类
//子类继承父类,就会拥有父类的全部方法!
public class Student extends Person {
private String name = "骆";
public void test(String name){
System.out.println(name);
System.out.println(this.name);
System.out.println(super.name);
}
}
测试
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.test("lll");
}
}
输出
lll
骆
lqy
2. 案例二
super注意点
- super调用父类的构造方法,必须在构造器第一个调用
- super必须只能出现在子类的方法或构造方法中
- super 和 this 不能同时在调用构造方法
super vs this
- 代表的对象不同:
super:代表调用者的这个对象
this:代表父类对象的应用
前提
this:没有继承也能用
super:只能在继承条件能用
构造方法
this();
super();
方法的重写
重写都是方法的重写,和属性无关
重写只和非静态方法有关
父类
public class B {
public void test(){
System.out.println("B==>test");
}
}
子类
public class A extends B {
public void test(){
System.out.println("A==>test");
}
}
测试结果
public class Application {
//静态方法和非静态方法有很大区别
public static void main(String[] args) {
//方法的调用只和左边有关,即定义的数据类型
A a = new A();
a.test();
//父类的引用指向了子类
B b = new A();
b.test();
}
}
输出
A==>test
A==>test
重写注意点:
- 需要有继承关系,子类重写父类的方法
- 方法名必须相同,参数列表必须同
- 修饰符:子类范围可以扩大,但不能缩小: public>Protected>Default>private
- 抛出异常:范围可以缩小,但不能扩大:ClassNotFounfException—> Exception (大)
- 子类方法和父类一致,但方法体可不同
为什么要重写?
- 父类的功能,子类不一定需要或满足
- 快捷键:ale+Insert—>override
多态
可以实现动态编译(可扩展性)
父类
public class Person {
public void run(){
System.out.println("run");
}
}
子类
public class Student extends Person {
@Override
public void run() {
System.out.println("run1");
}
public void eat(){
System.out.println("eat!");
}
}
测试
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Student();
//new Person();
//可以指向的引用类型不确定:父类的引用指向子类
//Student是子类,所以能调用的方法是自己的或者是继承父类的
Student s1 = new Student();
//Person 是父类,可以指向子类,但不能调用子类独有的方法
Person s2 = new Student();
Object s3 = new Student();
s1.eat();//子类重写了父类的方法,执行子类的方法
s2.run();
}
}
输出
eat!
run1
多态注意点
- 是方法的多态,属性没多态
- 子类和父类有联系,类型转换异常 ClassCastException
- 存在条件:继承关系,方法需要重写,父类的引用指向子类对象如上面代码中的Person s2 = new Student();
- 当父类和子类有一样的方法时(方法体不同),结果会调用子类
- 不能重写的方法(即没有多态):static 是属性类的,不属于实例
final 常量
private 方法
类型转换 instanceof
作用:引用类型,判断一个对象是什么类型(判断两类是否存在父子关系)
public class Application {
public static void main(String[] args) {
//Object > Person > Student
//Object > Person > Teacher
//Object > String
Object obj = new Student();//obj实例化Student
System.out.println(obj instanceof Student);true
System.out.println(obj instanceof Person);//true
System.out.println(obj instanceof Object);//true
System.out.println(obj instanceof Teacher);//false
System.out.println(obj instanceof String);//false
System.out.println("=========================");
Person person = new Student();
System.out.println(person instanceof Student);//true
System.out.println(person instanceof Person);//true
System.out.println(person instanceof Object);//true
System.out.println(person instanceof Teacher);//false
//System.out.println(operson instanceof String); 编译报错
System.out.println("=========================");
Student student = new Student();
System.out.println(student instanceof Student);//true
System.out.println(student instanceof Person);//true
System.out.println(student instanceof Object);//true
//System.out.println(student instanceof Teacher);//编译报错
//System.out.println(student instanceof String); 编译报错
}
}
案例:
父类转子类(高转低)
父类
public class Person {
public void run(){
System.out.println("run");
}
}
子类
public class Student extends Person {
public void go(){
System.out.println("go");
}
}
测试
public class Application {
public static void main(String[] args) {
//类型之间的转换: 父(高) 子(低),高转低要强制转换
//高 低
Person obj = new Student();
//将obj这个类型转换为Student类型,就能用Student类型的方法
((Student) obj).go();
}
}
输出
go
注意点
- 父类引用指向子类
- 子类转父类,向上转型,可能会丢失一些方法
- 父类转子类,向下转型,需要强制转换
- 方便方法的调用,减少重复代码