我可以从静态内部类访问外部类的字段吗?

Posted

技术标签:

【中文标题】我可以从静态内部类访问外部类的字段吗?【英文标题】:Can I access an outer class's field from a static inner class? 【发布时间】:2021-04-21 16:55:44 【问题描述】:

我有一个类有另一个static 内部类:

class A 
    private List<String> list;

    public static class B 
        // I want to update list here without making list as static 
        // I don't have an object for outer class
    

【问题讨论】:

静态嵌套类没有对周围类的任何实例的隐式引用。您需要将引用传递给您希望它修改的实例。为什么 B 类是静态的? Class B 只是为 UI 显示生成一个模板结构,现在我正在执行一些操作来获取值,并且需要设置为周围的类。这是设计问题吗? 如果您需要每个 B 实例与特定的 A 实例相关联,并且能够对其进行操作,最简单的解决方案是使 B 成为非静态的,并在构建时建立这种关系。 我可以将评论重新表述为“我没有 A,但我想更改它的列表”。这是否更明显地表明您的问题没有意义? 是的,我现在明白了。谢谢 【参考方案1】:

当您不需要需要访问实例变量时,您通常会使用静态类。如果您需要访问实例变量,请使类成为非静态类。

【讨论】:

【参考方案2】:

正如您从其他答案中看到的那样,您将需要一个非静态内部类来执行此操作。

如果你真的不能让你的内部类非静态,那么你可以在外部类中添加所需的 getter 和 setter 方法,并通过从内部静态类中创建外部类的实例来访问它们:

public class A 
    private List<String> list = new ArrayList<String>();
    public List<String> getList() 
        return list;
    
    public void setList(List<String> list) 
        this.list = list;
    
    public static class B 
        // i want to update list here without making list as static
        void updList() 
            A a = new A();
            a.setList(someOtherList);
            System.out.println(a.getList());
        
    
 

【讨论】:

这真的是一个解决方案,考虑到表达式A a = new A(); 中的 A 类对象只是局部的,具有其初始值吗?请详细说明一下好吗? 你想用内部类做什么? 在此处添加 getter 和 setter 无关紧要,只需通过 a.list 访问该字段即可。关键是您创建了一个A 的新实例。但正如this comment 已经说过的,使用A 的临时实例没有持久效果。 因为它是一个静态内部类(并且list 是非静态的),我们需要一个显式实例来访问它,否则我们可以简单地使用A.this.list【参考方案3】:

不,您需要一个非static 内部类来执行此操作。

来自JLS §8.5.1:

static 关键字可以修改非内部类或接口 T 的主体内的成员类型 C 的声明。它的作用是声明C 不是内部类。正如 T 的静态方法在其主体中没有 T 的当前实例一样,C 也没有 T 的当前实例,也没有任何词法封闭实例。

如果 static 类包含封闭类的非静态成员的用法,则会出现编译时错误。

【讨论】:

【参考方案4】:

在您的代码中,list 是类 A 的实例变量,B 是嵌套的静态类。对于嵌套的静态类,访问静态和非静态成员的规则不会改变。

变量list 是实例变量,因此无法从静态上下文中访问。

要启用此功能,您需要将静态嵌套类更改为内部类。

class A 
private List<String> list = new ArrayList<String>();
  public class B 
     public void someMethod()
         list.add("abc");
     
  

【讨论】:

【参考方案5】:

private List&lt;String&gt; list;

这里 list 是一个实例变量,而内部类是静态的,这意味着 class B 是在不同的 class A 实例中相同;无法访问它。而且,这也是一个非常好的和明显的原因。

您可以使用的一种解决方案是将成员 list 的引用传递给 class B 的构造函数weakReference 以避免内存泄漏。

类似这样的:

class A 
    private List<String> list;

    public static class B 
        WeakReference<List<String>> innerList;
        //constructor
        B(WeakReference<List<String>> innerList)
            this.innerList = innerList;
        
    

【讨论】:

以上是关于我可以从静态内部类访问外部类的字段吗?的主要内容,如果未能解决你的问题,请参考以下文章

JAVA 中外部类可以访问非静态内部类的私有属性???

内部类访问外部类的变量必须是final吗,java静态方法中不能引用非静态变量,静态方法中不能创建内部类的实例

java内部类的静态嵌套类

如何调用内部类中的静态方法

内部类之静态内部类

在静态方法中new 一个内部类对象和new 一个外部类对象的区别