【问题标题】: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,但我想更改它的列表”。这是否更明显地表明您的问题没有意义?
  • 是的,我现在明白了。谢谢

标签: java


【解决方案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;
                }
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-08-11
          • 2014-09-09
          • 2021-03-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-01-03
          相关资源
          最近更新 更多