使用接口时,需要注意的以下事项:
-
接口没有静态代码块没有构造方法
-
一个类只能继承一个父类,但是可以实现多个接口
一个接口可以继承多个接口,类与类之间是单继承关系,类与接口之间是一种多实现关系
-
如果一个类实现了多个接口,出现了重名的抽象方法,只需要重写一次抽象方法
-
如果一个类没有重写接口的所有抽象方法,该类必须是抽象类
-
如果一个类实现了多个接口,接口当中存在有重名的默认方法,那么实现类一定要对冲突的默认方法进行重写
-
如果一个类直接继承了一个父类,又实现了多个接口,父类当中的成员方法和接口中的默认方法存在重名,优先调用父类中的成员方法
今日内容
-
多态
-
final
-
权限修饰符
-
内部类
多态
概述:多态是继封装、继承之后面向对象的第三大特性
定义:多态是指同一行为,具有多种不同的表现形式。即同一行为,通过不同的事物,表现出不同的状态。
前提:
- 继承或实现【二选一】
- 出现父类的引用指向子类对象【格式体现】
- 方法的重写【不重写无实际意义】
多态的表现
格式:
父类类型 变量名 = new 子类对象;
变量名.方法名();
备注:父类类型指的是子类对象继承的父类类型,或者是实现的父接口类型
public class Fu{
public void method(){
System.out.println("这是父类的method方法!!!");
}
}
public class Zi extends Fu{ //1.继承
@Override
public void method(){
System.out.println("这是子类的method方法!!!"); //2.重写
}
}
public class PolymorphismTest{
public static void main(String [] args){
//父类引用指向子类对象 //3.父类引用指向子类对象
Fu fu = new Zi();
fu.method();//调用的是子类重写后的方法
}
}
如果在使用多态方式调用方法时,首先检查父类当中是否有该方法,如果没有则编译报错
如果有,执行的是子类重写后的方法
多态的优点
在实际开发中,父类类型作为放啊的形式参数,传递子类对象给方法,进行方法的调用,更能体现出多态的扩展性和便利性。
public abstract class Animal{
public abstract void eat();
}
public class Dog extends Animal{
@Override
public void eat(){
System.out.println("啃骨头"); //重写
}
}
public class Cat extends Animal{
@Override
public void eat(){
System.out.println("吃鱼"); //重写
}
}
//测试类
public class PolymorphismTest{
public static void main(String [] args){
//根据不同的对象表现不同的eat()内容
Animal animal1 = new Cat();
Animal animal2 = new Dog();// 编左运右
show(animal1);
show(animal2);
}
public static void show(Animal animal){
animal.eat();
}
}
说明:用于多态特性的支持,show方法中的形式参数Animal类型,是Dog和Cat的父类型,父类类型接受子类对象,可以把cat对象和dog对象传递给方法
当程序执行过程中,执行eat()方法实际执行的是各自子类对象重写之后的eat方法,不仅仅可以做到替代,在扩展性方面,无论之后出现多少个子类,都可以使用show方法。
(多态下)访问父类中成员变量有两种方式:
- 直接通过对象名访问成员变量:看等号左边是谁,优先用谁,如果没有,继续往上找
- 间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,如果没有,继续往上找
//定义父类
public class Fu{
int num = 10;
public void showNum(){
System.out.println(num);
}
}
public class Zi extends Fu{
int num = 20;
public void showNum(){
System.out.println(num);
}
}
public class PolymorphismTest{
public static void main(String [] args){
Fu fu = new Zi();
System.out.println(fu.num);//10 编左运左
fu.showNum();// 20
}
调用属性:编左运左
调用方法:编左运右
向上转型一定是安全的、正确的,但有一个弊端:无法调用子类特有内容。由此需要向下转型
引用数据类型的转型问题
-
向上转型:
多态本身就是子类类型向父类类型向上转型的过程,这个过程是默认的
当一个父类引用指向子类对象,便是向上转型。
父类类型 变量名 = new 子类类型();
-
向下转型:
父类类型向子类类型向下转换的过程,这个过程是强制的。
一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制转换格式,便是向下转型
子类类型 变量名 = (子类类型) 父类变量名;
转型的异常
在进行向下转换的过程中,一不小心就会出现 java.lang.ClassCastException类型转换异常。
为了避免这种类型转换异常的发生,java提供了 instanceof关键字,给引用变量做类型转换校验
变量名 instanceof 数据类型
如果变量属于该数据类型,则返回true
如果变量不属于该数据类型,则返回false
所以,我们在类型转换前,最好进行引用变量的类型判断
public class Test{
public static void main(String []args){
//向上转型
Animal animal = new Cat();
//向下转型
if(animal instanceof Cat){
//表明你就是一只猫
Cat cat = (Cat)animal;
cat.eat();
cat.catchMouse();
}else if(animal instanceof Dog){
//表明你就是一只狗
Dog dog = (Dog)animal;
dog.lookDoor();
}else{
//...
}
}
}
学习目标:
- final
- 权限修饰符
- 内部类
- 引用类型
final :最终的、不可改变的
常见的四种用法:
-
可以修饰一个类
public final class 类名称 { }
特点:当前这个类不能有任何子类,这个类依然拥有父类。
如果一个类是final的,那么其中的所有成员方法都无法被重写(无子类)
-
可以修饰一个方法
当方法被final修饰,它是一个最终的方法,不能被覆盖重写。
修饰符 final 返回值类型 方法名称(参数列表){ }
注意事项:对于类、方法来说,abstract关键字和final关键字矛盾, 不可同时使用
-
可以修饰一个局部变量
一旦赋值,不可更改
对于基本数据类型,不变的是变量中的数据值 final int n = 1999;
对于引用数据类型,不变的是变量中的内存地址值,内容值可以变化 final Person p = new Person();
-
可以修饰一个成员变量
对于成员变量来说,如果使用final关键字修饰,那么这个变量也是不可改变的
①由于成员变量具有默认值,使用final后【必须】手动赋值,不再有默认值
②由于final的成员变量,要么使用直接赋值(包括使用代码块赋值),要么通过构造方法赋值 【二选一】
③必须保证类当中的所有的重载的构造方法,都最终对final成员变量赋值