内部类
-
概念:在一个类的内部定义一个完整的类
-
特点:编译之后可生成独立的字节码文件
-
内部类可以直接访问外部类的私有成员,而且不破坏封装。
-
可为外部类提供必要的内部功能组件。
1、成员内部类
-
在类的内部定义,与实例变量、实例方法同级别的类
-
外部类的一个实例部分,创建内部类对象时,必须依赖外部类对象。
public class TestOut { public static void main(String[] args) { //定义外部类 Out out = new Out("张三",15); //创建内部类 Out.Inner inner = out.new Inner(); inner.show(); } }
public class Out { private String name ; private int age; public class Inner{ public void show(){ System.out.println("姓名:"+ name + ",年龄 :"+ age); } } }
-
当外部类、内部类存在重名属性时,会优先访问内部类属性。如果想访问外部类,使用Out.this.
-
成员内部类不能定义静态成员。
-
1.成员内部类可以写任何访问修饰符
-
2.成员内部类可以直接访问外部类的属性和方法
-
3.成员内部类中属性和外部类的属性同名时,使用外部类名.this访问外部类的属性
-
4.成员内部类不能包含静态成员,但是可以包含静态常量
2.静态内部类
-
不依赖外部类对象,可以直接创建或者通过类名访问,可以声明静态成员。
-
级别和外部类一样(学校和老师),静态内部类可以独立使用
-
静态内部类级别和外部类相同
-
静态内部类可以使用任意访问修饰符
-
只能直接访问外部类的静态成员
-
静态内部类不能直接访问外部类的实例属性和方法(创建对象访问)
-
Outer.Inner inner = new Outer.Inner(); Outer.Inner.show();
static class Inner{ String address = "ShangHai"; String sex = "woman"; final static int COUNT = 1; public void show(){ System.out.println(COUNT);// 静态内部类可以包含静态成员 Outer o = new Outer();//静态内部类不能直接访问外部类的实例属性和方法(创建对象) System.out.println(o.name); System.out.println(this.address+this.sex); } }
-
3、局部内部类
-
定义在外部类的方法之中,作用范围和创建对象范围仅限于当前方法。
-
局部内部类不能添加任何访问修饰符。
-
局部内部类访问外部类当前方法中的局部变量时,因无法保证变量的生命周期与自身相同,变量必须修饰为final。
-
局部内部类可以访问局部变量,但是局部变量必须使用final修饰(因为对象的生命周期长于局部变量),JDK1.8final可以省略,
-
局部内部类若是访问外部类的成员可以直接访问,若是访问局部变量,则变量必须用final修饰,也就是必须是常量。
-
原因:因为局部变量是随着方法的调用而存在,随着方法的调用结束而消失。如果但是局部内部类创建出的对象不会立即消失,如果它使用的局部变量消失了,就回产生问题。所以访问常量就无所谓了,因为常量在编译的时候,会替换成具体的内容。
-
public class OuterStatic { String name = "赵大"; public void show() { String address = "深圳"; System.out.println(address); //局部内部类,不能添加任何访问修饰符 class Inner { //局部内部类的属性 private String phone = "1+665526"; public void show2() { //访问外部类的属性(可直接访问) System.out.println(OuterStatic.this.name); //访问内部类的属性(可直接访问) System.out.println(this.phone); //访问局部变量,JDK1.7要求:变量必须是常量 JDK1.8自动添加final System.out.println(address); } } //创建局部内部类对象 Inner inner = new Inner(); inner.show2(); } }
public class TestOuter { public static void main(String[] args) { Outer outer = new Outer(); outer.show(); } }
4、匿名内部类
-
没有类名的局部内部类(一切特征都与局部内部类相同)
-
必须继承一个父类或者实现一个接口
-
定义类、实现类、创建对象的语法结合,只能创建一个该类的对象。
-
优点:减少代码量
-
缺点;可读性差
//使用匿名内部类(相当于创建一个局部内部类) Usb usb = new Usb() { @Override public void servie() { System.out.println("连接电脑成功,电扇开始工作..."); } }; usb.servie(); } //lambda表达式 Usb usb = () -> System.out.println("U盘3连接电脑完成,开始工作..."); usb.serivce();
-
创建匿名内部类可以使用接口,抽象类,普通类,必须实现接口或者抽象类中的抽象方法
-
匿名内部类不能手动添加构造方法,不能包含静态成员
-
匿名内部类中一般不包含特有的方法,不能直接访问,可以通过可访问方法调用或者匿名对象访问
-
匿名内部类生成class文件名:外部类名$编号.class,编号从1开始