内部类:如果A类需要直接访问B类中的成员,而B类又需要建立A类的对象。这时,为了方便设计和访问,直接将A类定义在B类中。就可以了。A类就称为内部类。内部类可以直接访问外部类中的成员。而外部类想要访问内部类,必须要建立内部类的对象。
在Java中内部类主要分为成员内部类、局部内部类、匿名内部类、静态内部类。
一、成员内部类
成员内部类也是最普通的内部类,它是外围类的一个成员,所以他是可以无限制的访问外围类的所有 成员属性和方法,尽管是private的,但是外围类要访问内部类的成员属性和方法则需要通过内部类实例来访问。
在成员内部类中要注意两点:
第一:成员内部类中不能存在任何static的变量和方法(有静态变量和静态方法就不是成员内部类了!);
第二:成员内部类是依附于外围类的,所以只有先创建了外围类才能够创建内部类。
第三:成员内部类中可以访问外部类中所有的成员(变量,方法),包含私有成员,如果在内部类中定义有和外部类同名的实例变量,访问:OuterClass.this.outerMember;
第四:外部类的外部/外部类的静态方法:new Outer().new Inner(); 外部类的实例方法:new Inner(); this.new Inner();
二、局部内部类
有这样一种内部类,它是嵌套在方法和作用于内的,对于这个类的使用主要是应用与解决比较复杂的问题,想创建一个类来辅助我们的解决方案,到那时又不希望这个类是公共可用的,所以就产生了局部内部类,局部内部类和成员内部类一样被编译,只是它的作用域发生了改变,它只能在该方法和属性中被使用,出了该方法和属性就会失效。
局部内部类可以访问的外部类的成员根据所在方法体不同。
如果在静态方法中:可以访问外部类中所有静态成员,包含私有
如果在实例方法中: 可以访问外部类中所有的成员,包含私有。
局部内部类可以访问所在方法中定义的局部变量,但是要求局部变量必须使用final修饰。
public class Parcel5 { public Destionation destionation(String str){ class PDestionation implements Destionation{ private String label; private PDestionation(String whereTo){ label = whereTo; } public String readLabel(){ return label; } } return new PDestionation(str); } public static void main(String[] args) { Parcel5 parcel5 = new Parcel5(); Destionation d = parcel5.destionation("chenssy"); } }
三、匿名内部类
1、 匿名内部类是没有访问修饰符的。(没有名字的局部内部类)
2、 new 匿名内部类,这个类首先是要存在的。如果我们将那个InnerClass接口注释掉,就会出现编译出错。
3、 注意getInnerClass()方法的形参,第一个形参是用final修饰的,而第二个却没有。同时我们也发现第二个形参在匿名内部类中没有使用过,所以当所在方法的形参需要被匿名内部类使用,那么这个形参就必须为final。
4、 匿名内部类是没有构造方法的。因为它连名字都没有何来构造方法。
四、静态内部类
使用static修饰的内部类我们称之为静态内部类,不过我们更喜欢称之为嵌套内部类。静态内部类与非静态内部类之间存在一个最大的区别,我们知道非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围内,但是静态内部类却没有。没有这个引用就意味着:
1.它的创建是不需要依赖于外围类的。
2.它不能使用任何外围类的非static成员变量和方法。
3.声明在类体部,方法体外,并且使用static修饰的内部类
4.访问特点可以类比静态变量和静态方法
5.在外部类的外部构建内部类的实例new Outer.Inner();在外部类的内部构建内部类的实例new Inner();
6.静态内部类体部可以直接访问外部类中所有的静态成员,包含私有
public class OuterClass { private String sex; public static String name = "chenssy"; /** *静态内部类 */ static class InnerClass1{ /* 在静态内部类中可以存在静态成员 */ public static String _name1 = "chenssy_static"; public void display(){ /* * 静态内部类只能访问外围类的静态成员变量和方法 * 不能访问外围类的非静态成员变量和方法 */ System.out.println("OutClass name :" + name); } } /** * 非静态内部类 */ class InnerClass2{ /* 非静态内部类中不能存在静态成员 */ public String _name2 = "chenssy_inner"; /* 非静态内部类中可以调用外围类的任何成员,不管是静态的还是非静态的 */ public void display(){ System.out.println("OuterClass name:" + name); } } /** * @desc 外围类方法 * @author chenssy * @data 2013-10-25 * @return void */ public void display(){ /* 外围类访问静态内部类:内部类. */ System.out.println(InnerClass1._name1); /* 静态内部类 可以直接创建实例不需要依赖于外围类 */ new InnerClass1().display(); /* 非静态内部的创建需要依赖于外围类 */ OuterClass.InnerClass2 inner2 = new OuterClass().new InnerClass2(); /* 方位非静态内部类的成员需要使用非静态内部类的实例 */ System.out.println(inner2._name2); inner2.display(); } public static void main(String[] args) { OuterClass outer = new OuterClass(); outer.display(); } } ---------------- Output: chenssy_static OutClass name :chenssy chenssy_inner OuterClass name:chenssy
附:
内部类编译后的文件名为:“外部类名$内部类名.java”;
为什么内部类可以直接访问外部类中的成员呢? 那是因为内部中都持有一个外部类的引用。这个是引用是 外部类名.this
内部类可以定义在外部类中的成员位置上(成员内部类),
也可以定义在外部类中的局部位置上(局部内部类)。 当内部类被定义在局部位置上,只能访问局部中被final修饰的局部变量。
想要定义匿名内部类:需要前提,内部类必须继承一个类或者实现接口。
匿名内部类的格式:new 父类名&接口名(){ 定义子类成员或者覆盖父类方法 }.方法。
匿名内部类的使用场景: 当函数的参数是接口类型引用时,如果接口中的方法不超过3个。可以通过匿名内部类来完成参数的传递。 其实就是在创建匿名内部类时,该类中的封装的方法不要过多,最好两个或者两个以内。