========================================================
作者:qiujuer
博客:blog.csdn.net/qiujuer
网站:www.qiujuer.net
开源库:Genius-Android
转载请注明出处:http://blog.csdn.net/qiujuer/article/details/43282699

——学之开源,用于开源;初学者的心态,与君共勉!
========================================================

有这篇文章,纯属巧合;那天在使用中突然发现 Java 内部类中还分 static ,说实话平时都在用,但是就是没有注意到;感觉有必要总结一下。

有必要说一下的是本文纯属浅析,如有补充还请在评论中指出,欢迎总结。

内部类的位置

public class A {class B {}public void pint() {class C {}new C();}public void pint(boolean b) {if (b) {class D {}new D();}}
}

从代码中可以看出,内部类可以定义到很多地方,常用的是成员变量中 (B),方法中也叫局部内部类 (C),作用域中 (D)

从上面来看似乎没有用到过在方法中和作用域中的情况啊,这就错了;再来看看这个:

public interface AInterface {void show();
}
public class B {public void show() {class Man implements AInterface {@Overridepublic void show() {}}Man man = new Man();man.show();}}

其中我们定义了两个文件,一个文件是一个接口类,一个是 B文件;在 B类中,的  show()方法中我们使用了局部内部类的方式创建了类  Man , Man class继承接口并实现方法,随后使用该类。

内部类的权限

为什么要有内部类的存在?

在我看来类主要的就是封装、继承、多态;当然其中的回调思想我认为是很重要的;而内部类的出现就是为了简化多重继承的问题;一个A类,并不能继承多个其他类,但是在使用中又需要使用到其他类的方法,这个时候内部类就发挥作用了;典型的就是事件点击的回调实现。

那么内部类的权限究竟有多大?

至于答案是什么,代码上看看就知道了。

public class C {int a = 1;private int b = 2;protected int c = 3;public int d = 4;void a() {System.out.println("A:" + a);}private void b() {System.out.println("B:" + b);}protected void c() {System.out.println("C:" + c);}public void d() {System.out.println("D:" + d);}class D {void show() {int max = a + b + c + d;a();b();c();d();System.out.println("Max:" + max);}}public static void main(String[] args) {D d = new C().new D();d.show();}
}

运行结果:


可以看出,内部类 D 对类 C 具有完整的访问权限,等于全身脱光了给你看。

那要是反过来呢?

public class C {class D {private int a = 20;private void a(){System.out.println("D.A:" + a);}}void show(){D d = new D();d.a();System.out.println("D.A:" + d.a);}public static void main(String[] args) {new C().show();}
}

运行结果:


可见也是完全可行的,也能直接访问私有属性 私有方法,在这里似乎私有的限制已经失效了一般,这个让我想起了以前看见过一个面试:在 Java 中 private 修饰何时会失效。

这完全是两个人互相脱光光了啊~

匿名内部类

这个非常常见,特别是在按钮点击事件绑定中。

public class D {void initButton() {Button b1 = new Button();b1.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(Button v) {}});Button b2 = new Button();b2.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(Button v) {}});}}

其中的:

    new OnClickListener() {@Overridepublic void onClick(Button v) {}}

就是匿名内部类的使用方式,OnClickListener 是一个接口类,接口类是无法直接new 一个实例的;这里也并不是那样,而是new 了一个其他的类,该类是匿名的,也就是没有名字,只不过该类实现了 OnClickListener接口类中的方法。

上面的添加回调部分可等同于:

public class D {void initButton1() {Button b1 = new Button();b1.setOnClickListener(new Listener1());Button b2 = new Button();b2.setOnClickListener(new Listener2());}class Listener1 implements OnClickListener {@Overridepublic void onClick(Button v) {}}class Listener2 implements OnClickListener {@Overridepublic void onClick(Button v) {}}}

这里就是先建立类,继承自接口;而后赋值到  Button 中。

要说两者的区别与好处,这个其实看具体的使用情况吧;如果你的按钮很多,但是为了避免建立太多类;那么可以建立一个回调类,然后都赋值给所有的按钮,不过最后就是需要在 onClick方法中进行判断是那个按钮进行的点击。

匿名内部类的使用地方很多;具体的使用应视使用情况而定~

静态内部类/静态嵌套类

这个其实并不应该叫做内部类了,因为其并不具备内部类的完全权限,在使用上与一般的类基本一样;那为什么会有这个的存在?

在我看来这个类的存在是为其包括类服务;意思是可以单独服务,不被外面的类所知晓;如这样:

public class E {private void show(){new A();}private static class A{}
}

其中类  A 使用了  static ,所以是 静态嵌套类,在这里使用 private 修饰;那么该类只能在  E 类中进行实例化;无法在 其他文件中实例化。

这样的情况使用外面的类能行么?不行吧?也许你会说在 E.java 文件夹中建立 A.java ,并使用protected修饰;但是在同样的包下,或者继承的类中同样能访问了;这也只是其中一个较为特殊的情况。

我们来看看权限

