例如一个类cow,它需要组合一个cowLeg类,cowLeg类只有在cow里才有意义,离开cow没有任何意义。所以我们可以把cowLeg定义为cow的一个内部类。
作用:
①更好的封装。内部类类除了public和包以外,还可使用private,protected,static修饰符,因此可以提供更好的安全性。
②内部类成员可以直接访问外部类的私有数据。外部类不能访问内部类的实现细节,例如内部类的成员变量。
③匿名内部类适合用于创建那些仅需要使用一次的类,如“接口”中的addCommand类和printCommand类都可定义为匿名内部类。
注意:非静态内部类不能拥有静态成员。
内部类的分类:
1.非静态内部类:
非静态内部类访问某个变量时的顺序①查找该方法内的局部变量②在该方法所在的内部类中查找成员变量③在外部类中查找④编译报错
非静态内部类的成员只在非静态内部类范围内是可知的,并不能被外部类直接使用。如果外部类需要访问非静态内部类的成员,必须显式创建非静态内部类对象来调用访问其实例变量。
java不允许在非静态内部类里定义静态成员。
2.静态内部类:
static修饰内部类,则这个内部类就属于类本身,(而不属于某个对象)。
静态内部类可以包含静态成员,也可以包含非静态成员。
根据静态成员不能访问非静态成员的原则,静态内部类不能访问外部类的实例成员。(即使是静态内部类的实例方法也不能访问外部类的实例成员)。
外部类依然不能直接访问静态内部类的成员,但是可以通过静态内部类的类名作为调用者来访问静态内部类的类成员。
java允许接口中定义内部类,但是必须(默认也是)是public static 修饰。即接口内部类施能是静态内部类。
3.使用内部类:
外部类以外使用非静态内部类:
在外部类以外使用内部类,内部类完整的类名应该是OuterClass.InnerClass
声明创建一个非静态内部类:
Out.In in=new Out().new IN();
等号左边为in的完整类名的声明,右边体现了用外部类的对象来创建内部类对象!
外部类以外使用静态内部类:
StaticOut.staticIn in=new StaticOut.StaticIn();
和上面比较可知,左侧和上面相同,右侧用外部类的类名来创建内部类对象!、
4.局部内部类:(很少用)
如果把一个内部类放在方法里定义,则这个内部类就是一个局部内部类。
5.匿名内部类:
匿名内部类适合创建只需要一次使用的类。例如命令模式中的Command对象。
规则:①匿名内部类不能使抽象类。(因为在创建匿名内部类的时,会立即创建它的对象)
②匿名内部类不能定义构造器。(匿名内部类没有类名,不能定义构造器,可以使用初始化块)
最常用的创建匿名内部类的方式是需要创建某个接口类型的对象。(即实现该接口的类的对象)
interface product{ public double getPrice(); public String getName();}public class AnonymousTest { public void test(product p) { System.out.println("购买了一个"+p.getName()+",花掉了"+p.getPrice()); } public static void main(String [] args) { AnonymousTest ta=new AnonymousTest(); //调用test方法时,需要传入一个product //此处传入其匿名实现类的实例 ta.test(new product() { public double getPrice() { return 567.8; } public String getName() { return "agp显卡"; } }); }}
也可以通过继承父类(包括抽象类)来创建匿名内部类,匿名内部类将拥有和父类相似的构造器,此处相思知的就是拥有相同的形参列表。
匿名内部类:可以选择父类的构造器,然后在类的内部可以写初始化块,实现抽象方法,重写父类的实例方法。
局部变量和匿名内部类访问的局部变量必须被final修饰(默认也是)。