java的inner-class

今天咱们说内部类 设计模式

keywords :inner-class 将一个类的定义放在另外一个类的定义内部 数组

有了她,咱们能够把一些逻辑相关的类组织起来并放到一块儿,并控制位于内部类的可视性。起初咱们彻底会作出内部类是一种代码的隐藏机制的判断,但实际上内部类远非如此,她是如此的优雅,能够与外部类发生关系,进行通讯。 app

inner-class 看上去是使人感到怪异的,但她的特性依然让人着迷,并且你必须花费更多的时间去设计以及实践性的去使用他。然而在大多数时间里面,对inner-class的需求并不是显得那么的明显,可是一旦你掌握并能够灵活的使用她,我相信其中的益处也是显而易见的。那么,咱们还在等什么呢? this

如今,咱们将拥有一个内部类:
public class Parcel1{
spa

class Contents{ 设计

private int i=11; code

public int value(){ orm

return i; 对象

} 接口

}

class Destination{

private String label;

Destination(String whereTo){

label=whereTo;

}

String readLabel(){

return readLabel;

}

}

public void ship(String dest){

Contents c = new Contents();

Destination d = new Destination();

System.out.println(d.readLabel());

}

public static void man(String[] args){

Parcel1 p =new Parcel1();

p.ship(“Tasmania”);

}

}//Use this code and into your compiler, see the result .

就这段代码而言,实际上经过嵌套,外部类Parcel1的对象p使用了其内部类Destination 中的readLabel方法 ,可是这样的用法没有什么可以让咱们惊呼的。

如今,咱们将尝试更为奇妙的东西,她将实现这样一个目的:out-class有一个方法,其将返回一个指向内部类的引用;

public class Parcel2{

class Contents {

private int i=11;

public int value() {

return i;

}

}

class Destination {

private String label;

Destination(String whereTo){
label = whereTo;

}

String readLabel() {

return label;

}

}

public Destination to(String s){

return new Destination(s);

}

public Contents contents(){

return new Contents();

}

public void ship(String dest){

Contents c = new Contents();

Destination d = new Destination();

System.out.println(d.readLabel());

}

public static void main(String[] args){

Parcel2 p = new Parcel2();

p.ship(“Tasmania”);

Parcel2 q = new Parcel2();

Parcel2.Contents c = q.contents();

Parcel2.Destination d = q.to(“Borneo”);

}

}//Use this code and into your compiler, see the result.

正如咱们所看到的,粗体字代表了须要在一个out-class的非static 方法以外的任意位置使用inner-class中的object的用法。

接下来咱们来研究如下inner-class out-class是如何发生关系连接

如今,你是否仍是这样认为,inner-class只是一种名字隐藏和组织代码的模式。你仍然没有感受到她的奇妙之处。那么如今请注意下面这句话:当生成一个inner-classobjects时,此object与制造它的enclosing object便发生了关系。这种关系就体如今object能够access enclosing object 中的全部成员(attribute or field ,and functions),而这却不须要任何的代价。

看看这段有趣儿的代码:

interface Selector{

boolean end();

Object current();

void next();

}

