类和对象4
- 🍉内部类
- 🍌实例内部类
- 🍌静态内部类
- 🍌局部内部类
- 🍌匿名内部类
- 🍉总结
🍉内部类
在 Java 中,我们可以将一个类定义在另一个类或者一个方法的内部
,前者称为内部类
,后者称为外部类。内部类也是封装的一种体现
注意:内部类和外部类共用同一个java源文件,但是经过编译之后,内部类会形成单独的字节码文件
根据内部类定义的位置
,可以分为两种形式:
- 成员内部类:实例内部类、静态内部类
- 局部内部类、匿名内部类
🍌实例内部类
在成员位置
定义,并且没有被static修饰
- 通过外部类引用来实例化实例内部类的对象
必须先有外部类对象,然后才能创建实例内部类对象
public class Main {
Out out = new Out();
Out.InnerClass innerClass = out.new InnerClass();
}
- 除非被final修饰成为常量,否则实例内部类不能有静态字段
这很好理解,因为实例内部类的对象需要通过外部类对象产生,而静态字段不依赖对象而存在,所以这两者会产生冲突
而一个静态字段如果被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.同名成员名字
”的格式访问
(这就类似父类和子类有同名的成员,如果不使用super进行访问,就会优先访问子类的)
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
修饰的内部类,它不依托外部类的对象存在,所以:
- 它不可以访问外部类的普通字段、方法(可以访问静态字段和静态方法)
2. 创建静态内部类对象时,无需创建外部类对象
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.外部类成员”
访问
外部类不能直接访问实例内部类中的成员,必须先创建内部类的对象 - 匿名内部类在开发过程经常使用,很重要