如何通过覆盖方法在java枚举中使用字段? [英] How to use fields in java enum by overriding the method?

查看:164
本文介绍了如何通过覆盖方法在java枚举中使用字段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

} 
},
SECOND {
@Override
public String doIt(){
return2:+ someField; // error
}
};

private String someField;

public abstract String doIt();

}

但是当引用 someField 我得到


无法静态引用非静态字段someField。

$ b $

解决方案

一个专门的枚举只不过是一个具有内部类语义的子类。如果您在编译后查看字节码,您将注意到,编译器仅插入用于读取私有字段的访问器方法,但是任何专门的枚举都将被编译为其自己的类。您可以考虑将枚举实现为:

  public abstract class MyEnum {

private static class First extends MyEnum {

@Override
public String doIt(){
return1:+ someField; // error
}
}

private static class Second extends MyEnum {

@Override
public String doIt(){
return2:+ someField; // error
}
}

public static final MyEnum FIRST = new First();
public static final MyEnum SECOND = new Second();

private String someField;

public abstract String doIt();
}

如您所见,同样的编译器错误发生。有效地,您的问题与枚举不相关,但与内部类语义无关。



但是,您发现编译器猜测您的代码的意图的边界情况,并试图警告您,您打算是非法的。通常,任何专门的枚举可以看到 someField 字段。然而,从内部类中访问 private 字段有两种方法:


  1. private 成员不被继承。因此,在超级类中定义 c 这个实例时,您不能访问 private


  2. 对于内部类,外部类的成员即使是 private 也可以访问。这是通过编译器通过将访问器方法插入到外部类中实现的,这些外部类通过访问器方法公开 private fields。只有当内部类不是 static 时,才能访问非静态字段。对于枚举 s,内部类总是 static


稍后的条件是编译器所抱怨的:


静态引用非静态字段 someField


您正在尝试访问来自 static 内部类的非静态字段。这是不可能的,即使该领域在技术上可见,因为内部类语义。您可以通过以下方式指导编译器访问该值:例如:

  public String doIt() {
MyEnum thiz = this;
return thiz.someField;
}

现在,编译器知道您正在尝试访问可见的成员外部)类型,而不是错误地访问(非静态)外部类实例(不存在)的 someField 字段。 (同样地,你可以写 super.someField ,表示想要继承继承链的想法,而不是访问外部实例的字段。)然而,更容易的解决方案只需使字段 protected 。这样,编译器就可以继承可见性并编译您的原始设置。


The task is to implement beautiful strategy design pattern with the java enum:

public enum MyEnum {

    FIRST {
        @Override
        public String doIt() {
            return "1: " + someField; //error
        }
    },
    SECOND {
        @Override
        public String doIt() {
            return "2: " + someField; //error
        }
    };

    private String someField;

    public abstract String doIt();

} 

but when referring to someField I get

Cannot make a static reference to the non-static field someField.

What is wrong and is it possible to do that better?

解决方案

A specialized enum is nothing but a subclass with inner-class semantics. If you look at the byte code after compilation, you will notice that the compiler only inserts accessor method for reading a private field but any specialized enum is compiled as its own class. You can think about your enum as being implemented as:

public abstract class MyEnum {

  private static class First extends MyEnum {

    @Override
    public String doIt() {
        return "1: " + someField; //error
    }
  }

  private static class Second extends MyEnum {

    @Override
    public String doIt() {
        return "2: " + someField; //error
    }
  }

  public static final MyEnum FIRST = new First();
  public static final MyEnum SECOND = new Second();

  private String someField;

  public abstract String doIt();
} 

As you can see, the same compiler errors occur. Effectively, your problem does not relate to enums but to their inner-class semantics.

However, you found a borderline case of the compiler guessing the intend of your code and trying to warn you that what you intend is illegal. In general, the someField field is visible to any specialized enum. However, there are two ways of accessing the private field from an inner class and only one is legal:

  1. private members are not inherited. You can therefore not access a private field from this instance when it was defined in a super class.

  2. For inner classes, members of outer classes are accessible even if they are private. This is achieved by the compiler by inserting accessor methods to the outer classes which expose the private fields by accessor methods. A non-static field can only be accessed if the inner class is non-static. For enums, the inner classes are however always static.

The later condition is what the compiler complains about:

Cannot make a static reference to the non-static field someField

You are trying to access a non-static field from a static inner class. This is not possible even though the field would be technically visible because of the inner class semantics. You could instruct the compiler explicitly to access the value by reading it from the super class by for example:

public String doIt() {
  MyEnum thiz = this;
  return thiz.someField;
}

Now the compiler knows that you are trying to access a member of a visible (outer) type instead of erroneously accessing the someField field of the (non-static) outer class instance (which does not exist). (Similarly, you could write super.someField which expresses the same idea that you want to go down the inheritance chain and not access an outer instance's field.) The easier solution would however be to simply make the field protected. This way the compiler is happy about the inheritance visibility and compiles your original setup.

这篇关于如何通过覆盖方法在java枚举中使用字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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