我是java的新手,在我的组织中遇到了一些高级的Enum代码。
我熟悉定义如下的枚举:public enum someList { VALUE1, VALUE2, ..}
但是在我遇到的高级枚举中,似乎还有很多......
/**
* Defines ways to compare records in {@link ApplicationStatus} to see if they
* are the same.
*/
public enum SourceStatusComparisonType
{
CONTEXT_KEY
{
@Override
public boolean compareKeys(SourceStatus source, ApplicationStatus status)
{
return source.getContextKey() == status.getSourceContextId();
}
},
DATE
{
@Override
public boolean compareKeys(SourceStatus source, ApplicationStatus status)
{
return source.getCobDate().equals(status.getCobDate());
}
};
public abstract boolean compareKeys(SourceStatus source,
ApplicationStatus status);
}
有人可以通过覆盖和重载的抽象方法来了解正在发生的事情。我不明白上面发生了什么。我被告知这被用来从使用它的代码中抽象出if / else块。但我不确定我理解。
提前谢谢。
答案 0 :(得分:4)
每个枚举常量可以选择后跟一个类主体,如JLS §8.9中所指定。
枚举常量的可选类体隐式定义了一个匿名类声明(第15.9.5节),该声明扩展了直接封闭的枚举类型。班级团体由匿名班级的通常规则管理;特别是它不能包含任何构造函数。
因此,它就像使用抽象方法SourceStatusComparisonType
创建一个抽象类compareKeys()
。您创建该类的2个实例:
CONTEXT_KEY = new SourceStatusComparisonType() {
@Override
public void compareKeys() { .. }
};
DATE = new SourceStatusComparisonType() {
@Override
public void compareKeys() { .. }
};
并覆盖每个实例的抽象方法。没有该方法的实现,您不能拥有任何实例。
类似地,所有枚举常量必须在其各自的匿名类主体中提供抽象方法的实现。否则,你不能把那个方法当作抽象的。您必须提供一个主体,默认情况下将用于枚举常量,但不提供该方法实现:
public enum SourceStatusComparisonType
{
CONTEXT_KEY
{
@Override
public boolean compareKeys(SourceStatus source, ApplicationStatus status)
{
return source.getContextKey() == status.getSourceContextId();
}
},
DATE
{
@Override
public boolean compareKeys(SourceStatus source, ApplicationStatus status)
{
return source.getCobDate().equals(status.getCobDate());
}
},
DEFAULT;
public boolean compareKeys(SourceStatus source,
ApplicationStatus status) {
// return somedefaultvalue;
}
}
因此,对于前两个常量,当您调用compareKeys
方法时,将使用它们的具体实现,对于DEFAULT
,将使用外部定义的方法。
答案 1 :(得分:1)
枚举类型可以像抽象方法一样具体,所有枚举常量都应该实现那些抽象方法。
在这里查看JSL http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9.2并转到Example 8.9.2-4. Enum Constants with Class Bodies
部分。
您甚至可以使用接口实现ENUM,而不是使用抽象方法。类似于public enum SourceStatusComparisonType implements StatusComparable
。
答案 2 :(得分:1)
你需要了解的关于Java中Enum的首要问题是它们是类,将它们视为类。因此,您学到的所有面向对象的设计/编程概念都适用于它们。
想象一下你制作的宇宙,其中只有3种生物,猫,牛和狗。一个实现是
public abstract class Animal
{
private final String name;
public Animal(String name) {
this.name = name;
}
public abstract String sayHello(Animal other);
}
public class Cat extends Animal
{
public Cat(String name) {
super(name);
}
@Override
public String sayHello(Animal other) {
System.out.println(this.name + " says Meow!!! to " + other.name);
}
}
public class Cow extends Animal
{
public Cow(String name) {
super(name);
}
@Override
public String sayHello(Animal other) {
System.out.println(this.name + " says Moo!!! to " + other.name);
}
}
public class Dog extends Animal
{
public Dog(String name) {
super(name);
}
@Override
public String sayHello(Animal other) {
System.out.println(this.name + " says Woof!!! to " + other.name);
}
}
public Universe {
public List<Animal> animals;
public Universe(List<Animal> animals) {
this.animals = animals;
}
public void run() {
for (Animal animal : animals) {
for (Animal other : animals) {
if (other != animal) {
animal.sayHello(other);
}
}
}
}
}
您对Universe感到满意并将其部署到生产环境中。只有发现,另一个恶意开发者已经为你的宇宙引入了一个新生物,一个僵尸
public class Zombie extends Animal
{
public Zombie(String name) {
super(name);
}
public String sayHello(Animal other) {
System.out.println(this.name + " says Arrggggg!!! to " + other.name);
eat(other);
}
private void eat(Animal other) {
System.out.println("nomm nomm " + other.name);
}
}
以打招呼为幌子的僵尸吃掉了他们遇到的所有动物。很快就会有没有猫,狗和奶牛离开。您决定部署Universe的第2版以防止这种情况并防范僵尸
public Universe2 {
public List<Animal> animals;
public Universe(List<Animal> animals) {
this.animals = animals;
}
public void run() {
for (Animal animal : animals) {
for (Animal other : animals) {
if (other != animal) {
if (!(animal instanceof Zombie))
animal.sayHello(other);
}
}
}
}
}
你现在很高兴,但你注意到猫的数量在减少,猫和狗不再是朋友,僵尸已经感染了他们的大脑,你部署了宇宙的第3版。
public Universe3 {
public List<Animal> animals;
public Universe(List<Animal> animals) {
this.animals = animals;
}
public void run() {
for (Animal animal : animals) {
for (Animal other : animals) {
if (other != animal) {
if (!(animal instanceof Zombie) && !((animal instanceof Cat) && (animal instanceof Dog)))
animal.sayHello(other);
}
}
}
}
}
在这个版本中,没有僵尸。猫和狗向奶牛问好,但彼此不和。宇宙处于平衡状态,但你有一种唠叨的感觉,即世界并非一切都是正确的。你沉睡在它上面,并意识到你可以接受类似于僵尸的攻击,你决定锁定宇宙并实施重写,从头开始并完全消除僵尸流行病。除了你喜欢打招呼的友善僵尸。
public Enum Animal {
Cat {
@Override
public String sayHello(Animal other) {
System.out.println(this.name + " says Meow!!! to " + other.name);
}
},
Cow {
@Override
public String sayHello(Animal other) {
System.out.println(this.name + " says Moo!!! to " + other.name);
}
},
Dog {
@Override
public String sayHello(Animal other) {
System.out.println(this.name + " says Woof!!! to " + other.name);
}
},
Zombie {
@Override
public String sayHello(Animal other) {
System.out.println(this.name + " says Argggg!!! to " + other.name);
}
};
private String name;
public Animal(String name) {
this.name.
}
public String sayHello(Animal other);
}
public PerfectUniverse {
public List<Animal> animals;
public Universe(List<Animal> animals) {
this.animals = animals;
}
public void run() {
for (Animal animal : animals) {
for (Animal other : animals) {
if (other != animal) {
animal.sayHello(other);
}
}
}
}
}
您已使用继承消除了条件if,但使用枚举锁定了可扩展性。您可以使用类来执行相同的操作,限制对包外的Animal的访问,并使派生类型成为final。这个enum Cat作为Cat扩展Animal的一个例子。具有重写方法的派生类型避免了使用if条件进行检查的实例。