一、设计模型之模板模型
- 定义
- 使用接口制定规则,然后子类根据接口实现不同的方法的内部代码
- 实现类暴露的可用方法必须和接口中的相同
- 案例
- 执行汽车接口,里面规定的是汽车的基本要素
- 子类根据规则,实现不同功能的模板
二、成员内部类
-
定义
- 内部类就是类的内部定义另一个类
- 当一个类中的成员过多的时候,再次对类中的成员进行分组
-
使用
-
内部类可以直接访问外部类的成员,包括私有的
- 外部类名.this.成员
-
外部类调用内部类成员,必须先创建对象
- 内部类 对象 = 内部类对象
- 内部类 对象名 = new内部类()
public class Outer{ //外部类非静态方法 public void outerMethod(){ System.out.println("外部类方法"); //外部类调用内部类方法,必须先创建内部类对象 Inner inner = new Inner(); inner.innerMerthod(); } class Inner{ //内部类非静态方法 public void innerMethod(){ //内部类调用外部类非静态方法 //Outer.this.outerMethod(); //如果没有相同的方法,可以省略前缀 outerMethod(); } } }
-
别的类要访问内部类的成员,就必须创建对象
外部类名.内部类名 对象名 = 外部类对象.内部类对象
-
外部类.内部类. 对象名 = new 外部类().new 内部类()
public static void main(String[] args){ //创建内部类对象,必选先创建外部类对象 Outer.Inner inner = new Outer().new Inner(); //调用内部类的方法 inner.innerMethod(); }
-
-
内部类的权限
- 内部类的权限和成员方法一样,可以有private、默认、protected、public
- 外部类只能是public和默认的
- private效果等同于私有化方法,别的类无法直接调用,但是外部类可以调用,可以通过方法return回去
- 我们完全可以把内部类当做是一个类中的方法看待
- 内部类同时具备方法和类的所有权益
-
演示
public class Outer{ //外部类非静态方法 public void outerMethod(){ //私有的内部类只能在外部类中使用 Inner inner = new Inner(); inner.innerMethod(); } //只能在内部使用 private class Inner{ //内部类非静态方法 public void innerMethod(){ } } } public static void main(String[] args){ //外部类直接调用private修饰的内部类时,会报错 Outer.Inner inner = new Outer().new Inner();//报错 }
-
总结
-
为什么使用成员内部类?
- 当一个类中的成员过多的时候,再次对类中的成员进行分组
-
特性:怎么样创建内部类的对象?
-
外部类对象.内部类对象
Outer.Inner inner = new Outer().new Inner();
-
-
内部类的类名是什么?
-
外部类名.内部类名
Outer.Inner
-
-
-
测试题
判断输出结果
public class Outer{ public void method(){ System.out.println("外部类method方法"); method2(); } public void method2(){ System.out.println("外部类method2方法"); } public class Inner{ public void method(){ System.out.println("内部类method方法"); method2(); } public void method2(){ System.out.println("内部类method2方法"); Outer.this.method2(); } } } public static void main(String[] args){ Outer.Inner inner = new Outer().new Inner(); inner.method(); }
三、静态内部类
-
定义
- 使用static关键字修饰内部类
-
使用
-
调用静态内部类内部的非静态方法
- 外部类名.内部类名 对象名 = new 外部类名.内部类名();
public class Outer { //静态内部类 public static class Inner{ //静态内部类的非静态方法 public void innerMethod(){ } } } public static void main(String[] args) { //创建内部类对象 Outer.Inner inner = new Outer.Inner(); //调用内部类的方法 inner.innerMethod(); }
-
调用静态内部类内部的静态方法
- 外部类名.内部类名.方法()
public class Outer { //静态内部类 public static class Inner{ //静态内部类的静态方法 public static void innerMethod(){ } } } public static void main(String[] args) { //类名调用 Outer.Inner.innerMethod(); }
-
静态内部类调用外部类的非静态方法
- 必须先new出外部类然后才能调用
public class Outer { //外部类非静态方法 public void outerMethod(){ System.out.println("外部类的非静态方法"); } //静态内部类 public static class Inner{ //静态内部类非静态方法 public void innerMethod(){ //必须先创建外部类的对象 new Outer().outerMethod(); } } }
-
-
注意事项
- 内部类如果有静态方法,那么内部类就必须也是静态的
- 内部类时静态的,并不意味着内部类中的方法都是静态的,只是说明我们可以绕过外部类对象之间找到内部类来使用
四、局部内部类
-
定义
- 定义在类中的方法中的内部类叫做局部内部类(用的很少)
-
使用
- 局部内部类的作用范围仅限于本方法中
- 局部内部类在访问他所在方法中的局部变量必须用final修饰
- 因为当调用这个方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周期是一样的,当方法弹栈,这个局部变量也会消失,那么如果局部内部类对象还没有马上消失想用这个局部变量,就没有了,如果用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也可以继续使用
- jdk1.8 取消了这个定义,其实不是取消了,而是设置了隐式的
-
演示
public static void main(String[] args) { //局部内部内使用局部变量必须是final的 final String name = "小红"; //局部内部类 class Inner{ public void method(){ System.out.println("局部内部类"); } public String method2(){ return name + "我爱你"; } } Inner inner = new Inner(); inner.method(); inner.method2(); }
五、匿名内部类
-
定义
- 匿名内部类就是内部类的简写形式,相当于是一个没有名字的子类
- 匿名内部类用于定于接口的或者类的子类
-
使用
- 前提是必须存在一个类,或者接口
- 这里的类可以是具体的类也可以是抽象类
- 相当于是有一个没有名字的子类继承或者实现一个类或接口,然后重写里面的方法,本质是一个继承了该类或者实现了该接口的匿名子类对象
- 对用于规则简单,子类是有很少的接口应用中
-
格式
new 类名或者接口名(){
重写方法;
}
-
演示
public static void main(String[] args) { //匿名部内部类 MyInterface mi = new MyInterface() { @Override public void method() { System.out.println("重写接口的方法"); } }; }
总结
- 成员内部类
- 对类的成员在分组
- 分组完成之后,内部类中的成员没有办法直接调用了,必须先创建外部类对象
- 外部类对象.内部类对象
- 内外部类成员之间互相调用的问题
- 内部类成员可以直接使用外部类的成员,外部类成员不能直接使用内部类的成员,如果要使用,必须先创建对象
- 如果内部类中出现了和外部类相同的名称的成员(就近原则),如果内部类必须要调用外部类的同名成员时,使用外部类名.this.成员
- 静态内部类
- 成员内部类的写法造成了内部类的静态成员无法使用
- 将内部类也变成静态的
- 其他的成员之间的调用遵循的是静态的特性
- 局部内部类
- 当一个类只在当前方法内使用的时候
- 局部内部类使用局部变量的时候,变量要加上final关键字
- jdk1.8 版本之后,编译器如果发现局部内部类中使用到了局部变量,会自动添加final关键字,否则不添加,为了提高内存利用率和简化书写
- 匿名内部类
- 当一个类只使用一次的时候(省的起名字)
- 局部内部类有的特性,匿名内部类都有
- 简写的一定有局限性