修饰类——类不能被继承
修饰变量——变量就变成了常量,只能被赋值一次
修饰方法——方法不能被重写
详解:
1).用final修饰的实例变量,保存在堆中,在定义时被初始化,不能被修改;用final修饰的静态变量,存储在方法区中,不能被修改
2).用final修饰的实例方法,不能被子类重写,可以被子类对象调用
3).final修饰的类不能被继承(所谓断子绝孙了)
4).final修饰局部变量,一旦被初始化后,就不能修改——包括final修饰的方法的形参
5).final修饰的引用类型的变量,这个引用类型的变量不能再指向其他对象,但是可以修改这个对象的属性值
注意:以前提过静态方法重写的问题:静态方法不存在重写问题,因为静态方法不继承,在不同的类中,可以定义重名的静态方法,在哪个类中定义的,就属于哪个类。(以前学习不深入,就暂记为静态覆盖静态,现在更正了,在以后多态的时候还要讲,注意一下);另外一个:用final修饰静态方法没有意义,如果就是用了final修饰了父类的静态方法,也会约束子类不能定义重名的静态方法
事物存在的多种形态
多态前提:a.要有继承关系 b.要有方法的重写 c.要有父类引用指向子类对象
Animal a = new Cat();
多态中的成员访问特点
①成员变量:
编译看左边(父类),运行看左边(父类)
②成员方法:
编译看左边(父类),运行看右边(子类)
③静态方法:
编译看左边(父类),运行看左边(父类)——静态和类相关,算不上重写,所以还是访问左边
对象转型:
对象向上转型:让父类的引用指向子类的对象
对象向下转型:是对象向上转型的逆操作.先有向上转型才能向下转型
注意:在对象向下转型的时候,要先判断堆中的对象是否为目标对象
引入了instanceof关键字——判断前面的引用是否是后边的数据类型
多态的利弊:
优点:a.提高了代码的维护性(继承保证) b.提高了代码的扩展性(多态保证)——父类作为形式参数,可以接收任意子类对象
缺点:不能使用子类的特有属性和功能
抽象类和抽象方法必须用abstract关键字修饰(变量不可以用abstract修饰)
1)对一组类进一步抽象,可以形成更高层级的类
2)在更高层级的类中,有的操作没法具体实现,这个操作就可以定义为抽象方法
3)含有抽象方法的类必须是抽象类
4)抽象类中不一定有抽象方法
5)子类继承了抽象类,就需要重写抽象类的抽象方法;如果子类没有重写父类的抽象方法,子类也需要定义为抽象类
6)抽象类也是Java的引用数据类型,可以定义变量,抽象类不能实例化对象,定义的引用变量可以指向子类对象
7)普通类中定义的成员都可以在抽象类中定义
8)抽象类的应用场景
(1)抽象类作为父类,描述类与类之间的关系
(2)抽象类中可以定义抽象方法,约束所有的子类都必须重写这个抽象方法
补充:abstract不能和static , private ,final共同修饰同一个
A.现实生活中的接口:USB接口 插座接口 ... ——接口就是一个标准,一个协议,一个规范,对外提供的规则
JAVA的角度就是指JAVA中的interface
B.接口的特点:
(1)接囗用关键字 interface表示,接口中所有的方法都是抽象的
interface 接口名 { }
(2)类实现接口用 implements表示
class 类名 implements 接口名 {}
(3)接囗不能实例化——因为调用抽象方法没有意义
按照多态的方式来实例化。
(4)接口的子类
①可以是抽象类。但是意义不大
②可以是具体类。要重写接口中的所有抽象方法。(推荐方案)
C.接口中成员的特点
成员变量:只能是常量,并且是静态公共的
默认修饰符:public static final——建议自己手动给出,三个修饰符可以换位置
构造方法:接口中没有构造方法
成员方法:只能是抽象方法,没有非抽象方法
默认修饰符:public abstract
建议:自己手动给出
D.类与类,类与接口,接口与接口的关系
a:类与类:继承关系,只能单继承,可以多层继承
b:类与接口:实现关系,可以单实现,也可以多实现,并且还可以在继承一个类的同时实现多个接口
c:接口与接口:继承关系,可以单继承,也可以多继承。
相同点:
(1)都可以有抽象方法
(2)都不能实例化对象
(3)都可以含有静态成员
不同点:
A:含义不同:
抽象类用于表示其他类的父类;接口是一个功能的封装,一个标准
B:定义方法不同
抽象类用abstract class定义;接口用interface定义
C:成员区别
抽象类:
成员变量:可以变量,也可以常量
构造方法:有
成员方法:可以抽象,也可以非抽象
接囗:
成员变量:只可以常量
构造方法:无
成员方法:只可以抽象
D:关系区别
类与类——继承,单继承
类与接囗——实现,单实现,多实现
接囗与接口——继承,单继承,多继承
E:设计理念区别
抽象类 被继承体现的是:"is a"的关系。抽象关中定义的是该继承体系的共性功能
接口 被实现体现的是:"like a"的关系。接口中定义的是该继承体系的扩展功能
访问权限修饰符 | 当前类 | 当前包 | 子类 | 任意位置 |
private | 可以 | 不 | 不 | 不 |
default(默认) | 可以 | 可以 | 不 | 不 |
protected(受保护的) | 可以 | 可以 | 可以 | 不 |
public | 可以 | 可以 | 可以 | 可以 |
在一个类的内部还可以定义另外一个类,这就是内部类
内部类访问特点:
a.内部类可以直接访问外部类的成员,包括私有的——内部类之所以能获得外部类的成员,是因为内部类能获取到外部类的引用:外部类名.this
b.外部类要访问内部类的成员,必须创建对象
外部类名.内部类名 对象名 = 外部类对象.内部类对象;
Outer.Inner oi = new Outer().new Inner();
静态成员内部类的创建:
外部类名.内部类名 对象名 = 外部类名.内部类对象;
Outer.Inner oi = new Outer.Inner();
c.局部内部类——在方法中定义的内部类
注意:局部内部类访问局部变量必须用final修饰
因为当调用这个方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周期是一样的,当方法弹栈,这个局部变量也会消失,那么如果局部内部类对象还没有马上消失想用这个局部变量,就没有了;如果用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也可以继续使用。
但是jdk1.8取消了这个事情.......
c.匿名内部类——内部类使用一次,可以使用匿名内部类,就是没有名字的内部类,简写
匿名内部类的定义和匿名内部类对象的创建是在一起的——经常用于给抽象引用或接口引用赋值
匿名内部类当作参数传递本质是把匿名内部类看作一个对象
如果抽象类或者接口中有两个或两个以上需要重写的方法时,最好不用匿名内部类,太麻烦
new 接口名或抽象类名(){
需要重写的方法;
};