一个枚举常量特定的类体静态还是非静态? [英] Is an enum constant-specific class body static or non-static?

查看:171
本文介绍了一个枚举常量特定的类体静态还是非静态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个枚举类类:

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);
}

如上所述,我已经定义了一个枚举类型,其值为 PLUS 。它包含一个常数特定的身体。在其正文中,我尝试调用 printMe(val); ,但是我收到了编译错误:

As you see above, I have defined one enum type which has value PLUS. It contains a constant-specific body. In its body, I tried to call printMe(val);, but I got the compilation error:


无法静态引用非静态方法printMe()。

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

为什么我得到这个错误?我的意思是我在 PLUS 正文中覆盖一个抽象方法。为什么在 static 范围?如何摆脱它?

Why do I get this error? I mean I am overriding an abstract method in PLUS body. Why is it in static scope? How to get rid of it?

我知道在 printMe(){...}上添加 static / code>解决问题,但是如果我想保留 printMe()非静态,我有兴趣知道是否有其他方式?

I know adding a static keyword on printMe(){...} solves the problem, but I am interested to know if there is another way if I want to keep printMe() non-static?

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

Another issue, quite similar as above one, but this time the error message sounds the other way around, i.e. PLUS(){...} has non-static context:

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 -specific static 变量,但我最终会出现错误:

I try to declare a PLUS-specific static variable, but I end up with error:


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

为什么我不能在静态内部定义static constant code> PLUS 如果 PLUS 是一个匿名类?两个错误消息彼此矛盾,因为第一个错误消息说 PLUS(){...} 具有静态上下文,而第二个错误消息说 PLUS(){...} 具有非静态上下文。我现在更困惑了。

Why can I not define static constant inside PLUS if PLUS is an anonymous class? The two error messages sound contradictory to each other, as the 1st error message says PLUS(){...} has static context while the 2nd error message says PLUS(){...} has non-static context. I am even more confused now.

推荐答案

这是一个奇怪的情况。

似乎问题是:


  • 在这种情况下,私人会员应该可以访问 6.6.1 。 ):


否则,该成员或构造函数被声明为 private ,访问是允许,只有当它发生在包含成员或构造函数的声明的顶级类的主体内。

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.


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


    声明为 private 的类的成员不被子类继承

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


  • 因此, printMe 不是匿名子类的成员和编译器在超类* 操作( 15.12.1 ):

  • Therefore, printMe is not a member of the anonymous subclass and the compiler searches for it within the superclass* Operation (15.12.1):


    如果存在该方法是的封闭类型声明,则将T作为最内层的这种类型声明。要搜索的类或接口是T。

    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.

    此搜索策略称为梳状规则。在查找封装类及其超类层次结构中的方法之前,它会有效地查找嵌套类的超类层次结构中的方法。


  • 这里是奇怪的地方。因为在还包含 PLUS 的类中找到 printMe ,则该方法被调用是相反确定为一个包含操作的实例,它不存在( 15.12.4.1 ):

  • And here is where it gets strange. Because printMe is found in a class that also encloses PLUS, the object that the method is called on is instead determined to be an enclosing instance of Operation, which doesn't exist (15.12.4.1):


    否则,将T作为方法的成员的封闭类型声明,并且让 n 成为一个整数,使得T是 n '的词法封装类型该声明的声明立即包含方法调用。 目标引用是 c

    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.

    如果 n '这个这个的词法包围实例不存在,这是一个编译时错误。

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


  • 所以简而言之,因为 printMe 只是操作(而不是继承)的成员,编译器被迫调用 printMe 不存在的外部实例

    So in short, because printMe is only a member of Operation (and not inherited), the compiler is compelled to invoke printMe on a non-existent outer instance.

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

    However, the method is still accessible and we can find it by qualifying the invocation:

    @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 )。

    Yes, this is a confusing aspect of the language. On the one hand, an anonymous class is never static (15.9.5), on the other hand, an anonymous class expression can appear in a static context and therefore has no enclosing instance (8.1.3).


    匿名类始终是一个内部类;它不是 static






    一个内部类的实例 I 其声明发生在静态上下文中,没有任何词汇包围的实例。

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

    为了帮助了解这是如何工作的,这里是一个格式化的例子:

    To help understand how this works, here is a formatted example:

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

    italics 是静态上下文。从 bold 中的表达式派生的匿名类被认为是内部和非静态(但没有包含的实例示例)。

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

    Since the anonymous class is non-static it cannot declare static non-constant members, despite that it is itself declared within a static context.

    *除了模糊事情一点,事实上操作是一个完全不相关的枚举( 8.9。 1 ):

    * Besides obscuring the matter a little, the fact that Operation is an enum is completely irrelevant (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 [...].

    这篇关于一个枚举常量特定的类体静态还是非静态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