文档章节

《Java编程思想》第四版读书笔记 第十章 内部类

一万
 一万
发布于 2016/05/15 18:24
字数 2300
阅读 116
收藏 4
点赞 2
评论 0

内部类和组合的概念完全不同。最初,内部类看起来就像是一种代码隐藏机制:将类置于其他类的内部。但是,内部类远不止如此,它了解外围类,并能与之通信;而且用内部类写出的代码更加优雅而清晰。

10.1

如果想从外部类的非静态方法之外的任意位置创建内部类的对象,那么必须具体指明这个对象的类型:OuterClass.InnerClass。我的理解:内部类的对象可以看作是和外部类的对象相联的。没有外部类的对象,无法创建内部类的对象。

10.2

内部类的对象只能在与其外围类的对象相关联的情况下才能被创建,构建内部类对象时,需要一个指向其外围类对象的引用。

10.3

在内部类中如果想使用外部类对象的引用,可以使用"OuterClass.this"的形式。此引用自动的具有正确的类型,这一点在编译期被知晓并受到检查,因此没有任何运行时开销。

如果想要告知某些其他对象,去创建某个内部类的对象,必须在new表达式中提供对其外部类对象的引用:

Outer outer = new Outer();

outer.new Inner();

要想直接创建内部类的对象,不能引用外部类的名字,而必须使用外部类的对象来创建该内部类对象。在拥有外部类对象之前是不可能创建内部类对象事务。这是因为内部类对象会暗暗地连接到创建它的外部类对象上。但是如果创建的是嵌套类(静态内部类),就不需要外部类对象的引用。

10.4

练习6中在类中的一个protected内部类,在另外包的类中是无法创建对象的,因为该内部类的构造函数和内部类拥有相同的访问属性,即protected。解决方法是显示写出内部类的构造函数,并把它设置为public。

此处需要注意的特性是,内部类的构造函数和内部类具有相同的访问属性

练习8告诉我们,外部类可以访问内部类的private域和方法。内部类和外部类的访问权限是双向的。

10.5

可以在一个方法里或者在任意的作用域内定义内部类。这么做有两个理由:

(1)实现了某个接口,于是可以创建并返回对其的引用;

(2)要解决一个复杂的问题,想创建一个类来辅助,但又不希望这个类是公共可用的。

我的理解:这种在方法或作用域中的内部类与其他类一起被编译,并不是说只有到作用域里才编译。但是,它们只在作用域中可见。

匿名类不可能有构造函数。

10.6

如果定义一个匿名内部类,并且希望它使用一个在其外部定义的对象,那么编译器会要求其参数引用是final的。

由于匿名内部类没有构造函数,可以用语句块的形式对类的对象进行初始化。

练习12 要求在没有指定实现的接口或继承的基类的情况下返回一个匿名内部类,这时可用Object作为引用:

public Object getInnerClass() {   
    return new Object() {
       ...
    }
}

运用匿名内部类,修改接口那一章的工厂方法,使代码变得更整洁优雅:

10.7

静态的内部类也没称为嵌套类,它与普通内部的区别:

(1)要创建嵌套类的对象,并不需要外围类的对象;

(2)不能从嵌套类的对象中访问非静态的外围类数据;

(3)嵌套类可以有static方法和域,还可以有嵌套类,普通内部类不可以。

练习18 要求创建一个嵌套类并在main函数中创建其实例。答案说,如果在外围类中使用嵌套类,直接使用类名就可以,但是如果在其他地方使用嵌套类,则必须使用“外围类.嵌套类”的形式。经过代码测试,其实直接“import 外围类.嵌套类”也可以在其他地方使用嵌套类。

接口中可以包含嵌套类。放到接口中的任何类都自动的是public和static的。因为类是static的,只是将嵌套类置于接口的命名空间内,并不违反接口的规则。甚至可以在嵌套类中实现其外围接口。如果想要创建某些公共代码,使得它们可以被某个接口的所有不同实现所共有,那么使用接口内部的嵌套类会很方便。

作者还提到了一个技巧:

他建议在每个类中都写一个主函数用来测试这个类。这样有一个缺点,是必须带有这些额外的测试代码。可以使用嵌套类来放置主函数和测试代码。比如在类TestBed中创建Tester嵌套类,包含主函数和测试代码。那么编译器会生成一个独立的类TestBed$Tester,要运行这个程序,执行java TestBed$Tester(Unix/Linux系统中需要转义$)。当发布产品的时候,简单的删除TestBed$Tester.class文件即可。

经编码测试接口中的嵌套类是不会继承到它的实现中的。

