news 2026/7/11 4:29:00

Java 大厂面试高频题:Java 非静态内部类和静态内部类有什么区别?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java 大厂面试高频题:Java 非静态内部类和静态内部类有什么区别?

在学习 Java 内部类时,很多初学者会遇到两个非常相似的概念:

classOuter{classInner{}staticclassStaticInner{}}

其中,Inner是非静态内部类,StaticInner是静态内部类。

它们看起来只是相差一个static,但在对象创建方式、成员访问范围、内存关系和使用场景上都有明显区别。

一句话概括:

非静态内部类依赖外部类对象创建,并且可以直接访问外部类的实例成员;静态内部类不依赖外部类对象创建,只能直接访问外部类的静态成员。

一、什么是内部类?

在一个类的内部定义另一个类,这个类就叫内部类。

例如:

classOuter{classInner{}}

这里:

  • Outer是外部类;
  • Inner是内部类。

内部类通常用于表示一个只服务于外部类的辅助结构。把它放在外部类内部,可以让代码关系更加紧密,也可以隐藏不需要暴露给其他类的实现细节。

成员内部类主要可以分为两类:

非静态内部类 静态内部类

二、什么是非静态内部类?

没有使用static修饰的成员内部类,叫非静态内部类。

例如:

classOuter{intage=18;classInner{voidshow(){System.out.println(age);}}}

这里的Inner就是非静态内部类。

它最大的特点是:必须依赖一个具体的外部类对象才能创建。

创建方式如下:

Outerouter=newOuter();Outer.Innerinner=outer.newInner();inner.show();

不能直接写:

Outer.Innerinner=newOuter.Inner();// 编译错误

因为非静态内部类属于某一个具体的外部类对象,而不是只属于外部类本身。

可以把外部类理解成一栋房子,把非静态内部类理解成房子里的房间。

必须先有一栋具体的房子,才能创建这栋房子里的房间。

所以需要先执行:

Outerouter=newOuter();

再执行:

Outer.Innerinner=outer.newInner();

三、非静态内部类为什么能访问外部类实例成员?

看下面的代码:

classOuter{privateintage=18;classInner{voidshow(){System.out.println(age);}}}

age是外部类的实例变量,但是内部类可以直接访问它,甚至不需要写:

Outer.this.age

原因是,每个非静态内部类对象都会关联一个具体的外部类对象。

例如:

Outerouter=newOuter();Outer.Innerinner=outer.newInner();

这里创建出的inner内部保存了对outer的关联,所以当它访问age时,实际访问的是这个outer对象的age

可以简单理解为:

非静态内部类对象身上带着一个外部类对象。

因此,非静态内部类可以直接访问外部类中的:

实例变量 实例方法 静态变量 静态方法 private 成员

示例:

classOuter{privateintage=18;privatestaticintcount=100;classInner{voidshow(){System.out.println(age);System.out.println(count);}}}

这段代码是可以正常运行的。

四、什么是静态内部类?

使用static修饰的成员内部类,叫静态内部类,也常被称为静态嵌套类。

例如:

classOuter{staticclassStaticInner{voidshow(){System.out.println("静态内部类");}}}

静态内部类不依赖外部类对象,可以直接通过外部类名创建:

Outer.StaticInnerinner=newOuter.StaticInner();inner.show();

不需要先创建:

Outerouter=newOuter();

原因是,静态内部类属于外部类本身,而不是属于某个具体的外部类对象。

可以简单理解为:

非静态内部类属于外部类对象; 静态内部类属于外部类本身。

五、静态内部类为什么不能直接访问实例成员?

看下面的代码:

