原则:在拥有外部类对象之前是不可能创建内部类对象的。
因为内部类对象会暗暗地连接到创建它的外部类对象上。但是注意嵌套类(静态内部类)是不需要对外部类对象的引用。
内部类的使用1:(向上转型)
interface Destination{ String readLabel(); } interface Contents{ int value(); } class Parce{ public class Testnew{ public Parce outer(){ return Parce.this;//外部类的.this用法 } } protected class PDestination implements Destination{ private String label; private PDestination(String str){ label = str; } public String readLabel(){ return label; } } //private 说明了在Parce类外部是无法访问内部类PContents private class PContents implements Contents{ private int i = 5; public int value(){return i;} } public Destination getDestination(String str){ return new PDestination(str); } public Contents getContents(){ return new PContents(); } } public class Test { public static void main(String[] str){ Parce p = new Parce(); Contents c = p.getContents(); Destination d= p.getDestination("test"); //在外部访问public的内部类,必须有外部类实例 Parce.Testnew t = p.new Testnew(); //OK //p.TestNew t = p.new TestNew();//ERROR //Parce.Testnew t = p.new Parce.Testnew();//ERROR } }
方法和作用域的内部类:(局部内部类)
interface Destination{ String readLabel(); } class Parce{ //方法中的内部类 /* PDestination类是getDestination方法中的一部分,而不是Parce类中的一部分。 所以在getDestination之外是无法访问PDestination类的。 都是这并不意味一旦getDestination方法执行完毕,PDestination就不可用了。 */ public Destination getDestination(String str){ class PDestination implements Destination{ private String label; private PDestination(String str){ label = str; } public String readLabel(){ return label; } } return new PDestination(str); } //作用域中的内部类 private void intertest(boolean b){ /* IntertestA类嵌入if语句的作用域内,并不是说该类的创建时有条件的,它实际上和 别的类一起编译过了 */ if (b){ class IntertestA{ private String id; IntertestA(String s){id = s;} String getID(){return id;} } IntertestA it = new IntertestA("hello"); String s = it.getID(); } //IntertestA it = new IntertestA("hello");//ERROR //超出了IntertestA类的作用范围 } public void test() {intertest(true);} } public class Test{ public static void main(String[] str){ Parce p = new Parce(); Destination d = p.getDestination("test"); p.test(); } }
匿名内部类:
interface Contents{ int value(); } class Parce{ public Contents getContents(){ return new Contents(){//匿名内部类:创建一个继承于Contents的匿名类的对象 private int i = 5; public int value(){return i;} }; } } public class Test{ public static void main(String[] str){ Parce p = new Parce(); Contents c = p.getContents(); } }
实际上上面的匿名内部类结构等价于:
class Parce{ class MyContents implements Contents{ private int i = 5; public int value(){return i;} } public Contents getContents(){ return new MyContents(); } }
匿名内部类初始化操作怎么处理:
因为没有名字,所以不可能有构造器,所以我们利用实例初始化来做到和构造器相同的效果。
abstract class Base{ public Base(int i){ System.out.println("Base:i = " + i); } public abstract void f(); } class Base1{ } public class Test{ //i只是传递给匿名内部类的基类的构造器,没有在匿名内部类中使用,所以i不用时final //如果在匿名内部类中使用参数就必须是final public static Base getBase(int i){ return new Base(i){//匿名内部类 {//内部类的实例初始化 System.out.println("inside instance Base"); } public void f(){ System.out.println("Test f fun"); } }; } //如果在匿名内部类中使用参数就必须是final来修饰传入的参数 public Base1 testBase1(final int i){ return new Base1(){ private int j =i; public int getLabel(){return j;} }; } public static void main(String[] str){ Base b = getBase(47); b.f(); } }
//
输出:
Base:i = 47
inside instance Base
Test f fun
嵌套类(static内部类)和普通内部类区别:
(1) 普通内部类隐式地保存了一个引用,指向创建它的外围对象(特殊的this引用),而嵌套类没有
(2) 要创建嵌套类的对象,并不需要其外围类的对象
(3) 不能从嵌套类的对象中访问非static的外围类对象
(4) 普通内部类不能有static数据和字段,但是嵌套类可以有。
内部类使用的必要性:
1每个内部类都能独立继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。相对外围类继承接口,共享性好很多。
2接口解决了部分问题,而内部类有效的实现了”多重继承”
特性:
1. 内部类可以有多个实例,每个实例都有自己的状态信息,并且与外围类对象的信息相互独立。
2. 在单个外围类中,可以让多个内部类以不同的方式实现同一个接口或继承同一个类
3. 创建内部类对象的时刻并不依赖外部类对象的创立。
4. 内部类没令人迷惑的”is-a”关系
使用局部内部类替代匿名内部类的情况:
1.需要一个已命名的构造器或者需重载构造器,而匿名内部类只能实例初始化
2.需要不止一个该内部类的对象
内部类标示符:
一个类就会产生一个.class文件。
Test.class //Test类
Test$1.class //匿名内部类会产生一个简单的数字作为标示符
Parce$Pdestination.class //局部内部类直接在$后面加上类名就Ok了