java语言规定允许:
(1)在另一个类或者一个接口中定义一个类。
(2)在另一个接口或者一个类中定义一个接口。
(3)在一个方法中定义一个类。
(4)类和接口的定义可以相互嵌套。
因此,类的成员除了包括成员变量,构造方法,成员方法,初始化语句快外还应包括内部类。
这种类被称为内部类,而包含它的类被称为外部类。
以上是java程序设计教程对内部类的解释,下面我简写出我对内部类的理解,欢迎指正。
内部类在编译过程中被当作独立的类来处理,在编译过后内部类会被编译成一个单独的.class 文件。因此,非静态内部类并不跟随着外部类加载,而是在代码中有实例化对象后加载进JVM。当然由于内部类属于外部类的成员,因此内部类可以自由的访问外部类的成员变量。但是如果是静态内部类,那么他的只能直接访问外部类的静态成员。(原因是应为静态的变量是存放在方法区的,是不需要创建具体的对象,因此java在语法规定上就不允许静态类调用外部类的非静态成员,因为其还没有加载进JVM)
内部类主要分为静态内部类和普通内部类:
静态内部类声明方式就是用static修饰内部类,这样的内部类属于整个外部类,调用静态内部类的方法和属性方式如下:
- OutClass.SInner.method();
OutClass.SInner.nature;
需要说明的是,静态内部类同样也能实例化对象出来,实例化的对象与普通对象一样会放在堆内存中,垃圾回收的方式也与普通对象无异。
对象内部类声明方式与普通的类声明方式相同,这样的内部类属于具体的对象,调用对象内部类的方法和属性如下:
- 首先需要创建具体的对象:OutClass.CInner oc = new OutClass(). new CInner();
- oc.method();
- oc.nature;
下面是一个简单的示例:
package cn.skypointer;
public class OutClass {
private static double PI = 3.14;
private double r = 10;
static class SInner {
static void getPerimeter() {
System.out.println(2*PI*10);
}
void getArea() {
System.out.println(10*10*PI);
}
}
class OInner {
void getPerimeter() {
System.out.println(2*PI*r);
}
}
public static void main(String []args) {
OutClass.OInner oc = new OutClass().new OInner();
oc.getPerimeter();
OutClass.SInner sc = new OutClass.SInner();
sc.getArea();
sc.getPerimeter();
OutClass.SInner sInner = new OutClass.SInner();
sInner.getPerimeter();
}
}
在我使用内部类的过程中,有一次我在声明一个成员内部类时,声明了一个static的成员函数,但是编译器报错,在查询资料后看到一句话我明白了其中的原因:
if you’re going to have a static mathod ,the whole inner class has to be static ,without doing that ,you couldn’t guatantee that inner class existed when you attmpted to call the static method.
大意是:如果你的内部类中有静态方法,那么你应该把其声明为静态内部类。这也是因为JVM加载类的机制导致的,你不能保证内部类在你调用静态方法时是有具体的对象的。