10.7.2小节主要讲了,多层内部类,不论层数有多少,它都能透明的访问所有外围类。个人认为这个讨论不应放在10.7中,因为本节主要讲述嵌套类(即静态的内部类),而此处说的是普通内部类,容易造成混淆。此处应注意,10.7.2小节讨论的是普通内部类的嵌套,而不是嵌套类。

10.8

使用内部类的一个主要原因是每个内部类都能独立的继承一个类,而无论外围类是否已经继承了某个类。这样内部类和接口一起构成了多重继承的解决方案。

还有其他一些特性:

(1)内部类可以有多个实例,每个实例都有自己的状态信息,并且与其外围类对象的信息相互对立;

(2)在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或继承同一个类;

(3)书中有些迷惑。英语原话是:The point of creation of the inner-class object is not tied to the creation of the outer-class object. 我的理解是,内部类对象创建的时间点不与外部类对象的创建绑定在一起。这应该是相对于导出类与基类的关系来说的(因为导出类的对象创建时基类的对象也将创建);

(4)内部类并没有令人迷惑的“is-a”关系,它是一个独立的实体。

闭包是一个可调用的对象,它记录了一些信息,这些信息来自于创建它的作用域。按照这个定义,内部类是一种面向对象的闭包。

回调机制中的对象携带一些信息,这些信息允许它在稍后的某个时刻调用初始的对象。C++中通过函数指针可以实现回调,而Java通过内部类提供的闭包功能来实现回调。回调的价值在于它的灵活性——可以在运行时动态的决定需要调用什么方法。在实现GUI功能的时候,到处都用到了回调。

10.9

继承内部类时,语法比较特殊:

class WithInner {
     class Inner {
     }
}

public class InheritInner extends WithInner.Inner {
    //默认的构造方法不会编译通过
    //构造函数必须有一个外部类的引用参数
    public InheritInner(WithInner wi){
        wi.super(); //我的理解:可以看做是显示的调用Inner的构造函数
    }
}

10.10

当继承了某个外围类的时候,内部类并没有发生什么变化。这两个内部类是完全独立的两个实体,各自在自己的命名空间内。

10.11

方法或作用域内的内部类(局部内部类)可以访问当前代码块内的常量以及外围类的所有变量。

既然局部内部类的名字在作用域外是不可见的,那为什么不适用匿名内部类?有两个原因:

(1)需要构造函数;

(2)需要多个该内部类的实例。

10.12

每个类会产生一个.class文件,其中包含了如何创建该类型对象的全部信息(此信息产生一个meta-class,叫做Class对象)。内部类的命名规则:外围类的名字加上$,再加上内部类的名字。如果内部类是匿名的,编译器会简单的产生一个数字作为其标识符。

© 著作权归作者所有

共有 人打赏支持
一万
粉丝 28
博文 102
码字总数 173386
作品 0
朝阳
程序员
Java程序员必读书单,家族又添新成员

点击关注异步图书,置顶公众号 每天与你分享IT好书 技术干货 职场知识 参与文末话题讨论,每日赠送异步图书。 ——异步小编 有些革命出其不意地吸引了全世界的眼球。Twitter、Linux操作系统和...

异步社区 ⋅ 05/09 ⋅ 0

Java多线程学习(五)线程间通信知识点补充

系列文章传送门: Java多线程学习(一)Java多线程入门 Java多线程学习(二)synchronized关键字(1) java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Ja...

一只蜗牛呀 ⋅ 04/16 ⋅ 0

语言学习读书笔记PHP和asp.net编程语言哪个更有前途?

编程语言一直是学习计算机编程门专业的热门讨论话题,而我也选择了这个专业,入学一年了,马上面临着语言的选择问题,业余我需要选择一门编程语言作为重点研究对象,那么问题来了:到底是选择...

原创小博客 ⋅ 05/30 ⋅ 0

学好Java只需要做到这7点,年薪20W很简单~

大道至简,所以扎实有用的方法,其实都是很简单的,难在踏踏实实的执行过程。今天为大家介绍的就是Java学习的7个看起来非常简单的方法,快学起来吧。 为什么要学习java? Java是目前最流行的...

欧阳海阳 ⋅ 06/05 ⋅ 0

为什么我会弃Java,选择了Kotlin——专访《Java编程思想》作者 Bruce Eckel

点击上方“CSDN”,选择“置顶公众号” 关键时刻,第一时间送达! 这是前不久我们发布《Kotlin或将取代Java》一文之后,来自网友们的部分声音。 可以看到:作为编程语言界的老大——Java仍然...

