【Java_基础】Java内部类详解
1.四种内部类
java中的四种内部类:成员内部类、静态内部类、局部内部类和匿名内部类。其中匿名内部类用到的最多。
1.1.成员内部类
若一个类定义在另一个类的内部作为实例成员,我们把这个作为实例成员的类称之为成员内部类,也可以叫做实例成员内部类。
在成员内部类的里面可以无条件的访问外部类的任何成员(包括private成员和静态成员)。
class Circle {
private double radius = 0;
public static int count =1;
public Circle(double radius) {
this.radius = radius;
}
class Draw { //内部类无条件的访问外部类成员
public void drawSahpe() {
System.out.println(radius); //外部类的private成员
System.out.println(count); //外部类的静态成员
}
}
}
但是,在外部类中访问成员内部类的成员,必须要通过内部类的对象才能访问,而不能直接访问。
class Circle {
private double radius = 0;
public Circle(double radius) {
this.radius = radius;
getDrawInstance().drawSahpe(); //必须先创建成员内部类的对象,再进行访问
}
private Draw getDrawInstance() {
return new Draw();
}
class Draw { //内部类
public void drawSahpe() {
System.out.println(radius); //外部类的private成员
}
}
}
1.2.静态内部类
若一个类定义在另一个类的内部且加了static关键字作为静态成员,我们把这个作为静态成员的类称之为静态内部类。
静态内部类是不需要依赖于外部类实例的,这点和类的其它静态成员一样,作为静态成员他只能访问外部类的静态成员 ,而不能访问外部类的实例成员。
public class OuterClass {
private String outerClass1="我是外部类的实例成员";
private static String outerClass2="我是外部类的静态成员";
private static class StaticInnerClass{
public void printOuterClassMumber(){
//静态内部类里面只能访问外部类的静态成员
//System.out.println(outerClass1);此句需被注释掉否则会报错
System.out.println(outerClass2);
}
}
}
同成员内部类一样,外部类中也不能直接访问静态内部类成员,必须要通过内部类的对象才能访问。但是和成员内部类不同的是,静态内部类中可以定义静态成员,若外部类访问的是静态内部类的静态成员,则可以通过类名来完成,就无需创建静态内部类对象。
public class OuterClass {
private static class StaticInnerClass{
private String staticInnerClass1="我是静态内部类的实例成员变量";
private static String staticInnerClass2="我是静态内部类的静态成员变量";
}
public void staticInnerClassTest(){
//必须要通过内部类对象才能访问实例变量
System.out.println(new StaticInnerClass().staticInnerClass1);
//可以通过类名来访问静态变量
System.out.println(StaticInnerClass.staticInnerClass2);
}
}
1.3.局部内部类
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法或者该作用域内。局部内部类同局部变量一样,不能加如何访问修饰符,在其作用域外不能被访问。
class OuterClass {
public void localInnerClassTest(){
System.out.println("<<<<<<<<<<<<<<<<测试局部内部类>>>>>>>>>>>>>>>>>");
class LocalInnerClass{
public void pritTest(){
System.out.println("我是局部内部类");
}
}
new LocalInnerClass().pritTest();
}
}
1.4.匿名内部类
匿名内部类通过父类类名加上子类类体new出子类对象,减少了单独定义子类的环节。
public class OuterClass {
public void anonymousInnerClassTest(){
System.out.println("<<<<<<<<<<<<<<<<测试匿名内部类>>>>>>>>>>>>>>>>>");
new AnonymousClass(){
public void printAnonymousClass(){
System.out.println("我是生成的匿名内部类");
}
}.printAnonymousClass();
}
}
2.深入理解内部类
2.1.成员内部类为什么可以无条件的访问外部类的所有成员
我们通过查看编译后的文件可知,编译后内部类和外部类不再是嵌套关系,而是在同一个包下的两个类,并将内部类命名为"外部类类名$内部类类名.class"。

