内部类
一、创建内部类
public class Test { //第一个内部类 class Destination{ private int i = 11; public int value(){return i;} } //第二个内部类 class Parcel{ private String label; //构造方法 Parcel(String whereTo){ label = whereTo; } } }
二、内部类的作用(一)——自动拥有外围类所有成员的访问权限
public class Test { private Object[] items; class Destination{ private int i = 11; public int value(){return i;} //内部类可以直接调用外部类的成员变量(无视修饰符) public Object current(){ return items[i]; } } ... }
所以内部类(非static类时)自动拥有对其外围类所有成员的访问权限。
原理:当某个外部类对象创建一个内部类对象的时候,内部类对象会秘密捕获指向外部类的引用,然后访问外部类,就是通过这个引用选择外部成员。
三、内部类的作用(二)——获取对外部类对象的引用.this/.new
使用.this的作用
public class Test { class Destination{ //获取引用之后,可调用其方法 Destination(){ Test.this.take(); } //内部类获取外部类的引用 public Test getTest(){ return Test.this; } } public void take(){ } }
使用.new的作用
public class NestingInterfaces { public static void main (String args[]){ Test test = new Test(); //通过.new方法 创建Test的内部类 Test.Destination dest = test.new Destination(); } }
注:但是如果你使用的是嵌套类(内部类设为static)就不需要对外部类对象的引用 例:DotNew.Inner do = new DotNew.Inner();
四、内部类与向上转型
当将内部类向上转型为其基类,尤其是转型为一个接口的时候。内部类能够使某个接口的实现完全不可见,并且不可用。(隐藏实现细节)
示例:
//接口类 public interface Contents{ int value(); } //实现类 class Pacel { //创建内部类继承接口 private class PContents implemetns Contents{ private int i = 11; public int value(){ return i; } } //获取内部类并向上转型 public Contents getContent(){ return new PContents; } } //运行类 class Test{ public static void main(String args[]){ //创建类 Pacel p = new Pacel(); Contents content = p.getContene(); //这样就封装了接口的实现。 } }
五、在方法和作用域内的内部类
举例:
//接口类 public interface Destination{ String readLabel(); } //实现类 class Parcel1{ //方法 public Destination getDestination(String label){ //在方法内创建内部类,继承接口 class PDestination implements Destination{ public String readLabel(){ return label; } } //内部类向上转型返回Destination reuturn new PDestionation; } }
作用:1.实现了某类型的接口,于是可以创建并返回其引用
2.解决一个复杂的问题,创建一个辅助类,但又不想这个类被公共使用。
六、匿名类
举例:(使用默认构造器生成Contents)
public interface Contents{ public int value(); } public class Parcel{ public Contents contents(){ //创建内部类 return new Contents(){ private int i=11; public int value(){ return i; } } } //实现 public static void main(String[] args){ Parcel parcel = new Parcel; Contents content = parcel.contents(); } }
解析:新建接口对象,并重写接口的方法
使用有参数的构造器:
//初始类 public class Wrappping { private int i; public Wrapping (int x){ i = x; } public int value(){ return i; } } class Parcel3{ public Wrapping getWrapping(int x){ //调用父类的构造方法 return new Wrapping(x){ //重写父类的value()方法 public int value(){ //调用父类的value()方法 return super.value()*24; } }; } }
解析:新建类对象,调用新对象的构造器,并重写方法,调用其父类的构造方法(被当做了一个公共的接口)
细节
①、如果定义了一个内部类,并需要调用外部定义的对象的时候,则编译器会将其引用参数为final。
②、匿名类不可能有命名构造器,所以说如何创造构造器的效果。
举例:
class Parcel{ public Destination getDestination(final String dest,final float price){ return new Destination(){ private int cost; //在{}内根据传递而来的参数 初始化值。 { cost = Math.round(price); if (cost>100){ System.out.println("Nice"); } } //直接获取方法的参数,初始化值 private String label = dest; public String readLabel(){ return dest; } } } }
③、工厂方法 (略,以后有空再看)
七、嵌套类
定义:如果不需要内部对象与其外围类对象之间有联系,可以特地将内部类设置为static。
意义:①、不能从嵌套类中的对象访问非静态外部类的对象。(可以说,不含有外部类的指针了)
与普通内部类作对比:①、嵌套类可以有static数据和字段,二普通类不能有 ②、嵌套类还可以嵌套类,但是普通类不可以。
举例:
public class Parcel{ protected static class ParcelDestional implements Destination{ //静态数据 private static String label = "fine"; public String readLabel(){ return labe; } //静态方法 public static void f(){ System.out.println("asd"); } //嵌套嵌套类 static class H{ } } }
(一)接口内部的类
解释:嵌套类可以作为接口的一部分,甚至可以在类内部实现外部接口。
举例:
public interface Pacel{ void howdy(){ } //在接口中创建嵌套类,并继承该接口,重写接口方法 class Test implements Pacel{ public void howdy(){ System.out.println("asd"); } } }
八、为什么需要内部类
理由:一般来说内部类继承自某个类或者实现某个接口,内部类的代码操作用来创建它的外围类的对象。(将内部类的对象放置在外围类中)。
②、内个内部类都能独立的继承自一个(接口的)实现,无论外围类是否已经继承接口实现,对内部类都不影响。(不过能用外部类继承接口就用外部类)
③、可以使用外围类的private方法
其他特性:
①、内部类可以有多个实例,信息与其外围类对象信息对立。
②、在单个外围类中,可以让多个内部类实现统一接口,或继承同一类
③、创建内部类对象不依赖于外围类对象的创建。(指嵌套类)
九、闭包与回调
闭包:是个可调用对象,记录信息,这些信息来自创建它的作用域。(内部类就是面向对象的闭包:不仅包含外围类对象的信息,还有外围类的指针)
问题:有Callee继承自MyIncrement,但是还需要添加一个Increment接口中两个中含有相同的方法,且方法作用各不同,所以必须两个一起实现,就得用到内部类
/*前提条件*/ class MyIncrement { public void increment(){print("Other operation");} static void f(MyIncrement mi) {mi.increment()}; } interface Increment{ void increment(); }
class Callee extends MyIncrement{ private int i=0; public void increment(){ ++i; System.out.println(i); } //内部类 private class Course implements Increment{ public void increment(){ Callee.this.increment(); } } //返回内部类 public Increment getIncrement(){ return new Course; } } //统一类调用内部类的Increment的方法 class Calleer { private Increment in = null; public Caller (Increment increment){ in = increment; } public void go (){ in.increment(); } } class Test{ public static void main(String[] args){ //调用自身的方法 Callee c = new Callee(); c.increment(); //调用内部类的方法 Calleer cc = new Calleer(c); cc.go(); } }
作用:①、Closure实现了Incrementable,提供了一个返回Callee的钩子,无论谁获得Increment引用,都只能调用increment()。
②、Calleer对象可以使用Increment回调Callee对象。