Java内部类探讨
来源:互联网 发布:商城二次开发 php 编辑:程序博客网 时间:2024/06/14 04:10
默认的访问修饰符
最初的发现是遇到了一个疑问,Java中类、接口、内部类、抽象类中属性方法的默认访问修饰符是什么?
稍微查了查资料
- 普通类默认的访问修饰符是:default,也即包内友好
- 接口中的属性的默认是public static final ,方法是public abstract
- 内部类默认的访问修饰符是:public,只是要依附与外围类
- 抽象类默认的访问修饰符是:default
注意
Java中外围类、接口、抽象类的访问修饰符只能是public和default
成员内部类访问修饰权限的测试
这里还可以看一看如何实例化成员内部类,(滑稽
前期准备
- 包
InPackage
中有一个OutClass
,里面有一个内部类InClass
作为成员变量 - 同一个包下有一个测试类
InPackage_OutClass
- 不在同一个包下有一个测试类
OutPackage_OutClass
成员内部类的实例化方法
OutClass.InClass in = new OutClass.InClass(); //只有在内部类中的外围类中可以使用// 1.通用OutClass.InClass in2 = new OutClass().new InClass();// 2.通用OutClass out = new OutClass();OutClass.InClass in3 = out.new InClass();
实验
测试的方法就是看能否实例化成员内部类对象
- 首先是直接在外围类中测试
/** * public > protected > default > private * private 不能修饰外部类 * protected 不能修饰外部类 */public class OutClass { // 作为成员内部类,内部类拥有其外围类的所有成员的访问权 // 不加修饰符的情况下,其修饰符是 default public class InClass{ //public static int id; // static变量违法 // 内部类不能有static方法,因为内部类必须依赖与外部类存在 public void print(){ System.out.println("this inner class"); } } @Test public void testInClass(){ // 1.成员内部类的一种初始化方法 InClass in = new InClass(); in.print(); // 2.成员内部类的另一种初始化方法 OutClass.InClass in2 = new OutClass().new InClass(); in2.print(); // 3.使用外部类绑定来初始化 OutClass out = new OutClass(); OutClass.InClass in3 = out.new InClass(); // 4.当内部类是static修饰时可以使用这个初始化方式 //InClass in4 = new OutClass.InClass(); }}
- 接着是“同包不同类”中实验
/** * 该类旨在测试同一个包下,是否可以访问内部类 * * 所以访问权限是,只有依附与外部类,内部类是可以访问的;但无法直接访问,即便是public也不行 */public class InPackage_OutClass { @Test public void testInClass(){ OutClass out = new OutClass(); // 1.同一个包的情况下,可以访问内部类 OutClass.InClass in = new OutClass().new InClass(); // 不使用.new便无法初始化对象 // OutClass.InClass in2 = new OutClass.InClass(); // 在内部类的外围类中可以使用该初始化方法 // 2.使用外部类对象绑定初始化内部类 OutClass.InClass in3 = out.new InClass(); // 在同一个包的情况下,可以直接导入,但原理还是与上面一致 InClass in4 = out.new InClass(); }}
- 接着是“不同包不同类”
/** * 本例旨在测试不在同一个包的情况下,默认修饰的内部类的访问权限 * * 所以访问权限是,只有依附与外部类,内部类是可以访问的;但无法直接访问 */public class OutPackage_OutClass { public void testInClass(){ OutClass out = new OutClass(); // 1.该方法继承或不继承都可以使用 OutClass.InClass in = new OutClass().new InClass(); // 2.外围类对象绑定的方法可以初始化 OutClass.InClass in2 = out.new InClass(); // 该方法与上述原理一样 InClass in3 = out.new InClass(); // 不行 }}
结论
从上面的实验可以看出,成员内部类的默认访问修饰符是public,这个public其实是指在依赖于外部类的情况下来看这个内部类其实是public的(其实一开始认为是default,直到发现没有继承时也可通过外围类进行实例化…….)
有疑问的地方
其实上述的结论是不敢确定的,因为还看到了这个:Java内部类与访问修饰符
所以,真相究竟是什么? (ㄒoㄒ)
成员内部类的用途
其实一旦观察到了这个知识点,总是很容易会想到用途这个实际的东西(…….),看了看《Think In Java》,里面有这么一个例子:
interface Context{ public void print();}/** * 内部类的主要用途是在类向上转型(接口)时隐藏实现细节 */public class InnerClassApplication { class InClass implements Context{ @Override public void print(){ System.out.println("我是实现接口的成员内部类"); } } public Context getContext(){ return new InClass(); } @Test public void testInClassApplication(){ InnerClassApplication icap = new InnerClassApplication(); icap.getContext().print(); }}
解释一下就是,使用内部类实现一个接口或者继承一个基类,然后向上转型可以隐藏实现的细节
再来看看其它的内部类
局部内部类
首先来看为什么要这样用,无非是有这样的需求:
- 实现了某类型的接口,然后隐藏实现返回接口的实例化对象
- 希望有一个非公共的类来完成某些特殊的任务
普通局部内部类
定义在一个方法中,作用域就是该方法,相较于成员内部类,就是直接把类放入了方法体中
匿名内部类
这个就有说头了,匿名就是类没有名字,由JVM自动分配一个特殊助记名
public class Test{ public Context getContextFromNoNameClass(){ return new Context(){ @Override public void print(){ System.out.println("我是隐式实现了接口的匿名内部类"); } }; } @Test public void testNoNameInClass(){ // 可以看到的是尽管没有显式的实现Context接口,但还是重写了print()方法 this.getContextFromNoNameClass().print(); System.out.println(this.getContextFromNoNameClass().getClass()); }}
这个内部类的类名是class InnerClass.InnerClassApplication$1
,重点是$1
,这个就是JVM给匿名内部类分配的助记符
匿名内部类的一些注意
匿名类不可以改变外围类中的属性,所以当在匿名内部类中使用外部类对象时,会要求这个外围类对象加上final
修饰符
嵌套类
说白了就是给成员内部类加上了static
的修饰符,这意味着
- 要创建嵌套类的对象并不需要依附与外围类(长能耐了)
- 不能从嵌套类的对象中访问到非静态的外围类对象
- 同时可以使用InClass in = new OutClass.InClass();
这种实例化方法
为什么要有内部类
神说要有光,于是便有了光。那为什么会需要内部类呢?
“每个内部类都能独立的继承自一个(接口的)是实现,所以无论外围类是否已经继承了(接口的)实现,对内部类都没有影响” ——《Think in Java》
除此之外,私以为还有上述提到的隐藏实现细节这个原因,所以掌握熟练也是很有必要的,工业界应该少不了这个要求吧?!
- 探讨JAVA内部类
- Java内部类探讨
- 探讨Java内部类的可见性
- 探讨Java内部类的可见性
- 【Java】【内部类】Java 内部类简介
- [Java] Java 内部类
- Java 内部类(成员内部类、局部内部类、静态内部类和匿名内部类)
- Java内部类(成员内部类、静态内部类、局部内部类、匿名内部类)小结
- Java内部类(成员内部类、静态内部类、局部内部类、匿名内部类)小结
- Java内部类(成员内部类、局部内部类、静态内部类、匿名内部类)
- Java内部类(成员内部类、静态内部类、局部内部类、匿名内部类)小结
- Java内部类(成员内部类、静态内部类、局部内部类、匿名内部类)小结
- Java内部类(成员内部类、静态内部类、局部内部类、匿名内部类)小结
- 手记_老司机带你探讨java内部类_咕泡
- java的内部类、匿名内部类、局部内部类
- java内部类之成员内部类、静态内部类
- java 成员内部类 局部内部类,匿名内部类
- Java 静态内部类/内部类
- 浅谈ES6的let和const的异同点
- hbase参数调整
- poj3278之BFS
- JAVA设计模式-模板方法模式
- 数字图像处理实验(5):PROJECT 04-01 [Multiple Uses],Two-Dimensional Fast Fourier Transform
- Java内部类探讨
- 基于 dpdk-nginx 的 c1000k 并发研发
- 第一次苏嵌上课
- WEB 杂记
- 基于Hexo+GitHub Pages+独立域名 搭建博客详细教程
- Android应用开发入门经典学习笔记07--activity和fragment
- IKAnalyzer配置扩展词库经验总结
- “音之国度”游戏UI界面分析(一级界面)
- 学习笔记| AS入门(三) 布局篇