四、静态内部类与非静态的区别
首先,静态内部类实际上与普通类(即类名必须与文件名一样的顶级类)一样,只是静态内部类在某一类的内部定义了而已,既然是类,要想使用就必须实例化。概念上与静态变量、静态方法是不一样的,不要被“静态”两个字迷惑了(不要以为凡是静态的东西就不需要实例化就可以直接使用,静态内部类是有区别),而且只有静态内部类,而没有静态类(顶级类)的概念。例如,下面定义类是错误的:
public static class TestClass { // 此写法错误,不存在静态类,编译不通过
public void test() {
}
}
如果你不需要内部类对象与其外部类对象之间有联系,那你可以将内部类声明为static。这通常称为嵌套类(nested class)。Static Nested Class是被声明为静态(static)的内部类,它可以不依赖于外部类实例被实例化。而通常的内部类需要在外部类实例化后才能实例化。想要理解static应用于内部类时的含义,你就必须记住,普通的内部类对象隐含地保存了一个引用,指向创建它的外部类对象。然而,当内部类是static的时,就不是这样了。嵌套类意味着:
1. 嵌套类的对象,并不需要其外部类的对象。
2. 不能从嵌套类的对象中访问非静态的外部类对象。
如下所示代码为定义一个静态嵌套类:
public class StaticTest {
private static String name = "woobo";
private String num = "X001";
static class Person { // 静态内部类可以用public,protected,private修饰
// 静态内部类中可以定义静态或者非静态的成员
private String address = "China";
private static String x = "as";
public String mail = "kongbowoo@yahoo.com.cn";// 内部类公有成员
public void display() {
// System.out.println(num);//不能直接访问外部类的非静态成员
// 静态内部类不能访问外部类的非静态成员(包括非静态变量和非静态方法)
System.out.println(name);// 只能直接访问外部类的静态成员
// 静态内部类只能访问外部类的静态成员(包括静态变量和静态方法)
System.out.println("Inner " + address);// 访问本内部类成员。
}
}
public void printInfo() {
Person person = new Person();
// 外部类访问内部类的非静态成员:实例化内部类即可
person.display();
// System.out.println(mail);//不可访问
// System.out.println(address);//不可访问
System.out.println(person.address);// 可以访问内部类的私有成员
System.out.println(Person.x);// 外部类访问内部类的静态成员:内部类.静态成员
System.out.println(person.mail);// 可以访问内部类的公有成员
}
public static void main(String[] args) {
StaticTest staticTest = new StaticTest();
staticTest.printInfo();
}
}
总结:
1. 静态内部类可以有静态成员(方法,属性),而非静态内部类则不能有静态成员(方法,属性)。
2. 静态内部类只能够访问外部类的静态成员,而非静态内部类则可以访问外部类的所有成员(方法,属性)。
3. 实例化一个非静态的内部类的方法:
a. 先生成一个外部类对象实例
OutClassTest oc1 = new OutClassTest();
b. 通过外部类的对象实例生成内部类对象
OutClassTest.InnerClass no_static_inner = oc1.new InnerClass();
4. 实例化一个静态内部类的方法:
a. 不依赖于外部类的实例,直接实例化内部类对象
OutClassTest.InnerStaticClass inner = new OutClassTest.InnerStaticClass();
b. 调用内部静态类的方法或静态变量,通过类名直接调用
OutClassTest.InnerStaticClass.static_value
OutClassTest.InnerStaticClass.getMessage()
最后,我再告诉大家,接口虽然不能有任何实现,但内部类(无论是静态的还是非静态的内部类)却可以作为接口的一部分,例如:
public interface TestInterface {
void testMethod();
static class TestInnerClass implements TestInterface {// 并不是非要实现TestInterface,这里可以做任何事情。
@Override
public void testMethod() {
System.out.println("测试");
}
}
}
class Test {
public static void main(String[] args) {
TestInnerClass testClass = new TestInterface.TestInnerClass();
testClass.testMethod();
}
}