继承
为什么要使用继承?
多个在业务中相类似的类 , 有共同的属性与功能,可以将指这些属性与功能 封装 到 一个公共的类中,该类就是父类
其他的类 中的属性与功能 从父类中继承过来,这样 大大减少了 代码的冗余性。
语法
class A{}
class B extends A{}
Java是单继承,即 只有一个直接父类
Object 是所有类的超级父类,根类,基类
父类所有的属性与方法 是不是 都能被子类继承?
不是,需要看访问权限
class A{
private int x; // x 不能被子类继承,x 只能被 本类A 访问
public int y; // y 被子类继承,因为 y的访问权限是public
public void fun1(){} // 能被子类继承
private void fun2(){} //不能被子类继承
}
class B extends A{
//继承了A 中的 y成员变量
//继承了A 中的 fun1成员方法
}
创建子类对象
class A{
public A(){
System.ou.println("A 父类的 无参构造函数")
}
}
class B extends A{
public B(){
super(); //默认隐藏 调用父类的无参构造函数 A()
System.ou.println("B 子类的 无参构造函数")
}
}
//测试类
public class Test{
public static void main(String[] args){
new B();
}
/*
1. new : 在堆中开辟一块内存【创建对象】
2. B(){} : (1) 初始化属性
(2)执行构造函数方法体
*/
}
构造函数 Constructor(构造方法,构造器)
(1). 构造函数的作用:可以用于给对象进行初始化。
当一个类中没有定义构造函数时,那么系统会默认给该类加入一个无参的构造函数。
当在类中自定义了有参构造函数后,默认的构造函数就没有了。
如需还要使用无参构造函数,必须显式的定义出来。
(2)构造函数必须与类同名
(3)创建对象的粗略过程如下
a、分配对象空间,并将对象中成员初始化为0或者null等,java不允许用户操纵一个不定值的对象。
b、初始化属性
c、执行构造函数方法体
d、将对象名指向堆内存中
-
super 关键字
-
super :父类对象
-
this : 当前对象
-
继承与构造函数
//父类
class Father{
public Father(){}
public Father(String name,int age){…}
}//子类
class Son exetnds Father{
public Son(){
super();//默认访问父类 无参构造函数
}public Son(String name){ super();//默认访问父类 无参构造函数 } public Son(String name,int age){ super(name,age); }
}
/*
总结:
1. 子类的构造函数中 默认会调用父类 无参构造函数 super();
2. 在子类构造函数中 访问 父类构造函数 super(…), 这行代码必须放在第一行*/
访问权限
public : 公共的,其他类都能访问
prviate : 私有的,只有本类能访问
缺省: 只有本包能访问
protected: 只有本包能访问,还有不同包中的子类
final
1. final 修饰变量:常量,值不能改变
2. final 修饰类: 最终类,不能有子类(太监类)
防止该类的属性或方法 被别的类继承
3. final修饰方法:最终方法,方法不能被子类重写(防止方法被子类重写)
方法的重写 override
在继承关系中,子类继承过来的方法,子类向表现的内部实现 与父类不一样,就需要重写
class User{
//看视频
public void watchVideo(){
//具体实现看视频功能
}
//签到
public void checkIn(){
}
}
class NormalUser extends User{
}
class Vip extends User{
//为了与父类 看视频功能 不一样的实现,重新实现看视频
public void watchVideo(){
//内部实现与父类不一样
}
}
instanceof
dog instanceof Dog
// dog 对象 是不是Dog 类型
//等价于 Dog xx = dog;
多态
//1. 父类引用子类对象
//2. 子类重写父类方法
/***********************************父类 引用 子类对象******************************/
class Pet{}
class Dog extends Pet{}
Pet pet = new Dog(); // 父类 引用子类对象
Dog dog = new Dog();
Dog dog2 = (Dog)pet;// OK , pet 真正在内存中 是Dog
Pet pet1 = new Pet();
Dog dog3 = (Dog)pet1; // 错误的 ClassCastException
为了避免ClassCastException,一般在 父类转换成子类对象前,都要用instanceof 判断
if(pet1 instanceof Dog){
Dog dog3 = (Dog)pet1;
}
/**
子类 或 父类 = new 子类();
子类类型 = new 父类(); 错误
父类 引用子类对象
父类对象 强制类型 转换成 子类类型前,一定要用 instanceof 判断,避免ClassCastException
*/
/*************************************多态*************************************/
public class User{
public void watchVideo(){
System.out.println("user在看视频");
}
}
public class Vip extends User{
//重写
public void watchVideo(){
System.out.println("vip在看视频");
}
}
//1. 父类引用子类对象
//2. 子类重写父类方法
User userVip = new Vip();
userVip.watchVideo(); // 运行的是 子类的方法