杰瑞科技汇

Java内部类如何调用外部类的方法?

核心思想

内部类之所以能访问外部类的成员(包括方法和变量),是因为内部类持有了一个指向外部类对象的隐式引用,当你创建一个内部类对象时,JVM 会自动将外部类的对象引用传递给内部类。

Java内部类如何调用外部类的方法?-图1
(图片来源网络,侵删)

这个隐式引用在 Java 代码中的体现形式是:外部类名.this


内部类调用外部类的实例方法

这是最常见的情况,内部类可以直接访问外部类的所有 publicprotecteddefault(包私有)和 private 的实例方法和实例变量。

代码示例

public class OuterClass {
    private String outerName = "外部类实例变量";
    private void outerPrivateMethod() {
        System.out.println("这是外部类的私有方法 (outerPrivateMethod)");
    }
    // 定义一个成员内部类
    class InnerClass {
        public void innerMethod() {
            System.out.println("--- 内部类方法开始调用外部类方法 ---");
            // 1. 直接访问外部类的实例变量
            System.out.println("访问外部类的实例变量: " + outerName);
            // 2. 直接调用外部类的私有方法
            outerPrivateMethod();
            // 3. 如果需要,也可以显式地使用 "外部类名.this" 来引用外部类对象
            //    OuterClass.this 就代表当前这个 InnerClass 所在的 OuterClass 对象
            System.out.println("显式引用外部类对象: " + OuterClass.this);
            System.out.println("显式引用外部类实例变量: " + OuterClass.this.outerName);
            OuterClass.this.outerPrivateMethod();
            System.out.println("--- 内部类方法调用结束 ---");
        }
    }
    // 外部类的方法,用于创建内部类对象并调用其方法
    public void useInnerClass() {
        // 创建内部类对象
        InnerClass inner = new InnerClass();
        // 调用内部类的方法
        inner.innerMethod();
    }
}

测试代码

public class Main {
    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        outer.useInnerClass();
    }
}

输出结果

--- 内部类方法开始调用外部类方法 ---
访问外部类的实例变量: 外部类实例变量
这是外部类的私有方法 
显式引用外部类对象: OuterClass@15db9742
显式引用外部类的实例变量: 外部类实例变量
这是外部类的私有方法 
--- 内部类方法调用结束 ---

关键点分析:

  • 直接访问:在 InnerClassinnerMethod 中,我们可以像访问自己的成员一样直接使用 outerNameouterPrivateMethod()
  • 显式引用 OuterClass.thisOuterClass.this 是一个完整的表达式,它指向创建该内部类对象的外部类实例,在大多数情况下,编译器会自动帮你处理,所以不需要显式写出,但在某些情况下(内部类的成员变量与外部类的成员变量同名时),就必须使用它来消除歧义。

处理成员变量名冲突的情况

当内部类的成员变量(或方法)与外部类的成员变量(或方法)同名时,会产生“隐藏”现象,如果想在内部类中访问外部类的被隐藏成员,就必须使用 外部类名.this

Java内部类如何调用外部类的方法?-图2
(图片来源网络,侵删)

代码示例

public class OuterClass {
    // 外部类有一个名为 name 的变量
    private String name = "外部类的 name";
    class InnerClass {
        // 内部类也有一个名为 name 的变量
        private String name = "内部类的 name";
        public void printNames() {
            System.out.println("内部类的 name: " + name); // 直接访问,访问的是内部自己的
            System.out.println("外部类的 name: " + OuterClass.this.name); // 必须使用 this 来访问外部类的
        }
    }
}

测试代码

public class Main {
    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        OuterClass.InnerClass inner = outer.new InnerClass();
        inner.printNames();
    }
}

输出结果

内部类的 name: 内部类的 name
外部类的 name: 外部类的 name

静态内部类 调用外部类方法

静态内部类不持有外部类的隐式引用,它不能直接访问外部类的实例成员(实例变量和实例方法)。

它只能访问:

  1. 外部类的 static 成员。
  2. 外部类的 public 成员(如果外部类本身是 public 的)。

如果确实需要访问外部类的实例成员,必须通过一个外部类的对象来调用。

代码示例

public class OuterClass {
    private String outerInstanceVar = "外部类实例变量";
    private static String outerStaticVar = "外部类静态变量";
    // 静态内部类
    static class StaticInnerClass {
        public void accessMembers() {
            System.out.println("--- 静态内部类方法 ---");
            // 1. 可以直接访问外部类的静态成员
            System.out.println("访问外部类静态变量: " + outerStaticVar);
            // 2. 不能直接访问外部类的实例成员,编译会报错
            // System.out.println(outerInstanceVar); // Compile Error!
            // 3. 必须通过外部类的对象来访问实例成员
            OuterClass outerObj = new OuterClass();
            System.out.println("通过外部类对象访问实例变量: " + outerObj.outerInstanceVar);
            outerObj.outerInstanceMethod();
        }
    }
    private void outerInstanceMethod() {
        System.out.println("这是外部类的实例方法");
    }
}

测试代码

public class Main {
    public static void main(String[] args) {
        // 创建静态内部类对象,不需要先创建外部类对象
        OuterClass.StaticInnerClass staticInner = new OuterClass.StaticInnerClass();
        staticInner.accessMembers();
    }
}

输出结果

--- 静态内部类方法 ---
访问外部类静态变量: 外部类静态变量
通过外部类对象访问实例变量: 外部类实例变量
这是外部类的实例方法

局部内部类 和 匿名内部类

这两种内部类也遵循与成员内部类相同的规则,因为它们都是非静态的,所以都持有对外部类对象的引用,它们可以访问外部类的所有成员,以及其所在作用域中的 final 或等效 final 的局部变量。

Java内部类如何调用外部类的方法?-图3
(图片来源网络,侵删)

匿名内部类示例

public class OuterClass {
    public void show() {
        System.out.println("外部类的 show() 方法");
    }
    public void createAnonymousInner() {
        // 创建一个匿名内部类,它实现了 Runnable 接口
        // 这个匿名内部类可以访问外部类的成员
        Runnable r = new Runnable() {
            @Override
            public void run() {
                System.out.println("--- 匿名内部类的 run() 方法 ---");
                // 调用外部类的 show() 方法
                OuterClass.this.show(); // 显式调用,也可以省略 this
                System.out.println("访问外部类的成员");
            }
        };
        new Thread(r).start();
    }
}

内部类类型 是否持有外部类引用? 能否直接访问外部类实例成员? 如何访问外部类实例成员?
成员内部类 直接访问,或使用 外部类名.this
静态内部类 不能 必须创建外部类的对象,然后通过对象访问
局部内部类 直接访问,或使用 外部类名.this
匿名内部类 直接访问,或使用 外部类名.this

记住这个核心区别:静态内部类没有外部类引用,其他内部类都有,这是理解它们如何与外部类交互的关键。

分享:
扫描分享到社交APP
上一篇
下一篇