Java 获得受保护的信息。链接使用了哪些差异(父项或子项)?

Java 获得受保护的信息。链接使用了哪些差异(父项或子项)?,java,scope,Java,Scope,请帮我解决这个问题: 考虑一下这个代码 import java.util.Observable; import java.util.Observer; public class MyObservable extends Observable { int k; public int getK() { return k; } public void setK(int k) { this.k = k; setChang

请帮我解决这个问题:

考虑一下这个代码

import java.util.Observable;
import java.util.Observer;

public class MyObservable extends Observable {
    int k;
    public int getK() {
        return k;
    }

    public void setK(int k) {
        this.k = k;
        setChanged();   //valid
    }

    public static  void   main(String [] args){
        Observable observable = new MyObservable();

        Observer myObserver1 = new MyObserver();
        Observer myObserver2 = new MyObserver();

        observable.addObserver(myObserver1);
        observable.addObserver(myObserver2);

        observable.setChanged(); //compilation error here
        observable.notifyObservers();
    }
}
我从public方法(它是有效的)和public静态方法(它是无效的(我看到消息说它是受保护的方法而不是vald))调用
setChanged()。我认为静态/非静态对访问没有影响

我不明白为什么

我在等你的正确解释

我想知道为什么java创始人会这样做?在概念上,我的变体有什么错误?

这不是真正的静态/非静态差异——它是试图调用方法的引用的编译时类型的不同

在instance方法中,您在
this
上隐式调用它,它的编译时类型为
MyObservable
。在
main
中,您正在对类型为
observeable
的引用调用它,但由于
受保护的
访问是如何工作的,因此您不能这样做

从JLS(结尾处的重点是我的):

对象的受保护成员或构造函数可以从包的外部访问,在包中它只能由负责该对象实现的代码声明

6.6.2.1。访问受保护的成员

设C为声明受保护成员的类。仅允许在C的子类S的主体内访问

此外,如果Id表示实例字段或实例方法,则:

  • 如果访问是通过限定名称Q.Id进行的,其中Q是ExpressionName,则当且仅当表达式Q的类型是S或S的子类时,才允许访问

  • 如果访问是通过字段访问表达式E.Id进行的,其中E是主表达式,或者通过方法调用表达式E.Id(…),其中E是主表达式,则当且仅当E的类型是S或S的子类时,才允许访问

因此,在本例中,如果您将声明的
observable
类型更改为
MyObservable
,您将发现错误消失。

这实际上不是静态/非静态差异,而是您试图调用该方法的引用的编译时类型的差异

在instance方法中,您在
this
上隐式调用它,它的编译时类型为
MyObservable
。在
main
中,您正在对类型为
observeable
的引用调用它,但由于
受保护的
访问是如何工作的,因此您不能这样做

从JLS(结尾处的重点是我的):

对象的受保护成员或构造函数可以从包的外部访问,在包中它只能由负责该对象实现的代码声明

6.6.2.1。访问受保护的成员

设C为声明受保护成员的类。仅允许在C的子类S的主体内访问

此外,如果Id表示实例字段或实例方法,则:

  • 如果访问是通过限定名称Q.Id进行的,其中Q是ExpressionName,则当且仅当表达式Q的类型是S或S的子类时,才允许访问

  • 如果访问是通过字段访问表达式E.Id进行的,其中E是主表达式,或者通过方法调用表达式E.Id(…),其中E是主表达式,则当且仅当E的类型是S或S的子类时,才允许访问


因此,在这种情况下,如果您将声明的
可观察的类型更改为
MyObservable
,您会发现错误消失了。

这些概念是什么?为什么要做?@gstackoverflow:我不知道你的意思。对不起,英语不好。我不明白禁止这种构造的概念性原因?@gstackoverflow:其思想是类应该只能使用自己类实例的受保护成员。。。一种“有点不完全私密”的感觉。我知道)如果允许使用observable.setChanged()有什么不好?如果把可观察和我可观察放在一个包中,它会起作用,这些概念是什么?为什么要做?@gstackoverflow:我不知道你的意思。对不起,英语不好。我不明白禁止这种构造的概念性原因?@gstackoverflow:其思想是类应该只能使用自己类实例的受保护成员。。。一种“有点不完全私密”的感觉。我知道)如果允许使用observable.setChanged()有什么不好?如果将可观察和可观察放在一个包中,它就会工作