`
abcxo
  • 浏览: 33450 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

thinking in java 学习笔记10内部类

阅读更多

第十章 内部类

 

 

这一章听说在其他的书籍中占的份额不大,也就是说不重要,但是在tij这本书里面,份额挺大的,老师也说了,重要,我个人看了下内容,的确是很重要,为你的实现代码低耦合再上一个层次,或者说再增加一个工具

 

可以将一个类的定义放在另一个类的定义内部,这就是内部类,注意哦,内部类不是组合

我们在前面几章有讨论过类的访问权限,对于内部类的访问权限是private和protected也可以的

 

 

 

 

.内部类的实例化

就我个人的理解,内部类就和普通的类变量一样,只不过是因为他的类型是类而已,对于它的实例化,你必须先实例化外围类(就是内部类所在的那个类),然后在实例化内部类

 

 

 

.链接到外部类

内部类最值得注意的不是它名字隐藏和组织代码的模式,而是他拥有其外围类所有元素的访问权(这当然啦,大家都在同一个类里面的)

例子,哎,这里又有一个新模式,迭代器模式,还是那句话,详细分析去我模式文章看

 

这个例子是这样的

有一个selector接口,里面有哪些end,选择的方法

 

有一个类叫做sequenc(队列),他有一些变量,例如一个数组,一些为数组增加元素的方法

 

特别注意他有一个内部类 ,SequenceSelector 实现了selector接口,并且他的方法里面访问了sequence类的变量,比如说返回长度什么的

 

在main方法中实例化了他们,展现了sequenceselector访问外围类元素的特点,通过这一点可以访问到sequence的private元素哦

假如内部类被定义为static,其的效果和普通变量也是一样的

 

 

.使用.this和.new

类名加.this,正确识别为该类的对象引用

要创建内部类对象,可以使用外部类对象.new inner();inner是内部类的名字而已

 


注意:除非是嵌套类,否则必须先实例化外部类对象才能创建内部类对象,嵌套类就是(静态内部类咯),前一张说的嵌套接口只是普通的一环套一环的接口而已

 

小结:在这里我们可以得出了一个访问private元素的方法,就是利用同类中能访问它的内部类,或者内部接口,或者是方法,这样就可以访问它了,我用得最多的是get、set方法

 

 

 

.内部类与向上转型

又见向上转型,在前两张,讨论继承,抽象类,接口,我们能感觉到他们最大的好处就是向上转型,由此可见这个点是非常重要的哦

private 内部类,这个只能让外部类访问,正是通过这个内部类向上转型,完全阻止了任何依赖于类型的编码,并且完全隐藏了实现的细节,对于使用的程序员来说,只能知道这个向上转型后的接口,其他完全一无所知,所以怎么可能可以编出依赖此类型的代码呢

 

.在方法和作用域内的内部类

以上说的只是内部类的典型用途,并且以上是容易理解得,下面进入内部类难啃的地方吧(在经常看别人写的框架的时候,很容易被他们的代码弄的相当糊涂,相信里面上不了内部类的功劳)

 

 

1.在方法中定义内部类(也叫做局部内部类)

书上的作法是在外部类的一个方法里面定义了一个内部类,然后返回这个内部类(我觉得假如这个方法什么都不返回,那么这个内部类还有什么用呢?),注意方法外是不可用的

 

2.在作用域中嵌入一个内部类 (作用域就是{})

这个就和平时在作用域内定义一个变量一样,通常在作用域内定义一个变量都是临时有用的,然后用完就算了

作用域外是不可用的

 

 

3.匿名内部类

例在一个外部类的方法里

public contents contents(){

return new contents()   //这里使用了默认的构造器

{

private int i; //这里定义了匿名类的一些元素

private String str;

}

}

 

语法分析,其实挺好理解得,就是在简写了类的名字而已,然后向上转型为contents,所以你甚至不知道匿名类的类型

若构造器是带参数的怎么办,那么就在方法那里传入参数就好拉,contents(int x)

 

注:若要在内部类中使用传入的参数,必须在前面加final

 

注:匿名类中无构造器,因为他没有名字,不过可以通过实例初始化来达到在匿名内部类创建一个构造器的效果

其实使用了static就ok了.....对于这点我暂时每有弄不明白?

 

 

 

.再访工厂方法(匿名内部类与工厂)

定义一个产品接口,一个工厂接口

然后定义两个产品类实现产品接口,同时产品类中使用单例模式,有一个匿名内部类

然后匿名内部类向上转型为工厂接口,里面实现了产品的生成

 

这样与前面很明显可以看出,每个产品内部相当于都有自己的一个工厂,自己生产自己,都知道怎么创建自己

最重要的一点和前面相比的是,没有人知道工厂的类型,更加隐藏了自己的代码

 

 

.嵌套类(静态内部类)

要创建嵌套类对象,并不需要其外部类对象

不能从嵌套类的对象中访问非静态的外部类对象

普通的内部类不能有static数据,也不能包含嵌套类,嵌套类可以有static数据

可以说嵌套类给类似于一个static方法

 

 

.接口内部的类

可以将嵌套类放在接口里面。原理是因为在接口里面的域都是public 和static的,所以说就可以

有一个好处就是在嵌套类中写main方法,然后测试完成发布产品时就可以将这个Ted$Test这个文件删掉

对于接口或者是类,都可以创建多层嵌套类

 

 

 

 

.为什么需要内部类

为什么作者和sun公司这么在乎这个特性,毫无疑问,这一章我是学习得最辛苦的,可能要花两天的时间来研究

内部类最吸引人的地方是:每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承(某个接口的)实现,对于内部类木有影响

这句话什么意思呢,我觉得可以这样理解,java只支持单继承,并且欲通过接口来弥补这一不足,但是明显的是,若外部类实现多个接口,????(迟点再说这里)

 

 

 

 

 

 

 

.闭包与回调

闭包是一个可调用的对象,他记录了一些信息,这些信息来自于创建他的作用域,内部类就是闭包

回调:在调用某个函数是,将自己的一个函数(回调函数)的地址作为参数传给那个函数,该函数在需要时利用传入的地址调用传入的回调函数,当然啦,在java中没有指针这回事,也就是传入那个回调函数的引用

 

例子,小明去图书馆借书,(借书是一个函数),然后图书馆告诉他,现在没书,有书再通知他,于是小明留下了qq号码(回调函数的引用),然后图书馆有书后调用qq这个引用指向的方法通知小明,,,,小明本来想调用别人,没想到被别人调回他,所以这就是回调

 

书上的例子,还真他妈的难理解,如果分开写,很快就可以理解了,

 

先说简单实现回调

 

定义一个接口a,然后一个类实现这个接口,里面实现了一个callback()(这个明显就是小明,callback()就是小明的qq联系方法)

 

定义一个类caller(就是图书馆),一个变量是刚才的那个接口类型a,然后在构造方法里面赋值个这个对象(a=xx)(xx就是传入的参数,这个接口类型的)

在go的方法里面这样写(a.callback());

 

然后在测试类里面就写caller cal=new caller(xx);

 

cal.go();

 

简单实现情况就是这样

 

复杂一点,就是用上闭包(其实是这样的,你看小明是不是要继承接口a,接口a里面有callback方法,假如小明本身就有callback方法了呢,就会冲突这样,而且使用闭包能够将回调的部分和其余部分分离,无论是逻辑上还是代码上都相当优良,这里的闭包就是内部类)

 

在假如还是小明,小明去继承接口b,接口b里面有一个callback的方法(这个仍然是实现功能的方法)

然后在小明里面有一个内部类,叫做qq类实现了刚才的a接口,那么qq就自然有一个callback方法,在这个方法里面写入小明本身的callback就可以了,因为内部类可以调用外部类的所有东西,然后写一个方法,返回这个内部类的实例就ok了

在测试类里面,caller cal=new caller(c2.getqq())

cal.go();

 

它的主要思想就是通过内部类来调用自身的回调方法

 

 

好处???

 

 

回调的价值在于它的灵活性:可以在运行时动态地决定需要调用什么方法,特别是gui中

 

 

 

 

.内部类与控制框架

holy shit!终于都涉及到框架了,其实内部类对于我来说,都是云里雾里,知道它和框架有关,那么就知道是很用的了

 

 

应用程序框架(application framework):被设计用来解决某类特定问题的一个类或者一组类.

要运用某个应用程序框架,通常是继承一个类或多个类,并覆盖某些方法。在覆盖后的方法中编写定制的应用程序框架提供的通用解决方案,以解决特定的问题,在设计模式的模板模式有详解,fuck

控制框架是一类特殊的应用程序框架,他用来解决响应事件的需求。主要用来响应事件的系统被称为事件驱动系统

gui完全是事件驱动的系统,java swing库就是一个控制框架,并使用了大量的内部类

 

 

 

下面是一个例子,又要分析一下了

今天上课老师讲解了一下,让我的思路也清晰了许多,对于这一章来说,我个人觉得8,9,10章是非常重要的章节,把java中最为难懂的,最巧妙的地方概况了,对于自己,以前编程也就是只是会调用函数之类的,都是学一些表面的功夫,好吧,我们分析一下这个事件驱动模型的例子吧

 

这个是关于greenhouse的,也就是环保房子的意思,环保房子也就是说它的水龙头,他的灯是节能的什么的

 

 

这里一开始是定义一个事件抽象类(为什么不定义接口呢,因为强关系使用抽象类,若关系使用接口,猜测而已)

 

event,在event里面有几种方法,分别是start,ready,acton,

然后再定义一个controller类,这个里面的方法就是顺序执行event的方法,比如说start完之后ready,然后就action这样,抽象了控制过程

 

好了,我们去到主类,也就是greenhousecontrols类,继承了刚才的controller。然后在里面定义数个内部类

继承了event,重写了action方法,比如说开灯内部类,关灯内部类,开水龙头内部类这样

 

 

这时候,框架基本搭起来了,我们在测试类里面实例化greenhousecontrols对象。然后分别调用它们的方法.

实现了开灯关灯等功能

 

有人会问,为什么要这么麻烦,直接在main函数里面写开灯关灯不就好了吗,还需要内部类?,其实这个是低级的写法,这样写,当需要添加新功能的时候呢,或者当需要改变关灯的函数呢,这样使程序的内聚性更强,这个内部类等迟点描述gui时,大家可能就能正在感受到了

 

 

 

.内部类的继承

内部类可以被继承的,但是构造器方面有点麻烦

因为要有外部类对象才会有内部类

所以在构造器里面必须传入外部类对象,并且构造外部类

 

.内部类可以被覆盖吗

疑问

 

.局部内部类

 

只能说之所以使用局部内部类,而不使用匿名内部类的一个理由是,需要不止一个该内部类的对象,而主要理由是我们需要一个已命名的构造器,或者需要重载之前,而匿名内部类只能实例初始化而已

 

.内部类标识符

使用外部类$内部类名字,若是匿名,内部类名字是是一个数字,这种命名方法是强壮的,除了一些特殊情况,在unix系统中,$是元字符,所以有时候可能会有点小问题..

 

 

 

总结:接口与内部类很好的解决了java多重继承的问题,这两张书太有用了,一定要深入理解

 

 

 

 

 

对于内部类,有许多东西还是不理解的,这一期没有扩展资料,还是要再看看如何深入探讨

 

 

这一章有3个设计模式,。迭代器设计模式模板, 设计模式,命令设计模式,迟点我会在模式篇那里逐一介绍

 

 

 

java美女10 北京紫荆侠

 

 

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics