java里覆盖字段怎么做,如何通过覆盖方法在java枚举中使用字段?

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:

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

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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在JDK1.5 之前,我们定义常量都是: publicstaticfianl.... 。现在好了,有了枚举,可以把相关的常量分组到一个枚举类型,而且枚举提供了比常量更多的方法。 public enum Color { RED, GREEN, BLANK, YELLOW } 用法二:switch JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强。 enum Signal { GREEN, YELLOW, RED } public class TrafficLight { Signal color = Signal.RED; public void change() { switch (color) { case RED: color = Signal.GREEN; break ; case YELLOW: color = Signal.RED; break ; case GREEN: color = Signal.YELLOW; break ; } } } 用法三:向枚举添加新方法 如果打算自定义自己的方法,那么必须在enum实例序列的最后添加一个分号。而且 Java 要求必须先定义 enum实例。 public enum Color { RED("红色" , 1 ), GREEN( "绿色" , 2 ), BLANK( "白色" , 3 ), YELLO( "黄色" , 4 ); // 成员变量 private String name; private int index; // 构造方法 private Color(String name, int index) { this .name = name; this .index = index; } // 普通方法 public static String getName( int index) { for (Color c : Color.values()) { if (c.getIndex() == index) { return c.name; } } return null ; } // get set 方法 public String getName() { return name; } public void setName(String name) { this .name = name; } public int getIndex() { return index; } public void setIndex( int index) { this .index = index; } } 用法四:覆盖枚举方法 下面给出一个toString()方法覆盖的例子。 public enum Color { RED("红色" , 1 ), GREEN( "绿色" , 2 ), BLANK( "白色" , 3 ), YELLO( "黄色" , 4 ); // 成员变量 private String name; private int index; // 构造方法 private Color(String name, int index) { this .name = name; this .index = index; } //覆盖方法 @Override public String toString() { return this .index+ "_" + this .name; } } 用法五:实现接口 所有的枚举都继承自java.lang.Enum类。由于Java 不支持多继承,所以枚举对象不能再继承其他类。 public interface Behaviour { void print(); String getInfo(); } public enum Color implements Behaviour{ RED("红色" , 1 ), GREEN( "绿色" , 2 ), BLANK( "白色" , 3 ), YELLO( "黄色" , 4 ); // 成员变量 private String name; private int index; // 构造方法 private Color(String name, int index) { this .name = name; this .index = index; } //接口方法 @Override public String getInfo() { return this .name; } //接口方法 @Override public void print() { System.out.println(this .index+ ":" + this .name); } } 用法六:使用接口组织枚举 public interface Food { enum Coffee implements Food{ BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO } enum Dessert implements Food{ FRUIT, CAKE, GELATO } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值