Java枚举定义
我原以为自己非常了解Java泛型,但后来在Java.lang.Enum中遇到了以下问题:Java枚举定义,java,generics,enums,crtp,Java,Generics,Enums,Crtp,我原以为自己非常了解Java泛型,但后来在Java.lang.Enum中遇到了以下问题: class Enum<E extends Enum<E>> 类枚举 有人能解释一下如何解释这个类型参数吗?提供其他可以使用类似类型参数的示例的好处。这意味着enum的类型参数必须派生自本身具有相同类型参数的enum。这怎么会发生?通过使类型参数成为新类型本身。因此,如果我有一个名为StatusCode的枚举,它将相当于: public class StatusCode exten
class Enum<E extends Enum<E>>
类枚举
有人能解释一下如何解释这个类型参数吗?提供其他可以使用类似类型参数的示例的好处。这意味着enum的类型参数必须派生自本身具有相同类型参数的enum。这怎么会发生?通过使类型参数成为新类型本身。因此,如果我有一个名为StatusCode的枚举,它将相当于:
public class StatusCode extends Enum<StatusCode>
这意味着您可以从消息中获得适当的生成器(例如,获取消息副本并更改某些位),并且在构建完成后,您可以从生成器中获得适当的消息。这是一个很好的工作,不过API的用户不需要真正关心这个问题——它非常复杂,需要多次迭代才能达到目的
编辑:请注意,这并不会阻止您创建使用类型参数的奇数类型,该参数本身是可以的,但它不是相同的类型。这样做的目的是在正确的情况下提供好处,而不是在错误的情况下保护您
因此,如果Enum
不是在Java中“专门”处理的,您可以(如注释中所述)创建以下类型:
public class First extends Enum<First> {}
public class Second extends Enum<First> {}
public类首先扩展Enum{}
公共类第二次扩展枚举{}
Second
将实现Comparable
而不是Comparable
。。。但是首先本身就可以了。你不是唯一一个想知道这意味着什么的人;看
“如果一个类扩展了这个类,它应该传递一个参数E。参数E的边界是针对一个使用相同参数E扩展这个类的类的。”以下是Java泛型和集合一书中解释的修改版本: 我们声明了一个
Enum
enum Season { WINTER, SPRING, SUMMER, FALL }
它将扩展为一个类
final class Season extends ...
其中,…
是枚举的参数化基类。让我们工作吧
知道那是什么。嗯,季节
的一个要求是它应该实现可比
。所以我们需要
Season extends ... implements Comparable<Season>
因此Enum
在seasure
等类型上被参数化。摘自<代码>季刊<代码>和
您可以得到Enum
的参数是满足以下条件的任何类型
E extends Enum<E>
E扩展枚举
Maurice Naftalin(Java泛型和集合的合著者)这篇文章向我彻底澄清了这些“递归泛型类型”的问题。 我只是想添加另一种情况,这种特殊的结构是必要的 假设在通用图中有通用节点:
public abstract class Node<T extends Node<T>>
{
public void addNeighbor(T);
public void addNeighbors(Collection<? extends T> nodes);
public Collection<T> getNeighbor();
}
公共抽象类节点
{
公共空间(T);
public void addneights(Collection这可以通过一个简单的示例和一种可用于实现子类的链式方法调用的技术来说明。在下面的示例中,setName
返回一个节点
,因此链式方法对城市
不起作用:
class Node {
String name;
Node setName(String name) {
this.name = name;
return this;
}
}
class City extends Node {
int square;
City setSquare(int square) {
this.square = square;
return this;
}
}
public static void main(String[] args) {
City city = new City()
.setName("LA")
.setSquare(100); // won't compile, setName() returns Node
}
因此我们可以在泛型声明中引用一个子类,这样City
现在返回正确的类型:
abstract class Node<SELF extends Node<SELF>>{
String name;
SELF setName(String name) {
this.name = name;
return self();
}
protected abstract SELF self();
}
class City extends Node<City> {
int square;
City setSquare(int square) {
this.square = square;
return self();
}
@Override
protected City self() {
return this;
}
public static void main(String[] args) {
City city = new City()
.setName("LA")
.setSquare(100); // ok!
}
}
抽象类节点{
字符串名;
SELF-setName(字符串名){
this.name=名称;
返回自我();
}
受保护的抽象自我();
}
类城市扩展节点{
内景广场;
城市广场(国际广场){
这个正方形=正方形;
返回自我();
}
@凌驾
受保护城市自我保护(){
归还这个;
}
公共静态void main(字符串[]args){
城市=新城()
.setName(“LA”)
.setSquare(100);//好的!
}
}
如果查看Enum
源代码,它有以下内容:
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable {
public final int compareTo(E o) {
Enum<?> other = (Enum<?>)o;
Enum<E> self = this;
if (self.getClass() != other.getClass() && // optimization
self.getDeclaringClass() != other.getDeclaringClass())
throw new ClassCastException();
return self.ordinal - other.ordinal;
}
@SuppressWarnings("unchecked")
public final Class<E> getDeclaringClass() {
Class<?> clazz = getClass();
Class<?> zuper = clazz.getSuperclass();
return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;
}
public static <T extends Enum<T>> T valueOf(Class<T> enumType,
String name) {
T result = enumType.enumConstantDirectory().get(name);
if (result != null)
return result;
if (name == null)
throw new NullPointerException("Name is null");
throw new IllegalArgumentException(
"No enum constant " + enumType.getCanonicalName() + "." + name);
}
}
如果我没有弄错的话,可以翻译成
public final class MyEnum extends Enum<MyEnum> {
public static final MyEnum THING1 = new MyEnum();
public static final MyEnum THING2 = new MyEnum();
}
public final类MyEnum扩展了Enum{
public static final MyEnum THING1=new MyEnum();
public static final MyEnum THING2=新的MyEnum();
}
这意味着MyEnum接收以下方法:
public final int compareTo(MyEnum o) {
Enum<?> other = (Enum<?>)o;
Enum<MyEnum> self = this;
if (self.getClass() != other.getClass() && // optimization
self.getDeclaringClass() != other.getDeclaringClass())
throw new ClassCastException();
return self.ordinal - other.ordinal;
}
public final int compareTo(MyEnum o){
枚举其他=(枚举)o;
Enum self=this;
if(self.getClass()!=other.getClass()&&//优化
self.getDeclaringClass()!=其他.getDeclaringClass())
抛出新的ClassCastException();
返回self.ordinal-other.ordinal;
}
更重要的是
@SuppressWarnings("unchecked")
public final Class<MyEnum> getDeclaringClass() {
Class<?> clazz = getClass();
Class<?> zuper = clazz.getSuperclass();
return (zuper == Enum.class) ? (Class<MyEnum>)clazz : (Class<MyEnum>)zuper;
}
@SuppressWarnings(“未选中”)
公共最终类getDeclaringClass(){
Class clazz=getClass();
类zuper=clazz.getSuperclass();
return(zuper==Enum.class)?(class)clazz:(class)zuper;
}
这使得getDeclaringClass()
转换为正确的Class
对象
一个更清楚的例子是我回答的,如果你想指定一个泛型绑定,就不能避免这个构造。根据维基百科,这个模式被称为。
基本上,通过使用CRTP模式,我们可以很容易地引用子类类型而无需类型转换,这意味着通过使用该模式,我们可以模拟虚拟函数。它仍然允许我创建一个类Foo extensed Node
,其中Foo与城市无关。当然,这是错的吗?我不这么认为。Node提供的基本契约是st很遗憾,只有你的Foo子类没那么有用,因为你开始使用Foos,但把Cities从ADT中去掉了。这可能有一个用例,但很可能更简单、更有用,只是让泛型参数与子类相同。但不管怎样,设计者都有这个选择。@mdma:我同意。那么绑定提供了什么用途呢,而不仅仅是类节点
?@nozeballe:您的示例没有证明“这个特定结构是必要的”。类节点
与您的示例完全一致。@artsrc:我不记得为什么它需要在两个构建中都是泛型的
public enum MyEnum {
THING1,
THING2;
}
public final class MyEnum extends Enum<MyEnum> {
public static final MyEnum THING1 = new MyEnum();
public static final MyEnum THING2 = new MyEnum();
}
public final int compareTo(MyEnum o) {
Enum<?> other = (Enum<?>)o;
Enum<MyEnum> self = this;
if (self.getClass() != other.getClass() && // optimization
self.getDeclaringClass() != other.getDeclaringClass())
throw new ClassCastException();
return self.ordinal - other.ordinal;
}
@SuppressWarnings("unchecked")
public final Class<MyEnum> getDeclaringClass() {
Class<?> clazz = getClass();
Class<?> zuper = clazz.getSuperclass();
return (zuper == Enum.class) ? (Class<MyEnum>)clazz : (Class<MyEnum>)zuper;
}