不仅如此,通过反编译成员内部类.class文件可知,编译器为内部类生成了一个指向外部类对象的引用this$0和一个以外部类对象引用作为形参的构造函数。当创建内部类对象时,通过构造函数给对象引用this$0赋值,更为重要的是针对外部类的私有成员还会创建访问他们的accesso方法。结合指向外部类的对象和访问私有成员的方法,才实现了内部类对外部类的无条件访问。这里也间接说明了成员内部类是依赖于外部类的,如果没有创建外部类的对象,则无法对Outter this&0进行赋值,也就无法创建成员内部类对象了。
下面是经编译后的成员内部类字节码文件:
class OuterClass$MumberInnerClass {
private String mumberInnerClass1;
private OuterClass$MumberInnerClass(OuterClass var1) {
this.this$0 = var1;
this.mumberInnerClass1 = "我是成员内部类的实例变量";
}
public void printOuterClassMumber() {
System.out.println(OuterClass.access$000(this.this$0));
System.out.println(OuterClass.access$100());
}
}
2.2.外部类中为什么要创建内部类的对象才能访问内部类成员
成员内部类中对外部类的访问是无条件的,但是外部类中访问内部类成员需要通过内部类对象才能完成。原因在于编译器并未在外部类中自动创建内部类对象,所以需要自己去创建。
下面是编译后的外部类字节码文件,可以看出外部类经编译后没有自动创建内部类对象。
package innerClassTest;
public class OuterClass {
private String outerClass1 = "我是外部类的实例成员";
private static String outerClass2 = "我是外部类的静态成员";
public OuterClass() {
}
public void mumberInnerClassTest() {
System.out.println("<<<<<<<<<<<<<<<<1.测试成员内部类>>>>>>>>>>>>>>>>>");
System.out.println((new OuterClass.MumberInnerClass(null)).mumberInnerClass1);
(new OuterClass.MumberInnerClass(null)).printOuterClassMumber();
}
public void staticInnerClassTest() {
System.out.println("<<<<<<<<<<<<<<<<2.测试静态内部类>>>>>>>>>>>>>>>>>");
System.out.println((new OuterClass.StaticInnerClass(null)).staticInnerClass1);
System.out.println(OuterClass.StaticInnerClass.staticInnerClass2);
(new OuterClass.StaticInnerClass(null)).printOuterClassMumber();
}
public void localInnerClassTest() {
System.out.println("<<<<<<<<<<<<<<<<3.测试局部内部类>>>>>>>>>>>>>>>>>");
class LocalInnerClass {
LocalInnerClass() {
}
public void pritTest() {
System.out.println("我是局部内部类");
}
}
(new LocalInnerClass()).pritTest();
}
public void anonymousInnerClassTest() {
System.out.println("<<<<<<<<<<<<<<<<测试匿名内部类>>>>>>>>>>>>>>>>>");
(new AnonymousClass() {
public void printAnonymousClass() {
System.out.println("我是生成的匿名内部类");
}
}).printAnonymousClass();
}
private static class StaticInnerClass {
private String staticInnerClass1;
private static String staticInnerClass2 = "我是静态内部类的静态成员变量";
private StaticInnerClass() {
this.staticInnerClass1 = "我是静态内部类的实例成员变量";
}
public void printOuterClassMumber() {
System.out.println(OuterClass.outerClass2);
}
}
private class MumberInnerClass {
private String mumberInnerClass1;
private MumberInnerClass() {
this.mumberInnerClass1 = "我是成员内部类的实例变量";
}
public void printOuterClassMumber() {
System.out.println(OuterClass.this.outerClass1);
System.out.println(OuterClass.outerClass2);
}
}
}
2.3.四种内部类的区别
1.四种内部类经编译后均会产生独立的class文件,除了静态内部类以外编译器均会为内部类添加一个指向外部类的引用,使得内部类能无条件访问外部类成员。
2.虽然内部类经编译后会产生独立的字节码文件,但是仍然要满足作为外部类成员的要求,即成员内部类中不能定义静态成员、静态内部类中可以定义静态成员、局部内部类同局部变量一样不能被其作用域以外的地方访问。
3.在外部类的外面创建内部类对象
a.由于成员内部类是依赖于外部类的,所以创建成员内部类对象必须先创建外部类对象。
b.静态内部类是不依赖外部类的,因此可以无需创建外部类对象而直接创建静态内部类对象。
下面是外部类之外创建内部类对象的案例:
public class Test {
public static void main(String[] args) {
OuterClass outerClass=new OuterClass();
OuterClass.MumberInnerClass mumberInnerClassInstance=outerClass.new MumberInnerClass();
mumberInnerClassInstance.printOuterClassMumber();
OuterClass.StaticInnerClass staticInnerClassInstance=new OuterClass.StaticInnerClass();
staticInnerClassInstance.printOuterClassMumber();
}
}
本文参考与:Java内部类详解 Java外部类可以访问内部类private变量
【Java_基础】Java内部类详解的更多相关文章
- Java内部类详解
Java内部类详解 说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉.原因是平时编写代码时可能用到的场景不多,用得最多的是在有事件监听的情况下,并且即使用到也很少去总结内部类的用法.今天我们就 ...
- [转] Java内部类详解
作者:海子 出处:http://www.cnblogs.com/dolphin0520/ 本博客中未标明转载的文章归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置 ...
- 【转】Java内部类详解
一.内部类基础 在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类.广泛意义上的内部类一般来说包括这四种:成员内部类.局部内部类.匿名内部类和静态内部类.下面就先来了解一 ...
- Java内部类详解(一)
(转自:http://blog.csdn.net/wangpeng047/article/details/12344593) 很多人对于Java内部类(Inner Class)都十分陌生,甚至听都没听 ...
- Java内部类详解 2
Java内部类详解 说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉.原因是平时编写代码时可能用到的场景不多,用得最多的是在有事件监听的情况下,并且即使用到也很少去总结内部类的用法.今天我们就 ...
- Java——内部类详解
说起内部类,大家肯定感觉熟悉又陌生,因为一定在很多框架源码中有看到别人使用过,但又感觉自己使用的比较少,今天我就带你具体来看看内部类. 内部类基础 所谓内部类就是在类的内部继续定义其他内部结构类. 在 ...
- Java内部类详解(转)
说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉.原因是平时编写代码时可能用到的场景不多,用得最多的是在有事件监听的情况下,并且即使用到也很少去总结内部类的用法.今天我们就来一探究竟.下面是本 ...
- (转)java内部类详解
本文转自http://www.cnblogs.com/dolphin0520/p/3811445.html,谢谢作者 说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉.原因是平时编写代码时可能 ...
- Java 内部类详解
什么 定义在一个类内部的类,称为内部类(累不累),如下: public class A { private int c = 1; public class C { public void test() ...
随机推荐
- 浅谈Nginx服务器的内部核心架构设计
前言 Nginx 是一个 免费的 , 开源的 , 高性能 的 HTTP 服务器和 反向代理 ,以及 IMAP / POP3代理服务器. Nginx 以其高性能,稳定性,丰富的功能,简单的配置和低资源消 ...
- C#连接Sqlite实现单表操作
今天我们来了解下VS使用的众多数据库中比较轻量的数据库SQLITE,好处当然就在于“轻~”!!!.自己理解
- StringUtils.split()和string.split()的区别
场景 出于业务考虑,将多个字符串拼接起来时,使用的分隔符是;,;.如果要将这样一个拼接来的字符串分割成原本的多个字符串时,就需要使用到jdk自带的split()方法.不过因为公司的编程规范,改为使用了 ...
- [題解]BZOJ_1260_塗色
簡單的區間dp,結果竟然寫掛了......還掛的很徹底......狗屎 如果區間左右端點相等,那麼不需要在多花一次去刷,對 f [ i+1 ] [ j ],f [ i ] [ j-1 ]取個min, ...
- aix 推荐使用重启
重启os AIX 主机 推荐 shutdown –Fr 在客户一次停机维护中,发现了这个问题. 环境是ORACLE 10G RAC for AIX6,使用了HACMP管理共享磁盘. 在停机维护时间段内 ...
- JDBC事务之例子篇
上一篇随笔记了一些有关JDBC事务管理的理论知识.这篇来看例子(主要怕一篇随笔装所有东西太长了然后分开呵呵) 一般讲事务管理的,都是拿转钱来当例子的,嗯没错我们这也是. 这个是数据库中的t_accou ...
- Solr的SolrCloud与Master-slave主从模式对比
第一印象 SolrCloud是Solr4.0引入的,主要应对与商业场景.它很像master-slave,却能自动化的完成以前需要手动完成的操作.利用ZooKeeper这个工具去监控整个Solr集群,以 ...
- springmvc 实现原理与struts2原理的区别
spring mvc的入口是servlet,而struts2是filter,这样就导致了二者的机制不同. spring mvc是基于方法的设计,sturts2是基于类设计的. springmvc将ur ...
- dubbo源码阅读之集群(故障处理策略)
dubbo集群概述 dubbo集群功能的切入点在ReferenceConfig.createProxy方法以及Protocol.refer方法中. 在ReferenceConfig.createPro ...
- leetcode140 Word Break II
思路: 直接爆搜会超时,需要使用记忆化搜索.使用map把已经计算过的情况记录下来,避免重复计算. 实现: class Solution { public: vector<string> w ...