Welcome 微信登录
编程资源 图片资源库 蚂蚁家优选 PDF转换器

首页 / 操作系统 / Linux / Java内部类

一、 内部类概念一个类定义在另一个类的内部,这个类就叫做内部类。代码示例:
public class TestClass {/*内部类,可以用private/public/protected修饰*/private class InnerClass{}public static void main(String[] args) {}}
内部类作为外部类的一个成员,并且依附于外部类而存在的。内部类可为静态,可用protected和private修饰(而外部类只能使用public和缺省的包访问权限)。内部类主要有以下几类:成员内部类、局部内部类、静态内部类、匿名内部类。内部类生成的class文件名称是外部类类名加上”$”再加上内部类类名,如上内部类就是OuterClass$InnerClass.class。除匿名内部类之外,其他的内部类都是在编译时直接生成而不是在调用时才生成。匿名内部类由于没有类名因此只有在运行时才会生成,而且只能创建一个实例。为什么需要内部类?典型的情况是,内部类继承自某个类或实现某个接口,内部类的代码操作创建其的外围类的对象。所以你可以认为内部类提供了某种进入其外围类的窗口。使用内部类最吸引人的原因是:每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”。二、 内部类的定义位置正如上述所列的几种内部类:成员内部类、局部内部类、静态内部类、匿名内部类,这几种内部类的区分正是由于定义的位置不同。成员内部类:定义在外部类的内部,非方法内,相当于外部类的一个成员变量。局部内部类:定义在外部类的方法中,可以使静态方法和普通方法,注意局部内部类的修饰符只能是abstract和final。静态内部类:又叫嵌套类,是定义位置同成员内部类,但是使用static修饰符修饰。静态内部类相当于外部类的静态成员变量(后面介绍)。匿名内部类:主要出现在方法内,没有类名,当然也就没有构造方法。(后面介绍)代码示例:
public class TestClass {/* 成员内部类,可以用private/public/protected修饰,不可以定义静态成员变量 */protected class InnerClass01 {private String myName = "Vicky" ;}/* 静态内部类,可以用private/public/protected修饰,可以有静态变量以及静态方法 */public static class StaticInnerClass {public static String myName = "Vicky";public static void main(String[] args) {}}public void method() {/* 普通方法内的局部内部类,只能使用abstract/final修饰,可以定义静态成员变量 */abstract class InnerClass02 {}}public static void method02() {/* 静态方法内的局部内部类,只能使用abstract/final修饰,可以重名 */final class InnerClass01 {}}public static void main(String[] args) {/*匿名内部类*/Thread th = new Thread(new Runnable(){@Overridepublic void run() {}}) ;}}
注意:非静态内部类(成员内部类和局部内部类)外其他类型的内部类都不能定义静态成员,包括变量以及方法;静态内部类可以有静态方法(包括main())和静态变量。匿名内部类由于没有类名,故也没有构造方法,但可以非静态定义变量以及方法。三、 普通内部类(成员内部类和局部内部类)的实例化方式内部类作为定义在外部类的成员变量,如同变量的使用一样,需要一个外部类的实例来调用,除静态内部类外。注意在不同的位置实例化内部类的方式有不同的实例化方式。代码示例:
public class OuterClass {/* 外部类的变量可以使用内部类,使用内部类类名和new就可以实例化,同一般类的实例化 */private InnerClass innerVar = new InnerClass();/* 成员内部类,可以用private/public/protected修饰,不可以定义静态成员变量 */protected class InnerClass {private String myName = "Vicky";}public void method() {/* 普通方法内直接使用内部类类名和new就可以实例化,同一般类的实例化 */InnerClass inner01 = new InnerClass();/* 普通方法内的局部内部类,只能使用abstract/final修饰,可以定义静态成员变量 */final class InnerClass02 {}/* 方法内的局部内部类,只能在方法内部使用,就如在方法内定义的变量只能在方法内部使用一样*/InnerClass02 inner = new InnerClass02() ;}public static void method02() {/* 显然静态方法中不能使用非静态内部类 */}public static void main(String[] args) {/* 我们知道main()方法和它所在的类没有任何关系,因此在main()方法中实例化内部类就同在其他类中一样,这样方便些 */// 首先实例化外部类,得到一个外部类对象OuterClass outer = new OuterClass();// 通过外部类的对象实例化内部类OuterClass.InnerClass inner = outer.new InnerClass();}}
我们可以看出定义在方法内的局部内部类只能在方法内部使用,就如定义在方法内部的变量一样。四、 普通内部类(成员内部类和局部内部类)使用外部类的域普通内部类可以直接访问外部类的所有域(包括private修饰的成员),如变量、方法等(但是有些地方需要注意)。普通内部类在实例化时会被自动添加一个指向外部类的引用,实际上是编译器在编译时为内部类构造了一个带有外部类类型参数的构造方法,如
public InnerClass(OuterClass outer){}
通过这个构造方法普通内部类就可以得到外部类的引用也就可以使用外部类的所有域。普通内部类(成员内部类/局部内部类)可以直接使用外部类包括静态成员变量在内的所有域(包括private修饰的)。静态内部类不是这样(后面介绍)。代码示例:
public class OuterClass {private String myName = "Vicky";private static int myAge = 21;public void method() {System.out.println("you are invoking outer class"s common method ...");}public static void staticMethod() {System.out.println("you are invoking outer class"s static method ...");}public void method01(){/* 局部类变量 */final class InnerClass {/* 内部类变量使用外部类普通变量 */private String inner_myName = myName;/* 内部类变量使用外部类静态变量 */private int inner_myAge = myAge;public void inner_method() {System.out.println("myName--" + inner_myName + ";myAge--"+ inner_myAge);/* 内部类使用外部类普通方法 */method();/* 内部类使用外部类静态方法 */staticMethod();}}}/* 成员内部类*/private class InnerClass {/* 内部类变量使用外部类普通变量 */private String inner_myName = myName;/* 内部类变量使用外部类静态变量 */private int inner_myAge = myAge;public void inner_method() {System.out.println("myName--" + inner_myName + ";myAge--"+ inner_myAge);/* 内部类使用外部类普通方法 */method();/* 内部类使用外部类静态方法 */staticMethod();}}public static void main(String[] args) {OuterClass outer = new OuterClass() ;OuterClass.InnerClass inner = outer.new InnerClass() ;inner.inner_method() ;}}
成员内部类和局部内部类在使用外部类的域时是一样的,可以直接调用。