public class E {int a1 = 0;private int a2 = 0;protected int a3 = 0;public int a4 = 0;private void show(){A a =new A();System.out.print("b1:"+a.b1);System.out.print("b2:"+a.b2);System.out.print("b3:"+a.b3);System.out.print("b4:"+a.b4);}private static class A{int b1 = 0;private int b2 = 0;protected int b3 = 0;public int b4 = 0;private void print(){System.out.print("a1:"+a1);System.out.print("a2:"+a2);System.out.print("a3:"+a3);System.out.print("a4:"+a4);}}
}

在这个中的结果是怎样?


从图片中可以看出,其权限级别是单方向的;静态嵌套类 A 对其包含类 E 完全透明;但 E 并不对 A 透明。

再来看看方法:


可以看出同样的情况;这个是为什么呢?为什么就是多一个 static 的修饰就这么完全不同?其是很好理解,两个独立的类;本来就无法直接使用,必须有引用才能调用其属性与方法。

我们或许可以这么调整一下就OK

public class E {int a1 = 0;private int a2 = 0;protected int a3 = 0;public int a4 = 0;private void show() {A a = new A();System.out.print("b1:" + a.b1);System.out.print("b2:" + a.b2);System.out.print("b3:" + a.b3);System.out.print("b4:" + a.b4);a.b1();a.b2();a.b3();a.b4();}void a1() {}private void a2() {}protected void a3() {}public void a4() {}private static class A {int b1 = 0;private int b2 = 0;protected int b3 = 0;public int b4 = 0;void b1() {}private void b2() {}protected void b3() {}public void b4() {}private void print(E e) {System.out.print("a1:" + e.a1);System.out.print("a2:" + e.a2);System.out.print("a3:" + e.a3);System.out.print("a4:" + e.a4);e.a1();e.a2();e.a3();e.a4();}}
}

在其静态类中传递一个  E 的引用进去就能解决问题了:


可以看出其中现在并没有报错了;能正常运行。

两者之间的隐藏区别

但是最开始上面的内部类是怎么回事?难道是闹鬼了?上面的内部类没有传递引用的啊;为啥加上一个 static 就不行了?

在这里我们需要看看字节码,我们先建立一个简单的内部类:

public class F {class A{}
}

这个够简单吧?别说这个都难了;汗~

然后我们找到 class 文件,然后查看字节码:

在这里分别查看了 F 类的字节码和 F$A 类的字节码。

其中有这样的一句: final F this$0; 这句是很重要的一句,这句出现的地方在其内部类中,意思是当你 new 一个内部类的时候就同时传递了当前类进去;所以在内部类中能具有当前类的完全权限,能直接使用所有的东西;就是因为在隐藏情况下已经传递了当前类进去。

那么我们再看看一个简单的静态内部类:

public class G {static class A {}
}

与上面的区别唯一就是在于添加了一个  static 。此时我们看看字节码:

可以看出其中无论是 G 类,还是 G$A 类的初始化中都没有其他多余的部分,也没有进行隐藏的传递进去当前类;所以这样的情况下并不具备访问权限,需要我们传递引用进去,可以通过接口也可以完全传递进去,具体取决于个人。所以加了static类的内部类除了在权限上比一般的类更加开放(与其包含类)外,与一般的类在使用上是一样的;所以准确的说应该叫做静态嵌套类。

初始化的区别

一个类中,同时包含了内部类与静态内部类,那么其初始化应该是怎么样的呢?

都是直接 new ?还是看看代码:

public class H {int a = 1;public class A {public void Show() {System.out.print("a:" + a);}}public static class B {public void Show(H h) {System.out.print("a:" + h.a);}}public static void main(String[] args) {H h = new H();//A a = new A();A a1 = h.new A();B b = new B();//B b1 = h.new B();B b3 = new H.B();}
}

其中注释了的两种方式是不允许的方式,也就是无法正常运行。

A 因为有一个隐藏的引用,所以必须是H 的实例才能进行初始化出A 类;而B 类则是因为是在H 类中以静态方式存在的类,所以需要 new H.B();之所以能直接使用new B(),与该 main 方法在 H 类中有关,因为本来就在 H类中,所以直接使用 H类的静态属性或者方法可以不加上:“H.”  在前面。

内部类的继承

直接继承的情况:

可以看出报错了,为什么?因为需要传递一个 H 类进去,所以我们在继承的时候需要显示的指明:

public class I extends H.A{public I(H h){h.super();}
}

也就是在构造方法中,传递一个 H 的引用进去,并调用 H 实例的 super() 方法,才能进行实例化。
使用的话应该这样:

 public static void main(String[] args) {H h = new H();I i = new I(h);}

而,如果是继承其静态嵌套类,则不需要这样:

public class J extends H.B{}

就这样就OK。

哎,差不多了~~整个内部类的东西差不多就是这些了,写了我3个小时42分钟~汗!!!!

如果有没有写到的地方,还请补充~~

不对的地方还请指正~~

========================================================
作者:qiujuer
博客:blog.csdn.net/qiujuer
网站:www.qiujuer.net
开源库:Genius-Android
转载请注明出处:http://blog.csdn.net/qiujuer/article/details/43282699

——学之开源,用于开源;初学者的心态,与君共勉!
========================================================

浅析总结 Java 内部类的一些使用与梳理相关推荐

