Java内部类
[来源] 达内 [编辑] 达内 [时间]2012-11-01
创建内部类
创建内部类的时候只需要将内部类放到外部类的打括号内部就可以,如果需要实例化这个内部类,只要不是在外部类的非静态方法中,必须使用外部类名称加上内部类名称来表示这个类:
// : innerclasses/ // Returning a reference to an inner 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 = contents(); Destination d = to(dest); System.out.println(d.readLabel()); } public static void main(String[] args) { Parcel2 p = new Parcel2(); p.ship( "Tasmania" ); Parcel2 q = new Parcel2(); // Defining references to inner classes: Parcel2.Contents c = q.contents(); Parcel2.Destination d = ("Borneo"); } } /* Output: Tasmania */// :~
与外部类的连接
看起来内部类只是一种命名隐藏和代码组织的方式,并不是强制性的语法 但是,这里有另外一点需要注意。当你创建一个内部类的时候,这个内部类的对象具有对与创建这个内部类的对象的连接,它可以获取到创建它的类的对象中的成员,而不用其他特殊的标识。另外,内部类具有对外部类所有成员的访问权限,如下面的代码:
// : innerclasses/ // Holds a sequence of Objects. 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.print(selector.current() + " "); (); } } } /* Output: 0 1 2 3 4 5 6 7 8 9 *///:~
从上面的代码中我们可以看到内部类具有对外部类的所有成员的访问权限。内部类创建的时候必须与对应的外部类相关联,使得内部类能够抓取创建它的外部类的实例。
使用this和new
用外部类的名字跟上.this表示外部类对象的引用,如下:
// : innerclasses/ // Qualifying access to the outer-class object. public class DotThis { void f() { System.out.println("DotThis.f()"); } public class Inner { public DotThis outer() { return DotThis.this ; // A plain "this" would be Inner’s "this" } } public Inner inner() { return new Inner(); } public static void main(String[] args) { DotThis dt = new DotThis(); DotThis.Inner dti = dt.inner(); dti.outer().f(); } } /* Output: DotThis.f() */// :~
当你已经获得了某个外部类的实例的引用,当你需要创建这个外部类实例的一个内部类实例的时候,关键字,如下:
// : innerclasses/ // Using .new to create instances of inner classes. 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(); // Must use instance of outer class // to create an instance of the inner class: Parcel3.Contents c = p.new Contents(); Parcel3.Destination d = p.new Destination("Tasmania"); } } // /:~
内部类和上塑造型
在上塑造型到基类或者接口的时候,内部可可以完全隐藏他们自己,这种情况下只能获得接口或者基类的引用,而无法获得具体的对象类型。因为继承了基类或者接口的内部类,可以设置为外界不可见或不可用,这对于实现的隐藏非常有用。所有你获得的仅仅是一个对基类或者接口的引用:
// : innerclasses/ class Parcel4 { private class PContents implements Contents { private int i = 11; public int value() { return i; } } protected class PDestination implements Destination { private String label; private PDestination(String whereTo) { label = whereTo; } public String readLabel() { return label; } } public Destination destination(String s) { return new PDestination(s); } public Contents contents() { return new PContents(); } } public class TestParcel { public static void main(String[] args) { Parcel4 p = new Parcel4(); Contents c = p.contents(); Destination d = p.destination("Tasmania"); // Illegal -- can’t access private class: // ! Parcel4.PContents pc = PContents(); } } // /:~
方法和作用域中的内部类
内部类还可以定义在方法中,甚至是一个作用域中,这样做的原因有两点:首先,像前面所看到的,你需要继承某个接口,从而可以创建和返回某个引用;其次,当你需要解决某些复杂问题的时候,你在类中创建某些辅助对象,而这些对象并不许要对外可见。
下面这个例子在方法中创建了一个内部类,我们也称之为本地内部类:
// : innerclasses/ // Nesting a class within a method. public class Parcel5 { public Destination destination(String s) { class PDestination implements Destination { private String label; private PDestination(String whereTo) { label = whereTo; } public String readLabel() { return label; } } return new PDestination(s); } public static void main(String[] args) { Parcel5 p = new Parcel5(); Destination d = p.destination("Tasmania"); } } // /:~
下面的例子显示了在任意作用域内创建的内部类:
// : innerclasses/ // Nesting a class within a scope. public class Parcel6 { private void internalTracking(boolean b) { if (b) { class TrackingSlip { private String id; TrackingSlip(String s) { id = s; } String getSlip() { return id; } } TrackingSlip ts = new TrackingSlip("slip"); String s = ts.getSlip(); } // Can’t use it here! Out of scope: // ! TrackingSlip ts = new TrackingSlip("x"); } public void track() { internalTracking( true ); } public static void main(String[] args) { Parcel6 p = new Parcel6(); p.track(); } } // /:~
匿名内部类
如下是匿名内部类的一种写法:
// : innerclasses/ // Returning an instance of an anonymous inner class. public class Parcel7 { public Contents contents() { return new Contents() { // Insert a class definition private int i = 11; public int value() { return i; } }; // Semicolon required in this case } public static void main(String[] args) { Parcel7 p = new Parcel7(); Contents c = p.contents(); } } // /:~
其含义表示如下:
// : innerclasses/ // Expanded version of public class Parcel7b { class MyContents implements Contents { private int i = 11; public int value() { return i; } } public Contents contents() { return new MyContents(); } public static void main(String[] args) { Parcel7b p = new Parcel7b(); Contents c = p.contents(); } } ///:~
当需要向匿名内部类传递初始化参数的时候可以使用如下的写法:
// : innerclasses/ // Calling the base-class constructor. public class Parcel8 { public Wrapping wrapping(int x) { // Base constructor call: return new Wrapping(x) { // Pass constructor argument. public int value() { return super.value() * 47 ; } }; // Semicolon required } public static void main(String[] args) { Parcel8 p = new Parcel8(); Wrapping w = p.wrapping(10 ); } } ///:~
如果需要在匿名内部类中使用匿名内部类外部定义的对象,那么编译器需要在参数前面加上final关键字,如下:
// : innerclasses/ // An anonymous inner class that performs // initialization. A briefer version of . public class Parcel9 { // Argument must be final to use inside // anonymous inner class: public Destination destination(final String dest) { return new Destination() { private String label = dest; public String readLabel() { return label; } }; } public static void main(String[] args) { Parcel9 p = new Parcel9(); Destination d = p.destination("Tasmania"); } } // /:~
以内匿名内部类没有名称,那么如何执行匿名内部类的初始化函数呢?可以通过instance initialization实例初始化来执行初始化的工作,如下:
// : innerclasses/ // Creating a constructor for an anonymous inner class. import static net.mindview.util.Print.*; abstract class Base { public Base(int i) { print( "Base constructor, i = " + i); } public abstract void f(); } public class AnonymousConstructor { public static Base getBase(int i) { return new Base(i) { { print( "Inside instance initializer"); } public void f() { print( "In anonymous f()"); } }; } public static void main(String[] args) { Base base = getBase(47); base.f(); } } /* Output: Base constructor, i = 47 Inside instance initializer In anonymous f() */// :~
这里的i不用添加final关键字,因为它只是用来传递给基类的初始化函数,而在匿名内部类中并没有对他进行任何使用。
下面是parcel例子的一个匿名内部类版本:
// : innerclasses/ // Using "instance initialization" to perform // construction on an anonymous inner class. public class Parcel10 { public Destination destination(final String dest, final float price) { return new Destination() { private int cost; // Instance initialization for each object: { cost = Math.round(price); if (cost > 100) System.out.println( "Over budget!"); } private String label = dest; public String readLabel() { return label; } }; } public static void main(String[] args) { Parcel10 p = new Parcel10(); Destination d = p.destination("Tasmania", 101.395F); } } /* Output: Over budget! *///:~
从上面代码我们看到,可以将不能放在域中初始化的代码放到实例初始器中, 完成构造器的功能,但是实例构造器也有限制,它不能被重载,因此对于内部匿名类只能有一个构造其。另外一点还需要记住的是匿名内部类只能继承自来或者接口,不能同时继承类和接口,如果是继承接口的话,也只能继承自一个接口。
下面我们就用匿名内部类来修改工厂方法:
// : innerclasses/ import static net.mindview.util.Print.*; interface Service { void method1(); void method2(); } interface ServiceFactory { Service getService(); } class Implementation1 implements Service { private Implementation1() {} public void method1() {print("Implementation1 method1");} public void method2() {print("Implementation1 method2");} public static ServiceFactory factory = new ServiceFactory() { public Service getService() { return new Implementation1(); } }; } class Implementation2 implements Service { private Implementation2() {} public void method1() {print("Implementation2 method1");} public void method2() {print("Implementation2 method2");} public static ServiceFactory factory = new ServiceFactory() { public Service getService() { return new Implementation2(); } }; } public class Factories { public static void serviceConsumer(ServiceFactory fact) { Service s = fact.getService(); s.method1(); s.method2(); } public static void main(String[] args) { serviceConsumer(Implementation1.factory); // Implementations are completely interchangeable: serviceConsumer(Implementation2.factory); } } /* Output: Implementation1 method1 Implementation1 method2 Implementation2 method1 Implementation2 method2 *///:~
嵌套类
如果不许要内部类与包含它的类有联系的话,可以使用嵌套类,也就是用s tatic修饰的内部类。一般的内部类总是包含一个包含它的外部类的引用,但是静态的内部类你需要记住两点:你不许要外部类来创建内部类的实例;在嵌套类内不你不能使用非静态的外部类对象。同时,一般内部类的域和方法只能通过外部ulei访问,因此一般内部类中不能有静态数据,静态域或嵌套类。但是在静态内部类中这些都可以存在:
// : innerclasses/ // Nested classes (static inner classes). public class Parcel11 { private static class ParcelContents implements Contents { private int i = 11; public int value() { return i; } } protected static class ParcelDestination implements Destination { private String label; private ParcelDestination(String whereTo) { label = whereTo; } public String readLabel() { return label; } // Nested classes can contain other static elements: public static void f() {} static int x = 10; static class AnotherLevel { public static void f() {} static int x = 10; } } public static Destination destination(String s) { return new ParcelDestination(s); } public static Contents contents() { return new ParcelContents(); } public static void main(String[] args) { Contents c = contents(); Destination d = destination("Tasmania"); } } ///:~
另外,在一般内部类中可以使用this关键字来表示对外部类的引用,但是在静态内部类中没有类似与上面的this引用外部类的用法。
一般来讲,接口中是不能有实现功能的代码的,但是在接口中可以有内部类,任何在接口中定义的类都是自动为public和static的。因为接口中的类是静态的,因此它并没有违反接口的规则,仅仅是在同一个命名空间下防止了一个嵌套类,这个静态的内部类还可以对周围的接口进行实现:
// : innerclasses/ // {main: ClassInInterface$Test} public interface ClassInInterface { void howdy(); class Test implements ClassInInterface { public void howdy() { System.out.println( "Howdy!" ); } public static void main(String[] args) { new Test().howdy(); } } } /* Output: Howdy! */// :~
当你需要为接口的多种实现版本定义一些共同的实现代码的时候,使用接口内部类非常方便。
不管嵌套类嵌套了多少个层次,在嵌套类中总是可以获取到这个嵌套层次中任何一个类的成员,如下:
// : innerclasses/ // Nested classes can access all members of all // levels of the classes they are nested within. class MNA { private void f() {} class A { private void g() {} public class B { void h() { g(); f(); } } } } public class MultiNestingAccess { public static void main(String[] args) { MNA mna = new MNA(); MNA.A mnaa = mna.new A(); MNA.A.B mnaab = mnaa.new B(); mnaab.h(); } } // /:~
我们可以看到在MNAAB中调用方法g和f的时候不许要特殊的修饰,同时也示范了如何在多嵌套层次的类中如何创建不同层次上的对象,.new可以帮助获取正确的范围。
为何使用内部类
为何Java的开发者要费劲心思创建出内部类的语法呢?通常内部类都是继承 自一个基类或者接口的,通常在内部类中对创建它的外部类对象进行操作。因此你可以说内部类提供了一个针对外部类的窗口。但是如果仅仅是为了获得对接口的引用,那么为什么不直接让外部类继承自这个接口呢?那么内部类 承和外部类继承有什么不同呢?答案是我们并不是总是要继承自接口,有时候我们需要继承自基类。因此使用内部类的最主要原因是:每个内部类都可以继承自一个基类,因此,使用内部类继承基类的时候不会受到外部类是否已经继承了某个基类的限制,本质上也就是可以实现多基类继承。
当有两个接口需要某个类继承的时候,可以选择继承一个接口,然后在内 类继承另外一个接口,另外一种方法就是直接继承自这两个接口,选择哪个都可以实现你需要的功能;但是如果这两个不是接口,而是抽象类或者类呢?那么那么我们就必须选择第一种方法,继承自一个类,然后在内部类中继承自另外一个类,如下:
// : innerclasses/ // With concrete or abstract classes, inner // classes are the only way to produce the effect // of "multiple implementation inheritance."package innerclasses; class D {} abstract class E {} class Z extends D { E makeE() { return new E() {}; } } public class MultiImplementation { static void takesD(D d) {} static void takesE(E e) {} public static void main(String[] args) { Z z = new Z(); takesD(z); takesE(z.makeE()); } } ///:~
如果不许要解决多重:继承的问题,那么可以完全不许要内部类,但是使 了内部类的话你还可以获得其他的特点,如下:在外部类对象中可以创建多个内部类对象的实例,每个实例都有自己的信息,相互独立;在一个外部类中你可以定义多个内部类,每个继承自相同或不同的类;内部类的创建不依赖与外部类对象。
闭包指的是保存了创建它的作用域信息的对象。从这个定义来看,内部类 就是一种闭包,内部类保存了对外部创建类的引用,并且可以引用所有的成员,即使是private修饰的成员。另外,Java中有一种类似与指针机制的参数使用称之为回调。通过回调可以在一些类中反向调用创建这个对象中的一些信息。但是Java中对指针的使用非常谨慎,因此在语言中并没有包含指针的概念。闭包可以有效地解决这个问题,如下面的代码:
// : innerclasses/ // Using inner classes for callbacks package innerclasses; import static net.mindview.util.Print.*; interface Incrementable { void increment(); } // Very simple to just implement the interface: class Callee1 implements Incrementable { private int i = 0; public void increment() { i++ ; print(i); } } class MyIncrement { public void increment() { print("Other operation"); } static void f(MyIncrement mi) { mi.increment(); } } // If your class must implement increment() in // some other way, you must use an inner class: class Callee2 extends MyIncrement { private int i = 0; public void increment() { super.increment(); i++ ; print(i); } private class Closure implements Incrementable { public void increment() { // Specify outer-class method, otherwise // you’d get an infinite recursion: Callee2.this .increment(); } } Incrementable getCallbackReference() { return new Closure(); } } class Caller { private Incrementable callbackReference; Caller(Incrementable cbh) { callbackReference = cbh; } void go() { callbackReference.increment(); } } public class Callbacks { public static void main(String[] args) { Callee1 c1 = new Callee1(); Callee2 c2 = new Callee2(); MyIncrement.f(c2); Caller caller1 = new Caller(c1); Caller caller2 = new Caller(c2.getCallbackReference()); caller1.go(); caller1.go(); caller2.go(); caller2.go(); } } /* Output: Other operation 1 1 2 Other operation 2 Other operation 3 */// :~
内部类的另外一种用法就是控制框架,应用框架是指一个或者一系列类,能够处理一系列一般性的问题。在使用框架的时候通常继承或者扩展框架里面类从而解决特定的问题。控制框架主要是针对事件响应的系统,主要的应用场景有用户界面。
首先我们创建一个事件基类:
// : innerclasses/controller/ // The common methods for any control event. package innerclasses.controller; public abstract class Event { private long eventTime; protected final long delayTime; public Event(long delayTime) { this.delayTime = delayTime; start(); } public void start() { // Allows restarting eventTime = System.nanoTime() + delayTime; } public boolean ready() { return System.nanoTime() >= eventTime; } public abstract void action(); } // /:~
下面是控制框架的主体部分,分离了不变和变化的部分,不便的部分已经封装到控制器内,变化的部分可以分散到不同的Event基类的派生类当中:
// : innerclasses/controller/ // The reusable framework for control systems. package innerclasses.controller; import java.util.*; public class Controller { // A class from java.util to hold Event objects: private List<Event> eventList = new ArrayList<Event>(); public void addEvent(Event c) { eventList.add(c); } public void run() { while(eventList.size() > 0 ) // Make a copy so you’re not modifying the list // while you’re selecting the elements in it: for (Event e : new ArrayList<Event>(eventList)) if (e.ready()) { System.out.println(e); e.action(); eventList.remove(e); } } } // /:
这个时候就可以使用内部类了,使用内部类可以一方面将控制框架集中到一个类中,内部类可以用来扩展不同的action方法;另外一方面使用内部类可以方便的获得外部类的成员,从而更加容易理解,如下:
// : innerclasses/ // This produces a specific application of the // control system, all in a single class. Inner // classes allow you to encapsulate different // functionality for each type of event.import innerclasses.controller.* ; public class GreenhouseControls extends Controller { private boolean light = false; public class LightOn extends Event { public LightOn(long delayTime) { super (delayTime); } public void action() { // Put hardware control code here to // physically turn on the light. light = true ; } public String toString() { return "Light is on"; } } public class LightOff extends Event { public LightOff(long delayTime) { super (delayTime); } public void action() { // Put hardware control code here to // physically turn off the light. light = false ; } public String toString() { return "Light is off"; } } private boolean water = false; public class WaterOn extends Event { public WaterOn(long delayTime) { super(delayTime); } public void action() { // Put hardware control code here. water = true ; } public String toString() { return "Greenhouse water is on"; } } public class WaterOff extends Event { public WaterOff(long delayTime) { super (delayTime); } public void action() { // Put hardware control code here. water = false ; } public String toString() { return "Greenhouse water is off"; } } private String thermostat = "Day"; public class ThermostatNight extends Event { public ThermostatNight(long delayTime) { super (delayTime); } public void action() { // Put hardware control code here. thermostat = "Night"; } public String toString() { return "Thermostat on night setting"; } } public class ThermostatDay extends Event { public ThermostatDay(long delayTime) { super (delayTime); } public void action() { // Put hardware control code here. thermostat = "Day"; } public String toString() { return "Thermostat on day setting"; } } // An example of an action() that inserts a // new one of itself into the event list: public class Bell extends Event { public Bell(long delayTime) { super (delayTime); } public void action() { addEvent(new Bell(delayTime)); } public String toString() { return "Bing!"; } } public class Restart extends Event { private Event[] eventList; public Restart(long delayTime, Event[] eventList) { super (delayTime); this.eventList = eventList; for (Event e : eventList) addEvent(e); } public void action() { for (Event e : eventList) { e.start(); // Rerun each event addEvent(e); } start(); // Rerun this Event addEvent(this ); } public String toString() { return "Restarting system"; } } public static class Terminate extends Event { public Terminate(long delayTime) { super (delayTime); } public void action() { (0); } public String toString() { return "Terminating"; } } } ///:~
下面是对控制框架的使用:
// : innerclasses/Greenhouse // Configure and execute the greenhouse system. // {Args: 5000} import innerclasses.controller.* ; public class GreenhouseController { public static void main(String[] args) { GreenhouseControls gc = new GreenhouseControls(); // Instead of hard-wiring, you could parse // configuration information from a text file here: gc.addEvent(gc.new Bell(900)); Event[] eventList = { gc. new ThermostatNight(0 ), gc. new LightOn(200 ), gc. new LightOff(400 ), gc. new WaterOn(600 ), gc. new WaterOff(800 ), gc. new ThermostatDay(1400 ) }; gc.addEvent(gc. new Restart(2000 , eventList)); if(args.length == 1 ) gc.addEvent(new GreenhouseControls.Terminate(new Integer(args[0 ]))); (); } } /* Output: Bing! Thermostat on night setting Light is on Light is off Greenhouse water is on Greenhouse water is off Thermostat on day setting Restarting system Terminating *///:~
内部类继承
因为内部类的构造器必须引用包含它的外部类对象,因此在继承内部类的时候有一点点复杂。因此对与外部类的实例必须在派生类中初始化,因为在派生类中没有默认的外部类的实例,因此必须显示初始化:
// : innerclasses/ // Inheriting an inner class. class WithInner { class Inner {} } public class InheritInner extends WithInner.Inner { //! InheritInner() {} // Won’t compile InheritInner(WithInner wi) { wi. super(); } public static void main(String[] args) { WithInner wi = new WithInner(); InheritInner ii = new InheritInner(wi); } } ///:~
内部类是否能够重写
如果要扩展外部类,继承之后重写内部类,会怎么样呢?
// : innerclasses/ // An inner class cannot be overriden like a method. import static net.mindview.util.Print.*; class Egg { private Yolk y; protected class Yolk { public Yolk() { print("Egg.Yolk()"); } } public Egg() { print( "New Egg()"); y = new Yolk(); }
} public class BigEgg extends Egg { public class Yolk { public Yolk() { print("BigEgg.Yolk()"); } } public static void main(String[] args) { new BigEgg(); } } /* Output: New Egg() Egg.Yolk() */// :~
我们可以看到继承外部类并且重写内部类实际上并没有做任何事情。下面的例子告诉我们继承外部类并且重写内部类的时候,两个内部类是分开的尸体,各有自己的命名空间,但是可以显式的继承内部类:
// : innerclasses/ // Proper inheritance of an inner class. import static net.mindview.util.Print.*; class Egg2 { protected class Yolk { public Yolk() { print("Egg2.Yolk()"); } public void f() { print("Egg2.Yolk.f()");} } private Yolk y = new Yolk(); public Egg2() { print("New Egg2()"); } public void insertYolk(Yolk yy) { y = yy; } public void g() { y.f(); } } public class BigEgg2 extends Egg2 { public class Yolk extends Egg2.Yolk { public Yolk() { print("BigEgg2.Yolk()" ); } public void f() { print("BigEgg2.Yolk.f()"); } } public BigEgg2() { insertYolk( new Yolk()); } public static void main(String[] args) { Egg2 e2 = new BigEgg2(); e2.g(); } } /* Output: Egg2.Yolk() New Egg2() Egg2.Yolk() BigEgg2.Yolk() BigEgg2.Yolk.f() */// :~
本地内部类
之前提到过内部类可以定义在语句块中,通常是在方法体中。一个本类内部类不能拥有可见性标识,因为它不是外部类的一部分,但是它能够获取到当前语句块中的final变量和外部类的所有成员:
// : innerclasses/ // Holds a sequence of Objects. import static net.mindview.util.Print.*; interface Counter { int next(); } public class LocalInnerClass { private int count = 0; Counter getCounter( final String name) { // A local inner class: class LocalCounter implements Counter { public LocalCounter() { // Local inner class can have a constructor print("LocalCounter()"); } public int next() { printnb(name); // Access local final return count++ ; } } return new LocalCounter(); } // The same thing with an anonymous inner class: Counter getCounter2(final String name) { return new Counter() { // Anonymous inner class cannot have a named // constructor, only an instance initializer: { print( "Counter()"); } public int next() { printnb(name); // Access local final return count++ ; } }; } public static void main(String[] args) { LocalInnerClass lic = new LocalInnerClass(); Counter c1 = lic.getCounter("Local inner "), c2 = lic.getCounter2("Anonymous inner "); for(int i = 0; i < 5; i++) print(()); for (int i = 0; i < 5; i++) print(()); } } /* Output: LocalCounter() Counter() Local inner 0 Local inner 1 Local inner 2 Local inner 3 Local inner 4 Anonymous inner 5 Anonymous inner 6 Anonymous inner 7 Anonymous inner 8 Anonymous inner 9 *///:~
因为本地内部类不能在方法外部使用,因此使用本地内部类而不使用匿名内部类的原因是你是否需要构造其或者重载的构造其,因为匿名内部类只能使用实例化初始。
内部类标识
每个类编译之后都会产生一个.clas s文件,里面包含了对象的相关信息,那么内部类呢,是否也是一个单独的clas文件呢?是的,但是文件的名称有着严格的格式,是外部类名称加上$再加上内部类的名称,例如上面的文件编译后产生如下class文件:
Counter.class
LocalInnerClass$l.class
LocallnnerClassSlLocalCounter.class
LocallnnerClass.class
如果内部类是匿名的,那么编译器仅仅是用数字表示匿名内部类的名称,如果有嵌套的内部类,那么将直接在后面继续添加$和内部类的名称即可。