继承
关键字:extends
public class Students extends People{}
内存原理:
派生类在堆内存中有子类空间(this)和父类空间(supper)
特点:
一个类只能继承一个父类;
不支持多继承,但支持多层继承;
Java中所有的类但是object的子类;
访问:
私有成员:无法直接访问;
static成员:不可继承,但可共享访问;
在子类中访问成员满足就近原则,因而子类中同名成员会覆盖父类(一定要访问父类成员则使用supper)。
方法重写:
父类的功能不能满足需求时,子类在父类的基础上增加新的方法。
注意事项:
(1)重写方法的名称、形参列表必须与被重写方法的名称和参数列表一致
(2)私有方法不能被重写
(3)子类重写父类方法时,访问权限必须大于或者等于父类(缺省< protected < public)
(4)子类不能重写父类的静态方法,如果重写会报错的
构造器:
子类中全部构造器默认先访问父类的无参构造器,再执行自己;如果父类没有完成初始化,子类将无法使用父类数据;
当父类只有有参构造器,子类对父类进行初始化:
super(name,age);
this和super:
继承练习:
package wryyyyy;
public class test
{
public static void main(String[] args)
{
Dog d = new Dog();
d.run();
}
}
package wryyyyy;
public abstract class Animal
{
public abstract void run();//定义一个animal抽象类
}
package wryyyyy;
public class Dog extends Animal
{
public void run()
{
System.out.println("狗在跑");//重写的成员方法
}
public void lookdoor()
{
System.out.println("狗会看门");//dog独有的
}
}
抽象类
关键字:
abstract
public abstract void run();//不能写方法体
有了抽象方法,类也要被定义为抽象类,class前面加上abstract声明
使用场景:
系统中同一个功能在多处开发,而该功能中只有部分不同。
注意事项:
子类必须重写父类所有抽象方法,否则子类也必须声明为抽象类
抽象类的应用-模板方法:
package wryyyyy;
public class moban
{
public void write()
{
System.out.println("--------------");
System.out.println("===============");
writemain();//这个是需要用户重写的,其他都是模板,不用自己写
System.out.println("+++++++++++++++");
}
private abstract void writemain();
}
接口
关键字:interface
格式:
接口是一种规范,其中常量和抽象方法即使没有public前缀也是默认公开化的
注意:
用idea新建类时,要选第二项interface
接口的用法:
接口是用来被类实现的,实现接口的类称为实现类,实现类相当于子类。
接口可以多实现(而继承不能多继承):
一个类实现接口,必须重写全部接口的抽象方法,否则需定义为抽象类
接口可以多继承:
一个接口可以继承多个接口
接口新增方法:
为防止接口新增方法时导致大量实现类需重写,允许接口中直接定义带有方法体的方法(这样实现类就可以直接获得新增方法,不需要重写)
默认方法(default):其实就是实例方法。默认是public修饰,需要接口的实现类对象来调用
静态方法(static):默认用public修饰,必须用static修饰;
接口的静态方法必须用本身的接口名调用(不同于前面父类方法可以用子类名调用)
私有方法(private):
就是私有的实例方法,必须用private修饰(从JDK9才有的)
只能在本类(本接口)被其他默认方法/私有方法访问
多态
概念:
同类型对象,执行同一行为,表现出不同特征。
成员访问特点:
方法调用:编译看左边,运行看右边
变量调用:编译看右边,运行看右边
(多态侧重行为多态)
多态的前提:
有继承关系;
父类对象引用指向子类对象;
有方法重写;
多态的优势:
多态形式下,右边对象可以实现耦合,便于拓展和维护。
Animal a = new Dog();
a.run();//Dog被切换为其他对象后,业务逻辑不变
多态存在的问题:
多态下不能使用子类独有功能
引用类型的类型转换:
两者有继承/实现关系,编译阶段可强制类型转换;
可以用来解决多态下不能使用子类独有功能:
package wryyyyy;
public abstract class Animal
{
public abstract void run();//定义一个animal抽象类
}
package wryyyyy;
public class Tortoise
{
public void run()
{
System.out.println("乌龟在跑");//重写的成员方法
}
public void pa()
{
System.out.println("乌龟在爬");
}
}
package wryyyyy;
public class Dog extends Animal
{
public void run()
{
System.out.println("狗在跑");//重写的成员方法
}
public void lookdoor()
{
System.out.println("狗会看门");//dog独有的
}
}
package wryyyyy;
public class test
{
public static void main(String[] args)//main方法
{
Animal a1 = new Dog();
a1.run();
// a1.lookdor();//错误,不能访问子类独有成员,应进行类型转换才能访问
Dog d =(Dog)a1;
((Dog) a1).lookdoor();//这样就可以访问了
}
}
子类 对象变量 = (子类)父类类型变量;
强制类型转换出错情况
一个派生类被强制转换为了另一个(如上述案例中dog类被强制转换我tortoise类)
为防止这种情况,强制类型转换前用instanceof判断当前对象真实类型,在进行转换:
if(a2 instanceof Tortoise)
{
Tortoise t = (Tortoise) a2;
t.pa();
}
else if (a2 instanceof Dog)
{
Dog d = new Dog();
d.lookdoor();
}