  1. 看到如此详细的Java内部类,我泪目了

    Java内部类 介绍 定义 成员内部类 语法格式 使用说明 代码示例 局部内部类 语法格式 使用说明 代码示例 匿名内部类 语法格式 使用说明 代码示例 静态内部类 语法格式 使用说明 代码示例 介绍 ...

  2. Java内部类作用全解

    提起Java内部类(Inner Class)可能很多人不太熟悉,实际上类似的概念在C++里也有,那就是嵌套类(Nested Class),关于这两者的区别与联系,在下文中会有对比.内部类从表面上看,就 ...

  3. netBeans调试时不进入java内部类(jdk源码)的方法 转载

    初次使用netbeans的调试功能时,会发现调试中,进入了java的内部类运行,具体情况,如下图所示: 对于我这样的一个新手,完全弄不懂啊. 后来我去论坛问了,同时自己研究,发现经过以下设置,就可以跳 ...

  4. Java内部类(Inner Class)小记

    一.引子 看到Trinea的博文Junit单测代码中java序列化失败的解决,让我想到Java内部类的一些小Gocha,初学Java时很迷惑.这里记录一下. 就以Trinea的博文中的序列化失败的例子 ...

  5. Java内部类简介.

    一, 什么是内部类 Java中所谓内部类, 就是定义在另1个类内的类. 例如: class A{int a;class B{int b;} } 上面类B就是类A的一个内部类. 但是下面的写法, B只是 ...

  6. java内部类文件,Java内部类学习

    Java内部类学习 1.内部类的实例与外部类的实例共享一种特殊的关系,这种特殊的关系为内部类中的代码提供对封装(外部)类成员的访问.其实,内部类就是外部类的一部分.不仅仅是"一部分" ...

  7. 在Java内部类中使用外部类的成员方法以及成员变量

    http://blog.csdn.net/zhongyili_sohu/article/details/8975947 众所周知,在定义成员方法或者成员变量的时候,可以给其加上一些权限的修饰词,以防止 ...

  8. Java内部类引用外部类中的局部变量为何必须是final问题解析

    Java内部类引用外部类中的局部变量为何必须是final问题解析 今天编写一个多线程程序,发现在方法内定义内部类时,如果内部类调用了方法中的变量,那么该变量必须申明为final类型,百思不得其解,后来 ...

  9. java内部格式_详解java内部类的访问格式和规则

    详解java内部类的访问格式和规则 1.内部类的定义 定义一个类来描述事物,但是这个事物其中可能还有事物,这时候在类中再定义类来描述. 2.内部类访问规则 ①内部类可以直接访问外部类中的成员,包括私有 ...

  10. 如何新建java内部类_java内部类-1(内部类的定义)

    小胖从官网出发,研究下为什么我们需要些内部类,内部类的区别和联系. 思考三个问题: (1)为什么需要内部类?静态内部类和非静态内部类有什么区别: (2)为什么内部类可以无条件访问外部类成员: (3)为 ...

最新文章

  1. 加快促进大数据与实体经济深度融合发展
  2. python自动测试p-python自动化测试_6
  3. 插入透明32位png格式图片支持ie5.5+、 FF、chrome、safari
  4. context switch的切换过程(TTBR0的切换/ASID的介绍)
  5. commvault oracle备份,CommVault for Oracle备份和恢复.pdf
  6. windows7系统适合哪个python_Python3.6.4在Windows7系统下安装配置教程
  7. 易语言注入 c dll,易语言DLL注入模块简单型
  8. linux命令栏下访问oracle,linux下远程连接oracle数据库
  9. vs编写windows服务和调用webservice
  10. webpack3快速入门
  11. Windows server 2008下查找 w3wp.exe对应的Appoolid
  12. java string是final_关于java:String和Final
  13. java入门到精通第六版_java从入门到精通-第6章.pdf
  14. 数字图像处理:图像与编码
  15. vue3 - composition api
  16. js和vue的图片加载完成事件
  17. c/c++ 洛谷 P1003 【NOIP2011 提高组】 铺地毯
  18. HDFS java接口——实现目录增删文件读写
  19. 主板中的电池是怎样放电的?
  20. 工程中脉冲函数 c语言,怎样用C语言画出二阶系统单位脉冲响应函数的动态曲线...

热门文章

  1. 【PRML 学习笔记】第三章 - 线性回归模型 (Linear Models for Regression)
  2. 编译原理完整学习笔记(八):目标代码生成
  3. 西门子S7系列中间人攻击:流量劫持和转发(一)
  4. 226.翻转二叉树 (力扣leetcode) 博主可答疑该问题
  5. 计算机原理内存详解,【讲给小白的计算机原理】什么是内存,内存的作用?
  6. CSS3实现的几个小loading效果
  7. 2.2.4 ES 6语法与ES 5语法
  8. idea 根据数据库表自动创建持久化类
  9. 提高 分类器 准确率的几种方法总结
  10. 自己动手写一个业务实体生成器(1)