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内部类详解的更多相关文章

  1. Java内部类详解

    Java内部类详解 说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉.原因是平时编写代码时可能用到的场景不多,用得最多的是在有事件监听的情况下,并且即使用到也很少去总结内部类的用法.今天我们就 ...

  2. [转] Java内部类详解

    作者:海子 出处:http://www.cnblogs.com/dolphin0520/ 本博客中未标明转载的文章归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置 ...

  3. 【转】Java内部类详解

    一.内部类基础 在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类.广泛意义上的内部类一般来说包括这四种:成员内部类.局部内部类.匿名内部类和静态内部类.下面就先来了解一 ...

  4. Java内部类详解(一)

    (转自:http://blog.csdn.net/wangpeng047/article/details/12344593) 很多人对于Java内部类(Inner Class)都十分陌生,甚至听都没听 ...

  5. Java内部类详解 2

    Java内部类详解 说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉.原因是平时编写代码时可能用到的场景不多,用得最多的是在有事件监听的情况下,并且即使用到也很少去总结内部类的用法.今天我们就 ...

  6. Java——内部类详解

    说起内部类,大家肯定感觉熟悉又陌生,因为一定在很多框架源码中有看到别人使用过,但又感觉自己使用的比较少,今天我就带你具体来看看内部类. 内部类基础 所谓内部类就是在类的内部继续定义其他内部结构类. 在 ...

  7. Java内部类详解(转)

    说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉.原因是平时编写代码时可能用到的场景不多,用得最多的是在有事件监听的情况下,并且即使用到也很少去总结内部类的用法.今天我们就来一探究竟.下面是本 ...

  8. (转)java内部类详解

    本文转自http://www.cnblogs.com/dolphin0520/p/3811445.html,谢谢作者 说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉.原因是平时编写代码时可能 ...

  9. Java 内部类详解

    什么 定义在一个类内部的类,称为内部类(累不累),如下: public class A { private int c = 1; public class C { public void test() ...

随机推荐

  1. Unable to load script from assets 'index.android.bundle'.Make sure your bundle is packaged correctly or you're running a packager server

    curl -k 'http://localhost:8081/index.android.bundle?platform=android' > android/app/src/main/asse ...

  2. [BZOJ3128]a+b Problem

    题解 最小割+主席树优化建图 首先看到每个点只有\(0/1\)两种状态就想到最小割 然后由于有一个限制是点\(i\)是黑点且有符合条件的白点就会减去\(p_i\) 所以我们将\(S\)集合设为黑点集合 ...

  3. 利用HttpClient4访问网页

    一.HttpClient介绍 虽然在 JDK 的 java.net 包中已经提供了访问 HTTP 协议的基本功能,但是它没有提供足够的灵活性和其他应用程序需要的功能.HttpClient 是 Apac ...

  4. Sql 2000系统表 语句查询表结构

     SQL2000系统表的应用  –1:获取当前数据库中的所有用户表 select Name from sysobjects where xtype=’u’ and status>=0 –2:获取 ...

  5. 2个rman自动恢复的脚本

    ### scripts 1--the scirpt is used for restore db from vcs to a point to time recovery--and the targe ...

  6. html 手机端click 事件去掉黑色阴影效果

    添加css样式 html{-webkit-text-size-adjust: 100%;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);} 1.  -web ...

  7. 一个简易的Http请求转发器

    这两天一直再看微信开发,临时在我的电脑搭了个IIS服务器做微信开发,外网也能访问了,关键是,调试太麻烦了!! 我写完代码,要将代码发布到IIS才能接收微信消息,可是在这个过程中,我不知道微信发过来的是 ...

  8. ES6语言特性,如何在低版本浏览器运行它

    Introduction ECMAScript 6 于今年6月正式成为了标准,关于ES6,我们最大的疑虑可能是客户端浏览器还没有完全支持它,也就node.js用用. 有很多种手段可以解决这个问题,比如 ...

  9. Java-String字符串相关

    字符串String: 封装char[] 字符数组,不可变(因为在底层代码中,值用final关键字修饰) 字符串的字面值: 如果第一次用到一个字符串字面值,会在内存中"字符串常量池" ...

  10. 自动完成文本框(AutoCompleteTextView与MultiAutoCompleteTextView)关联适配器

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools=&q ...