public class Sequence{

private Object[] items;

private int next=0;

public Sequence(int size){

items= new Object[size];

}

public void add(Object x){
if(next<items.length){

items[next++] = x;

}

}

private class SequenceSelector implements Selector {

private int i=0;

public boolean end(){
return i==items.length;

}

public Object current() {

return items[i];

}

public void next(){
if (i<items.length){

i++;

}

}

public Selector selector(){

return new SequenceSelector();

}

public static void main(String[] args){
Sequence sequence = new Sequence(10);

for(int i =0;i<10;i++){

sequence.add(Integer.toString(i));

}

Selector selector = sequence.selector();

while(!selector.end()){

System.out.println(selector.end() + “ ”);

selector.next();

}

}

}//Use this code and into your compiler, see the result.

Class Sequence 中固定大小的Object数组,是以类的形式包装起来的。只要还有空间即知足 next<items.length ,便可以调用add()方法以实如今序列的末尾处添加新的object。如今咱们须要使用Sequence这个类中的对象,那么,不难想象到咱们可使用interface。请注意下面这句话,它有关于“迭代器”的设计模式要获取Sequence中的每一个对象,可使用Selector接口。相应的,咱们不难看出,全部实现了Selector接口的类看上去都是实现了这样一些功能的(function):end()方法能够检查序列是否到了末尾current()方法能够访问当前对象,而next()功能则实现了移到序列的下一个对象。由于Selector是一个接口而非抽象类,因此很灵活的,当类SequenceSelector 实现了Selector接口时,它能够以本身的所喜欢的style去运转。再看看SequenceSelector这个类,他是个Private的类。也正是经过他,Selector接口中所描绘出的功能,才可以得以实现。在入口方法中,咱们将Sequence这个包含有一个固定长度的数组的类实例化了,并给它传递了一个整数型的参数。这样,一个定长的数组也就诞生了。接着咱们利用对象包装器,向里面添加一些String类型的对象。最后,使用Sequence类的对象sequenceselector方法,获得一个返回值为协变返回类型的对象,并将其赋值给Selector接口的实例化selector。如今你还认为inner-class技术不过如此吗,若是你还这么想,那么再仔细看一下实现了Selector接口的类SequenceSelector中的三个方法,他们都用到了Object,在这里实际上是一个引用,其实它并不属于类SequenceSelector,而仅仅是enclosing class 中的一个私有的filed。这样看来inner-class已经拥有了enclosing class中的全部内容。这是多么使人难以想象啊,你可能会这样问,那么这是如何实现的呢?inner-class 会在适当的时候catch一个指向那个enclosing-class的引用就这样,当你用inner-class的对象access那个enclosing-class的内容的以前,会调用那个引用,实际上那个神秘兮兮“引用先生”在访问enclosing-class的内容。固然,这一切都是托了compiler的福。

关于.this.new

看到这两个熟悉的keywords,你必定有不少想说的,他们对咱们来讲是显得那么的熟悉,但同时也经常会令咱们十分苦恼。

如今想要引用out-classobject那么能够这样写

out-classname.this 这样作的好处就是咱们能够自动得到一个正确类型的对象,编译器会帮助咱们作好审查工做,换回来的固然是运行时的零开销。

看看这个“.this”是如何apply的:

public class DoThis{

void() f(){
System.out.println(“DoThis.f()”);

}

public class Inner{
public DoThis outer(){

return DoThis.this;

}

}

public Inner inner(){

return new Inner();

}

public static void main(String[] args){
DoThis dt = new DoThis();

DoThis.Inner dti = dt.inner();

dti.outer().f();

}

}Use this code and into your compiler ,see the result

如今你明白了,如何生成对外部类对象的引用,那么你也许会问,若是想要让某些小家伙(enclosing-class's object)去建立在它们本身内部的某个inner-class's object ?

接下来我将展现,上面的问题时如何在代码中得以实现的

public class DotNew{

public class inner{

//nothing in this class.

}

public static void main(String[] args){

DotNew dn = new DotNew();

DotNew.Inner dni = dn.new inner();

}

}//Use this code and into your compiler ,see the result.

请记住,若是想要去建立一个inner-class's object,那么应该使用enclosing-class's object 去建立一个inner-class's object ,因此拥有内部来对象的前提是,你必须先建立一个外部类的对象。不过这也有例外,下面看嵌套类,她是一个静态的内部类,她不须要对外部类对象的引用。

public class Parcel3{

class Contents {
private int i =11;

public int value(){
return i;

}

}

class Destination {

private String label;

Destination(String whereTo){

label = whereTo;

}

String readLabel(){
return label;

}

}

public static void main(String[] args){
Parcel3 p = new Parcel3();

Parcel3.Contents d = p.new Contents();

Parcel3.Destination d = p.new Destination(“Tasmania”)

}

}Use this code and into your compiler ,see the result.


有关inner-classup-casting

如今咱们试着将内部类up-casting 为一个interface,将会发现这个内部类的(其必定是某个接口的实现),可以彻底不可见,而且不可用。咱们获得的仅仅是指向其parent-class或者interfacereference,因此细节的东西得以实现隐藏。

相关文章
相关标签/搜索