内部类主要作用:
1、内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类。假设需要创建Cow类,Cow类需要组合一个CowLeg对象,CowLeg类只有在Cow类里有效,离开了Cow类之后没有任何意义。在这种情况下,就可把CowLeg定义成Cow内部类,不允许其他类访问CowLeg。
2、内部类成员可以直接访问外部类的私有数据,因为内部类被当成其外部类成员,同一个类的成员之间可以互相访问。但外部类不能访问内部类的实现细节,例如内部类的成员变量。
3、匿名内部类适合用于创建那些仅需要一次使用的类。
下面程序在Cow类里定义了一个CowLeg非静态内部类,并在CowLeg类的实例方法中直接访问Cow的private访问权限的实例Field。
public class Cow
{
//外部类
private double weight;
public Cow(){}
public Cow(double weight)
{
this.weight=weight;
}
//定义一个非静态内部类
private class CowLeg
{
private double length;
private String color;
public CowLeg(){}
public CowLeg(double length,String color)
{
this.length=length;
this.color=color;
}
public void setLength(double length)
{
this.length=length;
}
public double getLength()
{
return this.length;
}
public void setColor(String color)
{
this.color=color;
}
public String getColor()
{
return this.color;
}
//非静态内部类的实例方法
public void info()
{
System.out.println("当前牛腿颜色是:"+color+",高:"+length);
//直接访问外部类的private修饰的属性
System.out.println("本牛腿所在奶牛中:"+weight);
}
}
public void test()
{
CowLeg c1=new CowLeg(1.12,"黑白相间");
c1.info();
}
public static void man(String args[])
{
Cow cow=new Cow(378.9);
cow.test;
}
}
编译上面程序,看到在文件所在路径上生成了两个class文件,一个是Cow.class,另一个是Cow$CowLeg.class,前者是外部类Cow的class文件,后者是内部类CowLeg的class文件。
非静态内部类对象必须寄存在外部类对象里,而外部类对象则不必一定有非静态内部类对象寄存其中。
根据静态成员不能访问非静态成员的规则,外部类的静态方法、静态代码块不能访问非静态内部类,包括不能使用非静态内部类定义变量、创建实例等。总之,不允许在外部类的成员中直接使用非静态内部类。
例如:
public class StaticTest
{
//定义一个非静态内部类,是一个空类
private class In{}
//外部类的静态方法
public static void main(String args[])
{
//下面代码引发编译异常,因为静态方法无法访问非静态成员
new In();
}
}
Java 不允许在非静态内部类里定义静态成员。
public class InnerNoStatic
{
//下面三个静态声明都将引发如下编译错误:非静态内部类不能有静态声明
static
{
System.out.println("======");
}
private static int inProp;
private static void test(){}
}
}
如果使用static修饰一个内部类,则这个内部类就属于外部类本身,而不属于外部类的某个对象,因此这种内部类称为静态内部类。
注意:static关键字的作用是把类的成员变成类相关,而不是实例相关,即static修饰的成员属于整个类,而不属于单个对象。外部类的上一级程序单元是包,所以不可使用static修饰;而内部类的上一级程序单元是外部类,使用static修饰可以将内部类变成外部类相关,而不是外部类实例相关。因此,static关键字不可修饰外部类,但可修饰内部类。
静态内部类可以包含静态成员,也可以包含非静态成员。根据静态成员不能访问非静态成员的规则,静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。即使是静态内部类的实例方法也不能访问外部类的势力成员,只能访问外部类的静态成员。
例如:
public class StaticInnerClassTest
{
private int prop1=5;
private static int prop2=9;
static class StaticInnerClass
{
//静态内部类里可以包含静态成员
private static int age;
public void accessOuterProp()
{
//下面代码出现错误:静态内部类无法访问外部类的实例成员
System.out.println(prop1);
//下面代码正常
System.out.println(prop2);
}
}
}
为什么静态内部类的实例方法也不能访问外部类的实例属性呢?
因为静态内部类是外部类的类相关,而不是外部类的对象相关。也就是说,静态内部类对象不是寄存在外部类对象里,而是寄存在外部类的类本身中。当静态内部类对象存在时,并不存在一个被他寄存的外部类对象,静态内部类对象里只有外部类的类引用,没有特有的外部类对象的引用。如果允许静态内部类的实例方法访问外部类的实例成员,但找不到被寄存的外部类对象,这将引起错误。
例如:
public class AccessStaticInnerClass
{
static class StaticInnerClass
{
private static int prop1=5;
private int prop2=9;
}
public void accessInnerProp()
{
System.out.println(StaticInnerClass.prop1);
System.out.println(new StaticInnerClass().prop2);
}
}