csdnnews ⋅ 05/30 ⋅ 0

Java编程语言:学JAVA没有基础,给你4个方向少走弯路。

Java java常常跟"企业"联系在一起, 因为具备一些很好的语言特性, 以及丰富的框架, 在企业应用中最被青睐, 你总可以听到关于J2EE, JSP, Hibernate之类的东西的讨论. 同时, java在手机领域也有...

启示录是真的 ⋅ 05/24 ⋅ 0

学习Java和Spring Boot Cloud ,不妨看看这个

专注于编程、互联网动态。最终将总结的技术、心得、经验(数据结构与算法、源码分析等)分享给大家,这里不只限于技术!还有职场心得、生活感悟、以及面经。 1 java版web项目 java版web项目,...

b644rofp20z37485o35m ⋅ 05/04 ⋅ 0

2018年Java编程学习面试最全知识点总结

Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于PC、数据中心、游戏控制台、科学超级计算机、移动电话和互...

Java小辰 ⋅ 05/14 ⋅ 0

Kotlin学习笔记(六) 伴生对象 对象表达式

一,伴生对象 1.类似于java中的静态方法static 在java中调用可见加了一个Companion,但是假设我们在开发是由java转kotlin项目肯定是一点一点的去动代码,那么这里就涉及到静态方法改成kotlin但是...

JackyRiver ⋅ 06/07 ⋅ 0

关于Java内部类字段和方法不能使用static修饰的原因

昨天的文章中,遗留了一个问题就是,为什么Java内部类字段和方法不能使用static修饰。 先下下面一段代码: 上面的内部类的成员变量和方法,只要加上了static修饰,就会出现编译错误。 原因:...

九劫散仙 ⋅ 06/02 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Java Web如何操作Cookie的添加修改和删除

创建Cookie对象 Cookie cookie = new Cookie("id", "1"); 修改Cookie值 cookie.setValue("2"); 设置Cookie有效期和删除Cookie cookie.setMaxAge(24*60*60); // Cookie有效时间 co......

二营长意大利炮 ⋅ 今天 ⋅ 0

【每天一个JQuery特效】淡入淡出显示或隐藏窗口

我是JQuery新手爱好者,有时间就练练代码,防止手生,争取每天一个JQuery练习,在这个博客记录下学习的笔记。 本特效主要采用fadeIn()和fadeOut()方法显示淡入淡出的显示效果显示或隐藏元...

Rhymo-Wu ⋅ 今天 ⋅ 0

Spring JDBC使用方法

普通实现: 1、创建数据表customer。 可以使用任何数据库实现,在项目中要引入相应数据库驱动包并配置相应数据库连接。 2、创建Customer pojo。 Customer类的属性对应数据库的属性,除了为每...

霍淇滨 ⋅ 今天 ⋅ 0

Contos 7 安装Jenkins

Jenkins是一款能提高效率的软件,它能帮你把软件开发过程形成工作流,典型的工作流包括以下几个步骤 开发 提交 编译 测试 发布 有了Jenkins的帮助,在这5步中,除了第1步,后续的4步都是自动...

欧虞山 ⋅ 今天 ⋅ 0

revel

revel install go get github.com/revel/revelgo get github.com/revel/cmd create new app revel new git.oschina.net/zdglf/myapp run app revel run git.oschina.net/zdglf/myapp ot......

zdglf ⋅ 今天 ⋅ 0

49. Group Anagrams - LeetCode

Question 49. Group Anagrams Solution 思路:维护一个map,key是输入数组中的字符串(根据字符排好序) Java实现: public List<List<String>> groupAnagrams(String[] strs) { Map<Strin......

yysue ⋅ 今天 ⋅ 0

spring Email

使用spring发Email其实就是使用spring自己封装携带的一个javamail.JavaMailSenderImpl类而已。这个类可以当一个普通的java对象来使用,也可以通过把它配置变成spring Bean的方式然后注入使用...

BobwithB ⋅ 今天 ⋅ 0

spark 整理的一些知识

Spark 知识点 请描述spark RDD原理与特征? RDD全称是resilient distributed dataset(具有弹性的分布式数据集)。一个RDD仅仅是一个分布式的元素集合。在Spark中,所有工作都表示为创建新的...

tuoleisi77 ⋅ 今天 ⋅ 0

思考

时间一天天过感觉自己有在成长吗?最怕的是时光匆匆而过,自己没有收获!下面总结下最近自己的思考。 认识自己 认识另一个自己,人们常说要虚心听取别人意见和建议。然而人往往是很难做到的,...

hello_hp ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部