【问题标题】:Private Member Access Java私人会员访问 Java
【发布时间】:2010-10-15 04:25:51
【问题描述】:

是类级别还是对象级别的私有成员访问。如果是在对象级别,那么下面的代码不应该编译

    class PrivateMember {
   private int i;
   public PrivateMember() {
      i = 2;
   }
   public void printI() {
      System.out.println("i is: "+i);
   }
   public void messWithI(PrivateMember t) {
      t.i *= 2;
   }
   public static void main (String args[]) {
      PrivateMember sub = new PrivateMember();
      PrivateMember obj = new PrivateMember();
      obj.printI();
      sub.messWithI(obj);
      obj.printI();
   }
}

请说明在 sub 的 messWithI() 方法中访问 obj 的成员 i 是否有效

【问题讨论】:

    标签: java accessibility private-members


    【解决方案1】:

    正如 DevSolar 所说,它处于(顶级)类级别。

    来自section 6.6 of the Java Language Specification

    否则,如果会员或 构造函数被声明为私有的,那么 当且仅当它允许访问 发生在顶部的体内 包含的级别类(§7.6) 成员声明或 构造函数。

    请注意,没有迹象表明它仅限于特定对象的成员。

    从 Java 7 开始,the compiler no longer allows access to private members of type variables。因此,如果该方法具有类似public <T extends PrivateMember> void messWithI(T t) 的签名,那么访问t.i 将是编译器错误。但是,这不会改变您的特定场景。

    【讨论】:

      【解决方案2】:

      请注意,您甚至不需要源代码级别的访问权限来处理私有字段。通过使用java.lang.reflect.AccessibleObject.setAccessibe(),所有代码都可以访问所有其他代码的所有私有成员,除非您指定了不允许的安全策略。

      private 本身并不是一项安全功能!它只是向其他开发人员强烈暗示,某些东西是代码的其他部分不应依赖的内部实现细节。 p>

      【讨论】:

      • 私有(和默认访问/“包私有”)是 Java 的主要安全特性!! setAccessible 对其进行了安全检查。
      • 默认的安全策略是允许的,因此很难将其视为“主要安全功能”。大多数开发人员的代码将使用默认的安全策略运行,因此他们不应过分相信私有成员无法访问。
      【解决方案3】:

      同一页说,在 6.6.8 小节中,您还可以找到以下语句:

      私有类成员或构造函数只能在包含成员或构造函数声明的顶级类的主体内访问。它不被子类继承。

      我们在这里评估其访问权限的私有类成员是i

      public void messWithI() 是一个存在于已声明 i 的顶级类的主体中的方法,确切地说,PrivateMember .

      您的构造符合上述陈述,这就是它运行没有问题的原因。

      这是 Jon 和 Devsolar 的另一种说法。

      类成员的访问修饰符与代码的编写位置相关(在哪个包中,在哪个类中),而与授予访问权限的成员类型无关:类成员或实例成员。

      从逻辑上讲,如果您没有类的实例,则不能使用该类的实例成员,但这是一个不同的问题,与成员的生命周期有关。

      【讨论】:

        【解决方案4】:

        两者都不是。私有访问仅限于封闭的顶级类,因此您可以访问同一顶级类中不同类的私有成员:

        class PrivateAccess {
            static class InnerOne {
                private int value;
            }
        
            static class InnerTwo {
                int getOne ( InnerOne other ) {
                    return other.value;
                }
            }
        }
        

        类访问的通常含义意味着您可以访问相同类型的其他实例的私有。在 Java 中,私有访问是由词法决定的,而不是由类型决定的。

        【讨论】:

        • 从技术上讲,您谈论的是类还是封闭外部类都没有关系。只是私人比预期或想要的更公开。
        • @Pete,您的意思是“这样您就可以访问同一顶级类中不同 object 的私有成员”吗?
        • @tori3852 您可以访问同一顶级类中不同类的私有成员,无论它们是实例成员还是静态成员。
        【解决方案5】:

        正如其他人所说,私有、默认访问(“包私有”)、受保护以及可能在 JDK 7 模块中是基于类的(嵌套类继承有非常奇怪的规则,我可以'不记得了)。但为什么呢?

        主要取决于充当二元(或更多)运算符的方法。为了高效实现,它们通常需要或者更容易编写,而无需使用或修改公共 API。看一下equals 的实现——在好的代码中,你会发现对this 的方法调用很少的字段的直接访问。 (这种性能方面现在与现代 JVM 内联常见调用几乎无关,但代码质量问题仍然存在。)

        【讨论】:

          【解决方案6】:

          为了补充 DevSolar 的答案,我希望 messWithI 被声明为静态的:

          public static void messWithI(PrivateMember t) {
            t.i *= 2;
          

          } 我什至很难在没有“静态”提示的情况下阅读你试图做什么......而且它也让你更容易回答你原来的问题——即私人成员的范围不仅限于有问题的实例。

          【讨论】:

            【解决方案7】:

            等级。这个想法是一个类的代码(但没有别的)知道如何处理该类的对象。

            如果您仍然可以访问类源代码,那么对您“隐藏”任何东西都没有什么意义。

            【讨论】:

              猜你喜欢
              • 2016-11-02
              • 1970-01-01
              • 1970-01-01
              • 2021-01-02
              • 2021-11-15
              • 2013-02-13
              • 1970-01-01
              相关资源
              最近更新 更多