在 Java 中,我们可以将一个类定义在另一个类或者一个方法的内部
,前者称为内部类
,后者称为外部类。内部类也是封装的一种体现
注意:内部类和外部类共用同一个java源文件,但是经过编译之后,内部类会形成单独的字节码文件
根据内部类定义的位置
,可以分为两种形式:
在成员位置
定义,并且没有被static修饰
public class Main {
Out out = new Out();
Out.InnerClass innerClass = out.new InnerClass();
}
而一个静态字段如果被final修饰,那就意味着它是一个常量,它在编译阶段
就会被确定,因此它不依赖于外部类的实例
然后还需要注意,即使采用就地初始化也还是不行,因为静态字段是在类加载的时候初始化,在编译阶段仍然不能确定它的值
class InnerClass{
public static int data2 = 20; //编译报错
public static final int data2 = 20;
}
外部类的任意成员
public class Out {
public int data1 = 1;
public static int data2 = 2;
private int data3 = 3;
class InnerClass{
public void Test() {
Out out = new Out();
System.out.println(out.data1);
System.out.println(data2);
System.out.println(out.data3);
}
}
}
优先
访问的是内部类的
外部类名称.this.同名成员名字
”的格式访问public class Out {
public int data1 = 1;
public static int data2 = 2;
private int data3 = 3;
class InnerClass{
public int data1 = 10;
public static final int data2 = 20;
public int data3 = 30;
void method() {
System.out.println(data1);
System.out.println(data2);
}
}
}
public static void main(String[] args) {
Out out = new Out();
Out.InnerClass innerClass = out.new InnerClass();
innerClass.method();
}
实例内部类的非静态方法中包含了一个指向外部类对象的引用
。所以实例内部类相当于有两个this:一个是内部类的this
;另一个是访问外部类成员的Out.this
创建内部类的对象
public class Out {
public int data1 = 1;
public void test() {
InnerClass innerClass = new InnerClass();
System.out.println(innerClass.data2);
}
class InnerClass{
public int data2 = 10;
}
}
顾名思义,就是用static
修饰的内部类,它不依托外部类的对象存在,所以:
public static void main(String[] args) {
// 静态内部类对象创建 & 成员访问
Out.InnerClass innerClass = new Out.InnerClass();
innerClass.methodInner();
}
定义在方法内部
的类,只可以在方法内部
使用(这种内部类很少用)
public class Out {
public int data1 = 1;
public static int data2 = 2;
private int data3 = 3;
public void func() {
//类A只能在func里面使用
class A {
private int data4 = 4;
}
A aa = new A();
System.out.println("data4" + aa.data4);
}
}
就是没有名字的内部类,通常可用于实现接口
public interface IA {
void test();
}
public static void main(String[] args) {
new IA(){
@Override
public void test() {
System.out.println("重写接口中的方法");
}
};
}
从IA( )到大括号结束,就是匿名内部类,它实现了IA接口,然后前面使用new创建这个匿名内部类的对象
如果要调用它的test方法,有两种办法:
//第一种:直接在匿名内部类后面调用
new IA(){
@Override
public void test() {
System.out.println("重写接口中的方法");
}
}.test();
//第二种:定义一个接口类型的引用指向这个对象,然后通过这个引用来调用方法
IA a = new IA(){
@Override
public void test() {
System.out.println("重写接口中的方法");
}
};
a.test();
“外部类.this.外部类成员”
访问