Java编程思想读书笔记 第十章 内部类
非静态内部类作用:
- 最基本的作用:名字隐藏和组织代码
- 用例:内部类不访问外部类的元素时可以直接new。(bad style!)
- 用例:通过外部类的非静态方法返回内部类的引用,这样隐含了内部类对象和其对应的外部类对象的关系(需要先创建外部类对象,然后通过外部类对象创建内部类对象)。
- 注意:内部类访问内部类的元素时,直接new内部类编译会报错
No enclosing(外围的) instance of type xxx is accessible
- 链接到外部类:访问其外围类所有成员的访问权
- 实现机制:普通内部类(非静态)对象和外部类对象之间存在联系。创建内部类对象时,该对象保存指向其外部类对象的引用。
- 用例:"迭代器"设计模式
非静态内部类使用:
外部类类名 + .this
- 用法:返回内部类对象引用的外部类对象
外部类对象 + .new
- 用法:返回内部类的引用,告知其它对象或静态方法中使用
// Creating an inner class directory using the .new syntax public class DotNew {
public class Inner {}
public static void main(String[] args) {
DotNew dotNew = new DotNew();
DotNew.Inner inner = dotNew.new Inner();
}
}
权限修饰符
- 私有内部类,隐藏内部类信息。接口的实现不可见也不可用,仅能得到指向基类或者接口的引用。
- 保护内部类,自己、子类、同一个包中的类可以访问
// 接口所有成员自动是public的
interface Destination {
String readLabel();
} interface Contents {
int value();
} class Parcel4 {
// 私有内部类,隐藏内部类信息。接口的实现不可见也不可用,仅能得到指向基类或者接口的引用。
private class PContents implements Contents {
private int i = 11;
public int value() { return i; }
}
// 保护内部类,自己、子类、同一个包中的类可以访问
protected class PDestination implements Destination {
private String label;
private PDestination(String whereTo) {
this.label = whereTo;
}
public String readLabel() { return this.label; }
}
public Destination destination(String s) {
PDestination pDestination = new PDestination(s);
// Exercise 8: 外部类是否可以访问内部类的private元素
// 答:外部类访问内部类的private对象就像访问自己的private对象一样
// 理由:编译器对内部类实现时,生成两个类,对于private变量的访问,编译器会生成一个accessor函数.
System.out.println(pDestination.label);
return pDestination;
}
public Contents contents() {
return new PContents();
}
} public class TestParcel {
public static void main(String[] args) {
Parcel4 p = new Parcel4();
Contents c = p.contents();
Destination d = p.destination("Tasmania");
// The type Parcel4.PContents is not visible
// 不能向下转型成private内部类,因为名字不可访问
// ! Parcel4.PContents pc = p.new PContents();
}
}
- 注意:嵌套类(内部静态类)不需要对外部对象的引用
// Exercise 8: 外部类是否可以访问内部类的private元素
// 答:可以,外部类访问内部类的private对象就像访问自己的private对象一样
// 实现机制:编译器对内部类实现时,生成两个类,对于private变量的访问,编译器会生成一个 accessor函数.
方法和作用域内的内部类
目的
- 实现了某种类型的接口,可以创建并返回对其的引用
- 创建一个类以解决问题,但不希望这个类是公共可用的
局部内部类
- 在方法内部定义类
- 局部内部类可以嵌入某个作用域内(如if作用域),则在作用域外不可访问
匿名内部类
- 创建继承/实现自公共类/接口的匿名类的对象
// Returning an instance of an anonymous inner class. // 普通类被当作“公共”接口来使用
class Wrapping {
private int i;
public Wrapping(int x) { i = x; }
public int value() { return i; }
} public class Parcel7 {
public Contents contents() {
// 创建一个实现/继承自Contents的匿名类的对象,且使用默认的构造器
return new Contents() {
private int i = 11;
public int value() { return i; }
};
} public Wrapping wrapping(int x) {
// Base constructor call:
return new Wrapping(x) { // Pass constructor argument
public int value() {
return super.value() * 47;
}
};
} public static void main(String[] args) {
Parcel7 parcel7 = new Parcel7();
Wrapping wrapping = parcel7.wrapping(4);
System.out.println(wrapping.value());
}
}
public class Parcel9 {
// Argument must be final to use inside
// anonymous inner class:
public Destination destination(final String dest) {
return new Destination(){
private String label = dest;
@Override
public String readLabel() {
return label;
}
};
}
public static void main(String[] args) {
Parcel9 p = new Parcel9();
Destination d = p.destination("Tasmania");
System.out.println(d.readLabel());
}
}
- 匿名内部类、局部内部类:若要使用一个在其外部定义的对象,那么编译器会要求其参数引用是final的
Java编译器实现的只是capture-by-value,并没有实现capture-by-reference
interface AnnoInner(){addXYZ();}
public class Outer {
public AnnoInner getAnnoInner(final int x) {
final int y = 100;
return new AnnoInner(){
// 编译器相当于拷贝外部自由变量的副本到匿名类
// int copyX=x;
// int copyY=y;
int z = 100;
public int addXYZ() {
return x + y + z;
}
}
}
}
- 利用实例初始化,以达到为匿名内部类创建一个构造器的效果
- 注意:匿名内部类既可以扩展类,也可以实现接口,但不能同时扩展类和实现接口,且如果是实现接口,也只能实现一个接口
嵌套类
不需要内部类对象与其外部类对象之间有联系。
- 意义
- 要创建嵌套类的对象,并不需要其外围类的对象
- 不能从嵌套类的对象中访问非静态的外围类对象
- 嵌套类可包含static数据和字段,但普通内部类不行
Java编程思想读书笔记 第十章 内部类的更多相关文章
- 《Java编程思想》笔记 第十章 内部类
1.创建内部类对象 创建内部类对象(相当于new内部类对象) 外围类对象.new 内部类( ). 创建内部类对象一种方法是 外围类有一个方法返回内部类对象. 没有外围类对象就不能创建内部类对象,因为内 ...
- JAVA编程思想读书笔记(五)--多线程
接上篇JAVA编程思想读书笔记(四)--对象的克隆 No1: daemon Thread(守护线程) 参考http://blog.csdn.net/pony_maggie/article/detail ...
- JAVA编程思想读书笔记(四)--对象的克隆
接上篇JAVA编程思想读书笔记(三)--RTTI No1: 类的克隆 public class MyObject implements Cloneable { int i; public MyObje ...
- JAVA编程思想读书笔记(三)--RTTI
接上篇JAVA编程思想读书笔记(二) 第十一章 运行期类型判定 No1: 对于作为程序一部分的每个类,它们都有一个Class对象.换言之,每次写一个新类时,同时也会创建一个Class对象(更恰当的说, ...
- JAVA编程思想读书笔记(二)--容器
接上篇JAVA编程思想读书笔记(一) 第八章.对象的容纳 No1: java提供了四种类型的集合类:Vector(矢量).BitSet(位集).Stack(堆栈).Hashtable(散列表) No2 ...
- Java编程思想读书笔记之内部类
现在是够懒得了,放假的时候就想把这篇笔记写出来,一直拖到现在,最近在读<Java编程思想>,我想会做不止这一篇笔记,因为之前面试的时候总会问道一些内部类的问题,那这本书的笔记就从内部类开始 ...
- Java编程思想读书笔记(一)【对象导论】
2018年1月7日15:45:58 前言 作为学习Java语言的经典之作<Java编程思想>,常常被人提起.虽然这本书出版十年有余,但是内容还是很给力的.很多人说这本书不是很适合初学者,我 ...
- Java编程思想读书笔记
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- <Java编程思想>读书笔记(1)-对象导论、一切都是对象
1.面向对象编程:OOP (Object-oriented Programming) 2.Alan Kay 总结的面向对象语言5个基本特性: 1) 万物皆为对象 2) 程序是对象的集合,他们通过发送消 ...
随机推荐
- Net中Attribute特性的高级使用及自定义验证实现
好久没写博客了,今天在百忙之中抽空来写篇文章,记录一下最近深入学习Attribute特性的笔记及心得.~~ 一.什么是特性? 特性(Attribute)是用于在运行时传递程序中各种元素(比如类.方法. ...
- JAVA静态方法是否可以被继承
结论:java中静态属性和静态方法可以被继承,但是没有被重写(overwrite)而是被隐藏.原因:1). 静态方法和属性是属于类的,调用的时候直接通过类名.方法名完成对,不需要继承机制及可以调用.如 ...
- sqli-labs(38)
0X01 ?id=' and 1=1%23 正确 ?id=1' and 1=2%23 错误 存在注入 0x1 堆叠注入讲解 (1)前言 国内有的称为堆查询注入,也有称之为堆叠注入.个人认为称之为堆叠注 ...
- [翻译]剖析C#中的异步方法
翻译自一篇博文,原文:Dissecting the async methods in C# 有些括号里的是译注或我自己的理解. 异步系列 剖析C#中的异步方法 扩展C#中的异步方法 C#中异步方法的性 ...
- xshell上windows和linux互传文件命令
1.安装lrzsz包: yum install -y lrzsz 2.从windows上传文件到linux服务器: rz 会弹出选择文件窗口,按照提示做就行3.从linux服务器下载文件到本地的win ...
- 【数据算法】Java实现二叉树存储以及遍历
二叉树在java中我们使用数组的形式保存原数据,这个数组作为二叉树的数据来源,后续对数组中的数据进行节点化操作. 步骤就是原数据:数组 节点化数据:定义 Node节点对象 存储节点对象:通过Linke ...
- IDEA全局配置
进入全局设置界面: 取消每次启动IDEA就默认打开上一次最后关闭的项目 编译器代码字体设置: 控制台字体大小和颜色设置 同一个文件代码里面的各个不同方法之间显示分割线 代码自动提示不区分大小写 格式化 ...
- 改善EDM数据营销的关键点
EDM数据营销有效增加潜在顾客.提升销售量,而成效得看你的邮件到达率.当点选发送后,邮件需要经过层层关卡才能够进入联络人收件箱,若是你的发送评级越好,邮件越容易进入收件箱.评级非常重要,它能够证明你是 ...
- 如何解决错误【selenium.common.exceptions.SessionNotCreatedException】
如何解决错误[selenium.common.exceptions.SessionNotCreatedException] [问题起因] 2018年12月26日晚,启动我的pycharm准备学习s ...
- 趣谈linux操作系统笔记-内核初始化
内核的启动从入口函数 start_kernel() 开始.在 init/main.c 文件中,start_kernel 相当于内核的main 函数.打开这个函数,你会发现,里面是各种各样初始化函数 X ...