classOuter{intage=18;staticclassStaticInner{voidshow(){System.out.println(age);// 编译错误}}}

这里会报错,因为age是外部类的实例变量。

实例变量属于某一个具体对象,而静态内部类在创建时并没有关联任何外部类对象。

假设存在两个外部类对象:

Outerouter1=newOuter();Outerouter2=newOuter();outer1.age=18;outer2.age=20;

当静态内部类访问age时,Java 无法判断它要访问的是:

outer1.age

还是:

outer2.age

所以静态内部类不能直接访问外部类的实例成员。

不过,它可以直接访问外部类的静态成员:

classOuter{staticintcount=100;staticclassStaticInner{voidshow(){System.out.println(count);}}}

因为静态变量属于类本身,不属于某一个具体对象。

如果静态内部类确实需要访问实例成员,可以手动创建或接收外部类对象:

classOuter{intage=18;staticclassStaticInner{voidshow(Outerouter){System.out.println(outer.age);}}}

使用:

Outerouter=newOuter();Outer.StaticInnerinner=newOuter.StaticInner();inner.show(outer);

六、完整代码对比

下面通过一个完整示例对比两者:

classOuter{intinstanceValue=100;staticintstaticValue=200;classNormalInner{voidshow(){System.out.println(instanceValue);System.out.println(staticValue);}}staticclassStaticInner{voidshow(){// 不能直接访问 instanceValueSystem.out.println(staticValue);}}}

创建非静态内部类:

Outerouter=newOuter();Outer.NormalInnernormalInner=outer.newNormalInner();normalInner.show();

创建静态内部类:

Outer.StaticInnerstaticInner=newOuter.StaticInner();staticInner.show();

两者的创建方式是最容易在考试和面试中被问到的区别。

七、两者的核心区别

对比项非静态内部类静态内部类
是否使用static
是否依赖外部类对象依赖不依赖
创建方式outer.new Inner()new Outer.StaticInner()
能否直接访问外部类实例成员可以不可以
能否直接访问外部类静态成员可以可以
是否关联外部类对象
更接近普通类还是对象成员对象成员普通类

八、为什么静态内部类更节省关联?

非静态内部类对象会隐式关联一个外部类对象。

例如:

Outerouter=newOuter();Outer.Innerinner=outer.newInner();

只要inner还被使用,它关联的outer也可能无法被垃圾回收。

如果内部类实际上并不需要访问外部类的实例成员,却仍然被定义成非静态内部类,就可能产生不必要的对象关联。

静态内部类没有这种隐式关联。

因此,如果内部类不需要使用外部类对象的实例成员,一般更推荐定义为静态内部类。

九、常见使用场景

1. 非静态内部类

当内部类必须依赖外部类对象的数据时,可以使用非静态内部类。

例如,一个订单中的订单项:

classOrder{privateStringorderNo;classOrderItem{voidprintOrderNo(){System.out.println(orderNo);}}}

OrderItem与某一个具体订单紧密关联,因此可以使用非静态内部类。

2. 静态内部类

当内部类只是为了组织代码,不需要访问外部类实例成员时,更适合使用静态内部类。

常见例子是建造者模式:

classUser{privateStringname;privateintage;staticclassBuilder{privateStringname;privateintage;Buildername(Stringname){this.name=name;returnthis;}Builderage(intage){this.age=age;returnthis;}Userbuild(){Useruser=newUser();user.name=name;user.age=age;returnuser;}}}

使用:

Useruser=newUser.Builder().name("Tom").age(18).build();

这里的Builder不需要依赖一个已经存在的User对象,所以通常定义为静态内部类。

十、初学者容易混淆的问题

1. 静态内部类能不能创建对象?

可以。

static并不代表这个类不能创建对象,而是表示创建它时不需要外部类对象。

Outer.StaticInnerinner=newOuter.StaticInner();

2. 非静态内部类自己能不能有成员变量?

可以。

classOuter{classInner{intvalue=10;}}

3. 静态内部类能不能访问外部类的 private 静态成员?

可以。

classOuter{privatestaticintcount=10;staticclassInner{voidshow(){System.out.println(count);}}}

内部类和外部类之间可以互相访问对方的私有成员,只要访问方式符合静态和非静态规则。

十一、面试怎么回答?

面试时可以这样回答:

非静态内部类依赖外部类实例创建,内部会关联一个具体的外部类对象,因此可以直接访问外部类的实例成员和静态成员;静态内部类不依赖外部类实例,可以直接通过外部类名创建,只能直接访问外部类的静态成员。如果内部类不需要访问外部类实例成员,通常更推荐使用静态内部类。

也可以用一句话回答:

非静态内部类属于外部类对象,静态内部类属于外部类本身。

十二、总结

非静态内部类和静态内部类最核心的区别,不是有没有static这么简单,而是它们是否依赖外部类对象。

非静态内部类:

必须依赖外部类对象创建; 可以直接访问外部类实例成员; 内部会关联一个具体的外部类对象。

静态内部类:

不依赖外部类对象; 可以直接通过外部类名创建; 不能直接访问外部类实例成员; 不会隐式关联外部类对象。

最后记住这句口诀:

非静态内部类先有外部对象,再有内部对象; 静态内部类直接通过外部类名创建。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/11 4:27:32

靠谱的区域教育一体化管理平台哪家比较好

教育数字化转型浪潮下,区域教育管理者面临的核心难题,早已不是“要不要用系统”,而是“用什么样的系统才能真正解决问题”。我和全国多地教育局、学校的负责人交流后发现,大家对教师管理平台的诉求惊人一致:既要全面覆…

作者头像 李华
网站建设 2026/7/11 4:27:20

基于MA12070与PIC18LF26K40的高保真音频系统设计

1. 项目概述:构建基于MA12070与PIC18LF26K40的高保真音频系统在便携式音频设备和智能家居产品快速发展的今天,对高音质、低功耗且紧凑的音频解决方案需求日益增长。MA12070作为英飞凌推出的高效D类音频放大器芯片,与Microchip的PIC18LF26K40低…

作者头像 李华
网站建设 2026/7/11 4:25:40

MATLAB 2023b 线性调频信号脉冲压缩实战:3种加窗方案旁瓣抑制对比

MATLAB 2023b 线性调频信号脉冲压缩实战:3种加窗方案旁瓣抑制对比雷达信号处理中,线性调频(LFM)信号的脉冲压缩技术是提升距离分辨率的关键手段。然而,未经优化的脉冲压缩结果往往伴随着较高的旁瓣电平,这可…

作者头像 李华
网站建设 2026/7/11 4:25:36

Unity集成ChatGPT:打造智能NPC对话系统的架构设计与工程实践

1. 项目概述:当游戏角色“活”过来你有没有想过,在游戏里遇到的NPC,不再只是重复那几句预设好的台词?比如,你扮演一个冒险者,走进酒馆,吧台后的老板不仅能认出你,还能跟你聊起上周你…

作者头像 李华
网站建设 2026/7/11 4:25:05

厄尔尼诺剑指“75年来最强“——期货市场的机会与风险

本文核心观点 美国气候预测中心(CPC)最新月度预测显示,当前厄尔尼诺事件有81%的概率在2026年10-12月发展为"极强"级别,并以97%概率持续至2027年初春,多项指标可能跻身1950年以来最大厄尔尼诺之列。世界气象…

作者头像 李华