gpt4 book ai didi

java - 特定于枚举常量的类主体是静态的还是非静态的?

转载 作者:IT老高 更新时间:2023-10-28 20:57:40 27 4
gpt4 key购买 nike

我有一个枚举类型类:

public enum Operation {
PLUS() {
@Override
double apply(double x, double y) {
// ERROR: Cannot make a static reference
// to the non-static method printMe()...
printMe(x);
return x + y;
}
};

private void printMe(double val) {
System.out.println("val = " + val);
}

abstract double apply(double x, double y);
}

正如你在上面看到的,我定义了一个 enum 类型,它的值是 PLUS。它包含一个特定于常量的主体。在它的正文中,我尝试调用 printMe(val);,但我得到了编译错误:

Cannot make a static reference to the non-static method printMe().

为什么会出现此错误?我的意思是我正在重写 PLUS 正文中的抽象方法。为什么它在 static 范围内?如何摆脱它?

我知道在 printMe(){...} 上添加 static 关键字可以解决问题,但我很想知道是否有其他方法保持 printMe() 非静态?


另一个问题,与上述问题非常相似,但这次错误消息听起来相反,即 PLUS(){...} 具有非静态上下文:

public enum Operation {
PLUS() {
// ERROR: the field "name" can not be declared static
// in a non-static inner type.
protected static String name = "someone";

@Override
double apply(double x, double y) {
return x + y;
}
};

abstract double apply(double x, double y);
}

我尝试声明一个 PLUS 特定的 static 变量,但最终出现错误:

the field "name" can not be declared static in a non-static inner type.

如果 PLUS 是匿名类,为什么我不能在 PLUS 中定义静态常量?这两条错误消息听起来相互矛盾,因为第一条错误消息说 PLUS(){...}static 上下文,而第二条错误消息说 PLUS(){...} 具有非静态上下文。我现在更困惑了。

最佳答案

这是一个奇怪的案例。

看来问题是:

  • 在这种情况下,私有(private)成员应该是可访问的(6.6.1。):

    Otherwise, the member or constructor is declared private, and access is permitted if and only if it occurs within the body of the top level class that encloses the declaration of the member or constructor.

  • 但是,私有(private)成员不会被继承 (8.2):

    Members of a class that are declared private are not inherited by subclasses of that class.

  • 因此,printMe不是匿名子类的成员,编译器会在父类(super class)中搜索它* Operation (15.12.1):

    If there is an enclosing type declaration of which that method is a member, let T be the innermost such type declaration. The class or interface to search is T.

    This search policy is called the "comb rule". It effectively looks for methods in a nested class's superclass hierarchy before looking for methods in an enclosing class and its superclass hierarchy.

  • 这就是奇怪的地方。因为printMe在一个也包含的类中找到PLUS ,调用该方法的对象被确定为 Operation 的封闭实例, 不存在 (15.12.4.1):

    Otherwise, let T be the enclosing type declaration of which the method is a member, and let n be an integer such that T is the n'th lexically enclosing type declaration of the class whose declaration immediately contains the method invocation. The target reference is the n'th lexically enclosing instance of this.

    It is a compile-time error if the n'th lexically enclosing instance of this does not exist.

简而言之,因为 printMe只是 Operation 的成员(而不是继承),编译器被迫调用 printMe 在一个不存在的外部实例上

但是,该方法仍然可以访问,我们可以通过限定调用来找到它:

@Override
double apply(double x, double y) {
// now the superclass is searched
// but the target reference is definitely 'this'
// vvvvvv
super.printMe(x);
return x + y;
}

The two error messages sound contradictory to each other [...].

是的,这是该语言的一个令人困惑的方面。一方面,匿名类永远不是静态的(15.9.5),另一方面,匿名类表达式可以出现在静态上下文中,因此没有封闭实例(8.1.3) .

An anonymous class is always an inner class; it is never static.

An instance of an inner class I whose declaration occurs in a static context has no lexically enclosing instances.

为帮助理解其工作原理,以下是一个格式化示例:

class Example {    public static void main(String... args) {        new Object() {            int i;            void m() {}        };    }}

<i>italics</i> 中的所有内容是静态上下文。从<b>bold</b> 中的表达式派生的匿名类被认为是内部的和非静态的(但没有 Example 的封闭实例)。

由于匿名类是非静态的,它不能声明静态非常量成员,尽管它本身是在静态上下文中声明的。


* 除了使事情变得模糊之外,Operation 的事实是一个枚举完全不相关(8.9.1):

The optional class body of an enum constant implicitly defines an anonymous class declaration that extends the immediately enclosing enum type. The class body is governed by the usual rules of anonymous classes [...].

关于java - 特定于枚举常量的类主体是静态的还是非静态的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28964926/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com