贵阳网站建设技术支持,余姚网站制作公司,wordpress装修主题,点卡平台网站开发一 内部类是什么Java类中不仅可以定义变量和方法#xff0c;还可以定义类#xff0c;这样定义在类内部的类就被称为内部类。根据定义的方式不同#xff0c;内部类分为静态内部类#xff0c;成员内部类#xff0c;局部内部类#xff0c;匿名内部类四种。Java为什么要引入内…一 内部类是什么Java类中不仅可以定义变量和方法还可以定义类这样定义在类内部的类就被称为内部类。根据定义的方式不同内部类分为静态内部类成员内部类局部内部类匿名内部类四种。Java为什么要引入内部类这个概念呢原因在于内部类定义在类的内部可以方便访问外部类的变量和方法并且和其它类进行隔离。二 静态内部类定义在类内部的静态类就是静态内部类。2.1 语法定义一个静态内部类public class Out {private static int a;private int b;public static class Inner {public void print() {System.out.println(a);}}}Inner就是静态内部类。静态内部类可以访问外部类所有的静态变量和方法即使是private的也一样。静态内部类和一般类一致可以定义静态变量、方法构造方法等。其它类使用静态内部类需要使用“外部类.静态内部类”方式如下所示Out.Inner inner new Out.Inner();inner.print();2.2 实现原理查看编译后的代码可以知道Out.java编译后会生成两个class文件分别是Out.class和Out$Inner.class。因为这两个类处于同一个包下所以静态内部类自然可以访问外部类的非私有成员。但是我们知道静态内部类是可以访问外部类所有访问权限的成员的Java是如何实现的呢看编译后生成的代码就知道了public class Out$Inner {public Out$Inner() {}public void print() {System.out.println(Out.access$000());}}静态内部类通过外部类的access$000()方法访问外部类的私有变量这个方法是编译器自动生成的。在运行时我们可以通过反射调用该方法。2.3 应用场景Java集合类HashMap内部就有一个静态内部类Entry。Entry是HashMap存放元素的抽象HashMap内部维护Entry数组用了存放元素但是Entry对使用者是透明的。像这种和外部类关系密切的且不依赖外部类实例的都可以使用静态内部类。三 成员内部类定义在类内部的非静态类就是成员内部类。3.1 语法定义一个成员内部类public class Out {private static int a;private int b;public class Inner {public void print() {System.out.println(a);System.out.println(b);}}}成员内部类可以访问外部类所有的变量和方法包括静态和实例私有和非私有。和静态内部类不同的是每一个成员内部类的实例都依赖一个外部类的实例。其它类使用内部类必须要先创建一个外部类的实例。如下所示Out out new Out();Out.Inner inner out.new Inner();inner.print();成员内部类不能定义静态方法和变量(final修饰的除外)。这是因为成员内部类是非静态的类初始化的时候先初始化静态成员如果允许成员内部类定义静态变量那么成员内部类的静态变量初始化顺序是有歧义的。3.2 实现原理和静态内部类类似Out.java编译后会生成两个class文件分别是Out.class和Out$Inner.class。成员内部类的代码如下public class Out$Inner {public Out$Inner(Out var1) {this.this$0 var1;}public void print() {System.out.println(Out.access$000());}}成员内部类访问外部类的私有变量和方法也是通过编译时生成的代码访问的。区别是成员内部类的构造方法会添加一个外部类的参数。四 局部类定义在方法中的类就是局部类。4.1 语法定义一个局部类public class Out {private static int a;private int b;public void test(final int c) {final int d 1;class Inner {public void print() {System.out.println(a);System.out.println(b);System.out.println(c);System.out.println(d);}}}public static void testStatic(final int c) {final int d 1;class Inner {public void print() {System.out.println(a);//定义在静态方法中的局部类不可以访问外部类的实例变量//System.out.println(b);System.out.println(c);System.out.println(d);}}}}局部类只能在定义该局部类的方法中使用。定义在实例方法中的局部类可以访问外部类的所有变量和方法定义在静态方法中的局部类只能访问外部类的静态变量和方法。同时局部类还可以访问方法的参数和方法中的局部变量这些参数和变量必须要声明为final的。4.2 实现原理Out.java编译后局部类会生成相应的class文件。class Out$1Inner {Out$1Inner(Out var1, int var2) {this.this$0 var1;this.val$c var2;}public void print() {System.out.println(Out.access$000());System.out.println(Out.access$100(this.this$0));System.out.println(this.val$c);System.out.println(1);}}和成员内部类类似生成的局部类的构造方法包含了外部类的参数并且还包含了定义局部类方法的参数这也就解释了为什么局部类可以访问外部类和方法的成员。同时也明白了为什么局部类访问的变量需要final修饰因为局部类访问的变量其实是该局部类自己的成员如果不用final修饰那么在局部类修改该变量的值并不会影响方法中该变量的值。为了避免这种困惑Java就禁止修改。4.3 应用场景如果一个类只在某个方法中使用则可以考虑使用局部类。五 匿名内部类5.1 语法定义一个匿名内部类public class Out {private static int a;private int b;private Object obj new Object() {private String name 匿名内部类;Overridepublic String toString() {return name;}};public void test() {Object obj new Object() {Overridepublic String toString() {System.out.println(b);return String.valueOf(a);}};System.out.println(obj.toString());}}匿名内部类可以出现在任何允许表达式出现的地方定义格式new 类/接口{//匿名内部类实现部分}5.2 实现原理Out.java编译后匿名内部类会生成相应的class文件。class Out$1 {private String name;Out$1(Out var1) {this.this$0 var1;this.name 匿名内部类;}public String toString() {return this.name;}}匿名内部类可以访问外部类所有的变量和方法。5.3 应用场景匿名内部类使用广泛比如我们常用的绑定监听的时候。view.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View v) {Toast.makeText(v.getContext(),click,Toast.LENGTH_SHORT).show(); }});