从同一类的不同实例访问私有方法

Posted

技术标签:

【中文标题】从同一类的不同实例访问私有方法【英文标题】:Accessing private method from different instance of the same class 【发布时间】:2017-09-19 05:53:56 【问题描述】:

我刚刚遇到一个代码。在一种情况下,我无法使用其实例访问该类的私有成员(这很好),但在另一种情况下,我能够使用其不同的实例访问私有成员(属于同一类)。谁能解释一下为什么会这样?

 class Complex 
    private double re, im; 
    public String toString() 
        return "(" + re + " + " + im + "i)";
    
    Complex()

/*Below c is different instance, still it can access re,im( has a private access) 
  without any error.why? */

    Complex(Complex c) 
        re = c.re;
        im = c.im;
    


public class Main 
    public static void main(String[] args) 
        Complex c1 = new Complex();
        Complex c2 = new Complex(c1);
        System.out.println(c1.re);  /* But getting an error here , 
        which is expected as re and im has a private access in Complex class.*/
    

【问题讨论】:

因为Java就是这样工作的? “否则,成员或构造函数被声明为私有,并且当且仅当它出现在包含成员或构造函数声明的***类(第 7.6 节)的主体中时才允许访问。” (JLS 6.6.1) Java 中的访问控制是按类而不是实例。 (诚​​然,protected 在这方面有点棘手。) 【参考方案1】:

您可以从同一类中定义的任何代码块访问私有成员。不管实例是什么,或者是否有任何实例(代码块在静态上下文中)。

但是您不能从不同类中定义的代码访问它们。

您的第一个参考在同一个类中,Complex,这就是它起作用的原因。而第二个在另一个类中,Main,这就是它不起作用的原因。

【讨论】:

如果我不希望同一类的不同实例访问该字段,我该怎么做?更清楚地说,我要求的是 Scala 中的 private[this] 之类的东西 AFAIK 在 Java 中是不可能的。无论如何,我看不到它的重要性:对我来说,封装是关于代码(及其所有权),而不是运行时实例。【参考方案2】:

原因是Main 类无法访问其他类的私有字段。在这种情况下,Complex 类的私有字段。 您只能从此类中的方法访问 Complex 类中的私有字段。换句话说,如果您将 main 方法移动到 Complex 类,代码将被编译。 如果你想从Main(或其他类)获取/设置Complex类中的值,你应该在Complex类中添加setter/getter。

【讨论】:

【参考方案3】:

这是解释访问修饰符的表格:

如您所见,在private 行中,除了Class 列之外,所有内容都是N。这意味着您可以访问私有成员,只要您在声明它们的同一类中访问它们。您甚至可以使用实例从同一类中的静态上下文访问私有非静态成员。没有访问修饰符只允许从同一个实例进行访问。

为什么?

因为在编译时弄清楚thisc 是否是同一个实例是一件很痛苦的事情。您必须实际运行代码以查看它们是否引用相同的实例。

【讨论】:

【参考方案4】:

从概念上讲,访问说明符是@class 级别,而不是@instance 级别。

以下可能是保持访问说明符@类级别的原因。 从JLS Documentation,我们可以清楚地看到访问是针对用户的,他们正在基于契约实现(或使用类/包)。

简单来说,作为开发人员(用户),我所关心的只是可用的成员(变量、方法)、它们的作用、我如何使用它们(抽象概念的基础)。

在你的情况下,它是同一个类,它拥有访问其成员的所有特权,因此可以观察到的行为。

【讨论】:

以上是关于从同一类的不同实例访问私有方法的主要内容,如果未能解决你的问题,请参考以下文章

Java子类访问父类的私有成员变量

类,对象和方法

为啥我能够从在同一对象的另一个实例上调用的方法访问一个实例的私有实例变量? [复制]

从子类访问父类的私有实例变量?

为啥我不能从不同命名空间中的朋友类更改类的私有成员?

Java学习笔记--不同包的访问权限