多态
-
多态的概念:
小黑是一只狗同时也是一个动物 小黑是一个对象,这个对象既有狗的形态也有动物的形态 这个就是多态
-
使用多态的格式
父类引用指向子类对象 父类名称 对象名 = new 子类名称(参数列表); 接口类 对象名 = new 实现类名称(参数列表);
-
多态访问成员变量
成员变量不存在覆盖重写!!! 访问成员变量的两种方法: 1、使用对象名访问成员变量(对象名.成员变量)(看左边) 创建对象时等号左边是谁就访问谁的成员变量,没有则向上找 2、使用方法访问成员变量时,new的是哪个类的对象就从哪个类中找,没有就向上找
多态中使用“对象名.变量”时:不能查找子类特有的变量:
可以使用子类的方法来获取子类变量:
- 多态访问成员方法
从new的类找,优先用new的类中的方法,没有就向上找
注意:不能使用子类的特有方法,只能使用重写方法和父类及以上的方法
-
多态访问成员变量和成员方法的特点:
1、访问成员变量:编译看左边,运行还看左边 如果编译错误,从等号左边找原因,运行结果也从等号左边找 2、访问成员方法:编译看左边,运行看右边 如果编译错误,从等号左边找原因,运行结果从等号右边找
对象的上下转型
-
对象的向上转型 —— 父类引用指向子类对象(向上类型转换一定是安全的)
其实就是多态的用法(创建一个子类对象,把它当作父类看待 —— 从小范围到大范围) 格式:父类对象 对象名称 = new 子类名称(参数列表); Fruit apple = new Apple(); —— 苹果是一个水果
-
对象的向下转型
向下转型解决的问题: 使用向上转型时,子类被当作父类看待,但是此时不可以用子类特有的方法,如果想用子类特有方法,就必须向下转型成原来的样子 对象的向下转型其实就是一个还原的动作 格式:子类名称 对象名 = (子类名称)父类对象 注意:向上转型时new的是哪个子类,向下还原时就要还原成哪个子类,否则运行报错
instanceof关键字
返回值是boolean值,用于判断父类引用的子类对象是是不是这个子类的(判断这个宠物是不是猫,是不是狗)
final关键字
-
Final关键字可以修饰:
1、类 2、方法 3、局部变量 4、成员变量
-
final关键字的使用
1、修饰类 格式:public final class 类名{...} (1)一旦使用final修饰了类,那么这个类不能有子类,类中的方法不能被重写 (2)final类一定有父类 2、修饰方法 格式:public final 返回值类型 方法名(参数列表){...} (1)一旦用final修饰了方法,那么这个方法不能被覆盖重写 (2)与abstract是相反的,两者不能同时使用 3、修饰局部变量 (1)一旦使用final修饰局部变量,内容不可改变 (2)基本数据类型的不能改变——数据内容不可改变 (3)引用类型的不可改变——地址值不能改变,但是内容可以变 (4)定义时可以不立刻赋值 4、修饰成员变量 (1)一旦使用,内容不可改变 (2)因为创建成员变量时,编译器会赋默认值,所以创建时应该立刻为其赋值
Java的四种权限修饰符
public:同一个类(自己)、同一个包(邻居)、子类(不同包下的子类)、不同包非子类
protect:同一个类(自己)、同一个包(邻居)、子类(不同包下的子类)
private:同一个类(自己)、同一个包(邻居)
private:同一个类(自己)
内部类
内部类:一个类内部中包含了另一个类(例如:人的身体和心脏)
1、成员内部类
2、局部内部类(包含匿名内部类)
-
成员内部类的定义
修饰符 class 外部类名{ 修饰符 class 内部类名{...} } 注意: 1、编译之后的文件——外部类名$内部类名.class 2、内用外——随意,外用内——需要创建内部类对象
-
成员内部类的使用
1、间接法——在外部类的方法中使用内部类,然后在main方法中通过调用外部类对象的外部类方法来使用内部类方法 2、直接法——创建内部类对象 格式:外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称()
-
内部类重名变量的访问
在内部类方法中使用 Outer.this.重名变量名 来访问外部类的重名变量
-
局部内部类
只有在当前方法中才可以使用,出了当前方法就无效了 格式: 修饰符 class 外部类名{ 外部类方法头{ class 内部类名{ ... } } }
类的权限修饰符
1、外部类——public/(default)
2、成员内部类——public/protect/(default)/private
3、局部内部类——什么都不能写,但是不代表时default
局部内部类的final问题
如果局部内部类要访问方法中的局部变量,那么这个局部变量必须是有效final的(可以不用final修饰,但是必须只能被赋值一次)
原因:new出来的内部类对象生命周期比局部变量长,如果局部变量一直在改变,内部类对象再使用此变量的时候不知道它消失的时候是多少
1、new出来的对象在堆内存中
2、方法的局部变量是跟着方法走的,在栈内存中
3、方法调用结束就会被从栈内存中收回,局部变量也就随之消失
4、但是new出来的对象还在堆内存中持续存在
匿名内部类
当接口的实现类或者父类的子类只使用了一次的时候,我们可以不去定义实现类或者子类,而直接使用匿名内部类
格式:
接口类名称 对象名 = new 接口名称(){
//覆盖重写接口中的所有抽象方法}
注意:
1、匿名内部类只能使用一次
2、匿名内部类和匿名对象不是同一个东西