【问题标题】:Java nested class visibility rulesJava 嵌套类可见性规则
【发布时间】:2018-09-22 16:11:48
【问题描述】:

有没有更简单的方法来访问下面对象other 的字段n

public class NestedVisibility
{
    private int n = 42;

    public static class B extends NestedVisibility {
        public void foo(NestedVisibility guest) {
            super.n = 0; // OK
            guest.n = 0; // OK

            B other = new B();
            other.n = 0; // Compile-time error. Weird!
            ((NestedVisibility)other).n = 0; // OK
        }
    }
}

访问other 的私有字段比访问guest 的私有字段需要做更多的工作,这不是很奇怪吗?

【问题讨论】:

  • 不那么繁琐的方法可能是不写这么奇怪的代码。
  • 不,这并不奇怪。 private 修饰符意味着它只能在 class 内部访问。不在 instance 内,而是在类内。这允许同一类的两个实例访问彼此的私有属性。
  • 一个静态的内部类扩展了外部类,让人有些头疼。
  • 你想做什么?也许我们可以帮助您提出一个不涉及内部扩展类的构造
  • @marco 你想使用封装。我提供了一个答案,解释了您的代码中发生的各种事情以及如何更改它以回答您的问题。一般来说,除非需要绕过封装,否则您不希望直接访问其他对象的值,这仍然是一个坏主意,因为有设计模式和 OOP 模式可以帮助您避免绕过它。

标签: java


【解决方案1】:

扩展类不会继承私有变量。您可以通过父类继承的 getter 和 setter 访问它们。

这是你重写的代码:

public class NestedVisibility
{
    private int n = 42;

    public int getN(){
        return this.n;
    }

    public void setN(int n){
        this.n = n;
    }

    public static class B extends NestedVisibility {
        public void foo(NestedVisibility guest) {
            super.n = 0; // OK
            guest.n = 0; // OK

            B other = new B();
            other.setN(0);
            console.log(other.getN());
        }
    }
}

所以基本上class B 没有field n,但它是超级的。 This post 有更多关于这方面的信息,而且互联网上有很多关于它的随机博客。

您可以从嵌套类访问私有变量。例如,如果您创建一个类型为 NestedVisibility(不是扩展)的对象,那么您可以在嵌套类中直接访问它,如下所示:

public class NestedVisibility
{
    private int n = 42;

    public static class B extends NestedVisibility {
        public void foo(NestedVisibility guest) {
            super.n = 0; // OK
            guest.n = 0; // OK

            NestedVisibility other = new NestedVisibility();
            other.n = 0; //OK
        }
    }
}

希望这有助于解决问题。

【讨论】:

    【解决方案2】:

    私有范围变量,仅对它们所属的类可见。


    如果您希望扩展类并希望授予对类变量的访问权限,则应使用 protected 范围声明它。

    public class NestedVisibility
    {
      protected int n = 42;
    
      public static class B extends NestedVisibility {
        public void foo(NestedVisibility guest) {
          super.n = 0; // OK
          guest.n = 0; // OK
    
          B other = new B();
          other.n = 0; // now is OK
          ((NestedVisibility)other).n = 0; // OK
        }
      }
    }
    

    【讨论】:

    • 实际上,根据 JLS 6.6.1:“私有类成员或构造函数只能在包含成员或构造函数声明的顶级类的主体内访问。” B 类在 NestedVisibility 的主体内。
    • @Marco 访问是可用的,只要使用了 NestedVisibility 类型。一旦你开始使用扩展类类型,私有范围规则就会应用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-24
    • 2015-03-31
    • 1970-01-01
    • 1970-01-01
    • 2012-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多