内部类就是定义在一个类内部的类。定义在类中方法间的有两种情况:一种是普通内部类,一种是静态内部类。
普通内部类与外部类的关系可以总结为两点:
1.外部类的作用范围内可以任意创建内部类,即使内部类是私有的
2.内部类对象持有对外部类对象的引用,并能访问到外部类的私有属性
即内部类对外部类可见,外部类对内部类可见。
如下两个例子:
//代码1:内部类对外部类可见 class Outer{ //创建私有内部类对象 public Inner in=new Inner(); //私有内部类 private class Inner{ ... } } //代码2:外部类对内部类可见 class Outer{ //外部类私有数据域 private int data=0; //内部类 class Inner{ void print(){ //内部类访问外部私有数据域 System.out.println(data); } } }
那到底这些特性的原理是什么呢?内部类的本质又是怎么一回事?
其实,内部类就像泛型一样都是编译器层面的事,虚拟机并不知道内部类与常规类的区别。内部类编译之后会得到两个class文件:Outer.class和Outer$Inner.class。只是在编译过程中编译器做了一些处理,至于内部类的那些特性就得益于这些处理
//反编译1 class Outer$Inner { Outer$Inner(Outer,Outer$Inner); //包可见构造器 private Outer$Inner(Outer); //私有构造器将设置this$0域 final Outer this$0; //外部类实例域this$0 }
首先编译器将外、内部类编译后放在同一个包中。在内部类中附加一个包可见构造器。这样Outer对象的Inner in = new Inner();实际上调用的是new Outer$Inner(this,null)。因此即使是private内部类,也会通过隐含的包可见构造器成功的获得私有内部类的构造权限
//反编译2 class Outer { static int access$0(Outer); //静态方法,返回值是外部类私有域 data 的值。 }
而外部类中添加了静态方法access$0。它将Outer对象的私有域返回。
access$0方法的汇编代码大概是
static int access$0(simpleTest.OutClass); descriptor: (LsimpleTest/OutClass;)I flags: ACC_STATIC, ACC_SYNTHETIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: getfield #12 // Field a:I 4: ireturn
这里是我的代码反编译成的私有属性是代号为a的int值,外部类名叫OutClass。可以看到静态方法access$0先加载参数OutClass对象,然后获得该对象的私有属性a,将其返回
相当于你调用外部类私有属性a,就是调用OutClass.access$0(this$0);
总结一下编译器动的手脚
1.在内部类中创建包可见构造器,使外部类获得创建权限
2.在内部类维护一个外部类对象
3.在外部类创建访问私有变量的静态方法,使内部类获得访问权限
静态内部类
静态内部类与普通内部类相比,反编译后少了一个指向外围对象的引用final Outer this$0;也就是说静态内部类无法得到其外围类对象的引用。因此,静态内部类只能范文外部类的静态成员,除此之外与非静态内部类没有任何区别
局部内部类--在方法中定义的内部类
局部内部类也有两个特点
1.方法内部类没有访问修饰符,方法内部类对包围它的方法之外的任何东西都不可见
2.方法内部类只能访问该方法中的局部变量,而且这些变量一定是final的
class Outter{ public void outMethod(){ final int beep=0; class Inner{ //使用beep } Inner in=new Inner(); } }
反编译后发现
1.Outter中没有返回私有域的隐藏方法access$0了
2.Inner类内部多了一个对beep变量的备份隐藏域:final int val$i;
可以这样解释编译器这种做法,当jvm运行到创建Inner对象后,Outter类可能以及运行完毕,垃圾回收机制可能释放掉局部变量beep,编译器就在Inner类中创建一个beep的备份。但是如果Outter中的beep不停在变,内部类也必须要无时无刻盯着,为了保持外部类的方法局部变量与内部类的备份域一致。编译器就规定死这些内部类需要的局域变量必须是final常量
相关推荐
Java 内部类详解 Java 内部类是一种高级特性,允许在一个类的定义内部创建另一个类。这种设计模式提供了更灵活的代码组织方式,同时还可以实现特定的封装和访问控制。内部类主要分为四种类型:静态内部类、成员内部...
### Java内部类总结 在Java编程语言中,内部类是一个重要的概念,它允许开发者在一个类的内部定义另一个类。这种特性极大地增强了代码的封装性和复用性,同时也为解决特定问题提供了灵活的方法。本文将围绕Java内部...
### Java内部类详解 #### 一、内部类的分类与概念 Java的内部类机制是其强大特性之一,它允许类作为另一个类的成员存在,从而增强了代码的封装性和复用性。根据定义和作用域的不同,Java内部类主要分为四类: 1. ...
Java 内部类是Java语言特性中的一个重要组成部分,它允许我们在一个类的内部定义另一个类。内部类可以访问外部类的所有成员,包括私有成员,这使得内部类在实现复杂逻辑和封装上具有很大的灵活性。下面我们将详细...
### Java内部类的应用场景 #### 场景一:当某个类除了它的外部类,不再被其他的类使用时 内部类的使用场景之一是当某个类仅需被其外部类使用时。这种情况下,将此类定义为内部类可以提高代码的封装性和可维护性。 ...
Java内部类是Java语言提供的一种独特特性,它允许我们在一个类的定义内部定义另一个类。这种内部类可以是成员内部类、局部内部类、匿名内部类或静态内部类,每种都有其特定的用途和使用场景。在这个"java内部类使用...
12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类...
Java内部类是Java语言的一个特色特性,它允许我们在一个类的内部定义另一个类。这种设计模式在处理一些特定情况时非常有用,例如实现匿名回调、封装特定逻辑或创建与外部类有紧密关系的类。本篇文章将深入探讨Java...
Java内部类是Java语言的一个独特特性,它允许我们在一个类的内部定义另一个类。这种设计提供了更高级别的封装和组织代码的方式。以下是关于内部类及其相关知识点的详细说明: 1. **内部类基本语法** - **实例内部...
### JAVA内部类总结 在Java编程语言中,内部类(Inner Classes)是一种非常重要的特性,它允许我们在一个类的内部定义另一个类。这种结构不仅能够提高代码的组织性,还能帮助我们更好地处理类与类之间的关系。根据...
Java内部类是Java语言提供的一种独特机制,它允许在一个类的内部定义另一个类。这种设计模式使得代码结构更紧凑,可以更好地封装和隐藏实现细节,同时也增强了代码的复用性。内部类分为几种类型,包括成员内部类、...
Java 内部类总结 Java 内部类是指在一个外部类的内部再定义一个类。内部类作为外部类的一个成员,并且依附于外部类而存在的。内部类可为静态,可用 protected 和 private 修饰(而外部类只能使用 public 和缺省的包...
Java内部类是Java语言特性中一个独特而强大的部分,它允许在一个类的内部定义另一个类。内部类可以访问外部类的所有成员,包括私有成员,这使得内部类在实现某些特定设计模式时非常有用。本篇文章将深入探讨Java中的...
Java内部类详解 Java内部类是Java语言中的一种特殊类别,它是指定义在另外一个类内部的类。内部类可以访问外部类的所有成员变量和方法,包括私有的变量和方法。内部类可以分为四种:成员内部类、静态嵌套类、方法...
谈Java内部类的四个应用场景
Java内部类是Java语言中一个独特且强大的特性,它允许我们在一个类的内部定义另一个类。内部类提供了增强封装的能力,使得内部类可以被隐藏在外部类中,仅对外部类可见,从而增加了代码的隐私性和安全性。同时,内部...
### Java内部类的作用 #### 一、定义及概念 内部类,顾名思义,指的是一个定义在另一个类内部的类。这样的结构让内部类能够访问外部类的成员(包括私有成员),并且允许内部类拥有不同的访问级别,如`private`、`...
Java内部类是Java语言的一个重要特性,它允许我们在一个类的内部定义另一个类。这种设计模式使得代码结构更加紧凑,同时也提供了更高级的封装和抽象。内部类主要有两种类型:成员内部类和局部内部类。 1. 成员内部...