7

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

    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 是否有效

4

7 回答 7

7

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

Java 语言规范的第 6.6 节

否则,如果成员或构造函数被声明为私有,则当且仅当它出现在包含成员或构造函数声明的顶级类(第 7.6 节)的主体内时,才允许访问。

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

从 Java 7 开始,编译器不再允许访问类型变量的私有成员。因此,如果该方法具有这样的签名,public <T extends PrivateMember> void messWithI(T t)那么访问将是编译器错误t.i。但是,这不会改变您的特定情况。

于 2009-03-24T11:13:45.940 回答
4

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

private本身并不是一个安全功能!这只是对其他开发人员的强烈暗示,即代码中其他部分不应依赖的内部实现细节。

于 2009-03-24T11:16:01.007 回答
3

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

class PrivateAccess {
    static class InnerOne {
        private int value;
    }

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

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

于 2009-03-24T11:19:03.900 回答
2

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

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

于 2009-03-24T11:09:07.700 回答
1

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

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

于 2009-03-24T11:39:55.330 回答
0

只是为了添加 DevSolar 的答案,我希望 messWithI 被声明为静态的:

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

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

于 2009-03-24T11:16:13.703 回答
0

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

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

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

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

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

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

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

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

于 2009-03-24T11:51:32.697 回答