Java内部类与静态内部类区别

前言:看Java源码时经常能看到内部类、静态内部类、私有内部类,一直好奇为什么要这么设计,这样的设计理念与作用在哪里,今天来研究下。

参考:

https://blog.csdn.net/jeason_chan_zju/article/details/103657934

https://www.zhihu.com/question/54730071/answer/140867608

https://stackoverflow.com/questions/70324/java-inner-class-and-static-nested-class

https://www.cnblogs.com/downey/p/4946815.html

https://blog.csdn.net/jianghuafeng0/article/details/109194468

目录

第一章 内部类概要

1.1 为什么需要内部类

1.2 内部类编译后文件的形式

第二章 静态内部类与内部类的区别

2.1 内部类的创建区别

2.2 内部类的访问权限

2.3 内部类中变量的定义

2.4 私有内部类

第三章 应用场景


第一章 内部类概要

1.1 为什么需要内部类

感觉主要是为了高内聚低耦合,当类中某个属性包含很多方面时可以将其声明为内部类,如设计类 B 的目的只是为了给类 A 使用,那么,我们就可将其设定为内部类,没有必要将类 B 设置成单独的 Java 文件,防止与其他类产生依赖关系。

1.2 内部类编译后文件的形式

代码:

public class TestInnerClass {

    String name;
    Head head ;

    public TestInnerClass(){
        head = new Head();
        head.IQ=100;
    }

    public int getIQ(){
        System.out.println(head.IQ);
        return head.IQ;
    }

    public class Head {
        String eye;
        String nose;
        private String brain;
        private int IQ;
    }

    public static class Clothes {
        String jacket;
        String pants;
    }
}

编译后: 

 可以看到内部类会被编译成加上$符号类,为了证明带$符号的类和其它的类一样,我尝试创建了Test$T类,也编译成了带$符号的类,证明内部类虽然是创建在类的内部,但编译之后还是会和正常类一样存在一个class文件。

public class Test$T {
}

思考: 既然会拆成不同的类,那么如何做到互相访问private属性?

javac会把内部类代码的解糖为类似下面的形式(不是一个代码哈,理解下意思就行了):

作者:RednaxelaFX
链接:https://www.zhihu.com/question/54730071/answer/140867608
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

public class Outer {
  private int outProp;

  public Outer() {
    super();
    this.outProp = 8;
  }

  public void accessInnerProp() {
    System.out.println(Outer$Inner.access$000(new Outer$Inner(this)));
  }

  public static void main(String[] args) {
    Outer p = new Outer();
    p.accessInnerProp();
  }
}

class Outer$Inner {
  private int inProp;
  final /* synthetic */ Outer this$0;

  Outer$Inner(Outer outer) {
    this.this$0 = outer;
    super();
    this.inProp = 5;
  }

  static /* synthetic */ int access$000(Outer$Inner self) {
    return self.inProp;
  }
}

 

第二章 静态内部类与内部类的区别

看源码的时候,很多内部类都是静态内部类,不禁思考为什么要用静态内部类

2.1 内部类的创建区别

首先看一下stackoverflow上给的区别:

静态内部类一般被称为nested classes(按中文翻译是嵌套类),普通的内部类一般被称为inner classes(按中文翻译是内部类),不过这里我们为了通俗易懂就还是按之前的静态内部类,普通内部类区分了。

静态内部类可以单独创建。

OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();

普通内部类只能依赖外部类生存,必须创建了外部类才能创建内部类。

OuterClass outerObject = new OuterClass()
OuterClass.InnerClass innerObject = outerObject.new InnerClass();

2.2 内部类的访问权限

在普通内部类中,可以直接访问外部类的属性、方法,即使是private类型也可以,这是因为内部类持有外部类的引用,可以自由访问。而静态内部类只能访问外部类的静态方法和静态属性,如果是private也能访问,其他则不能访问。静态内部类与外部类并不会保存相互之间的引用。

2.3 内部类中变量的定义

普通内部类不能声明static的方法和变量,允许static常量,静态内部类形似外部类,没有任何限制

2.4 私有内部类

就是普通内部类加了private修饰,私有内部类中可以使用外部类中所有的内容,私有内部类只能在外部类中可以通过对象使用私有内部类中的内容,其他类中不能创建私有内部类。

第三章 应用场景

如果内部类与外部类关系不紧密,耦合程度不高,不需要访问外部类的所有属性或方法,需要使用到外部类的静态属性或者需要其他类来处理这个类的内容,那么设计成静态内部类。

你在内部类中需要访问有关外部类的所有属性及方法与不符合静态内部类提供的好处的用普通内部类。

网上说比较典型的使用静态内部类的代码就是HashMap的源码,HashMap源码就有个静态内部类的经典使用,HashMap把put进去的一个key value包装成一个Node,该Node就是静态内部类。

个人感觉ReentrantLock中AbstractQueuedSynchronizer的应用也是挺典型的静态内部类的实现,有兴趣可以看看。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值