为什么这个枚举不能编译?

发布于 2024-10-19 14:38:50 字数 323 浏览 1 评论 0 原文

为什么这个枚举不能编译?

public enum Ackr implements Cloneable{
    INSTANCE;

    public <Ackr extends Cloneable> Ackr getInstance(){
        return INSTANCE; //Type mismatch: cannot convert from Ackr to Ackr
//      return (Ackr)INSTANCE; //Type safety: Unchecked cast from Ackr to Ackr
    }
}

Why this enum doesn't compile?

public enum Ackr implements Cloneable{
    INSTANCE;

    public <Ackr extends Cloneable> Ackr getInstance(){
        return INSTANCE; //Type mismatch: cannot convert from Ackr to Ackr
//      return (Ackr)INSTANCE; //Type safety: Unchecked cast from Ackr to Ackr
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

心如狂蝶 2024-10-26 14:38:50

据我所知,这种类型参数是不必要的。简单地尝试一下

public Ackr getInstance(){
    return INSTANCE;
}

That type argument is, as far as I know, not neccessary. Try simply

public Ackr getInstance(){
    return INSTANCE;
}
甲如呢乙后呢 2024-10-26 14:38:50

您想通过此签名实现什么目的?

public <Ackr extends Cloneable> Ackr getInstance() ...

你就不能写这个吗?

public Ackr getInstance() ...

我还认为扩展 Clonableenum 有点无意义。 enum 无法复制...枚举的值只有一个。

What are you trying to achieve with this signature?

public <Ackr extends Cloneable> Ackr getInstance() ...

Can't you just write this?

public Ackr getInstance() ...

I also think that an enum that extends Clonable is kind of nonsensical. An enum cannot be copied ... there is only ever one of value of the enum.

如痴如狂 2024-10-26 14:38:50

我发现您对泛型有误解。枚举类 Ackr 与类型 不同。

public Ackr getInstance()

您可以使用上述方法声明定义一个新类型。它与枚举类 Ackr 完全不同。这就是你的类无法编译的原因。

I see that you have a misunderstanding about generics.. Enum class Ackr is not same with the type <Ackr extends Cloneable .

public <Ackr extends Cloneable> Ackr getInstance()

You define a new type with with above method declaration. It is completely different than enum class Ackr. That is why your class could not be compiled.

烦人精 2024-10-26 14:38:50

您在评论中写道:

我认为没有理由 ,但是在什么情况下这个构造才有意义?

这是您的方法的类型参数。

public <Ackr extends Cloneable> Ackr getInstance(){ ... }

定义一个方法,该方法返回扩展 Cloneable 的某种类型的对象(可由调用者选择)。此方法只能合法地返回 null (因为您现在无法知道调用者选择了哪种类型,并且 null 是所有引用类型中唯一常见的值)或抛出一个例外,因此它并不是真正有用。

这里的类型参数 Ackr 与你的同名枚举类没有关系,所以你最好这样写:

public <A extends Cloneable> A getInstance(){ ... }

Java API 中有一些例子,其中类型参数的这种用法仅用于返回类型 - 但随后它们返回一些参数化类型(并且方法的类型参数用作返回类型的类型参数)。例如,查找 Collections.emptySet()

更常见的是,方法的类型参数用在方法的参数类型中(仅或附加于返回类型)。

 public <A> A getFirstElement(Iterable<A> list);

此方法采用某种类型 A 的 Iterable,并返回此类型 A 的对象。(从名称来看,人们会认为它采用此可迭代的第一个元素。)以下是一个实现:

 public <A> A getFirstElement(Iterable<A> list) {
     Iterator<A> it = list.iterator();
     if(it.hasNext()) {
         return it.next();
     }
     return null;
 }

通常: 如果你有一个类型参数(任何地方),请确保你没有将它命名为与某些现有类型相同的名称(就像你在这里所做的那样) - 它会掩盖你现有的类型,由于奇怪的错误消息而导致极大的混乱,例如Ackr 不可分配给 Ackr

这就是类型参数通常具有一个(或很少两个)字符名称的原因,例如 E(元素类型)、KV(键)和地图的值类型),T(一般类型)。

You wrote in a comment:

I think there is no reason for <Ackr extends Cloneable>, but in which context this construct would make sense?

This is a type parameter for your method.

public <Ackr extends Cloneable> Ackr getInstance(){ ... }

defines a method which returns an object of some type (electable by the caller) which extends Cloneable. This method could only legally return null (since you have no way to now which type the caller elected, and null is the only value common in all reference types) or throw an exception, thus it is not really useful.

The type parameter Ackr here has no relation to your enum class of same name, so you would better write it like this:

public <A extends Cloneable> A getInstance(){ ... }

There are some examples in the Java API which have such uses of type parameters only used in the return type - but then they return some parametrized type (and the type parameter of the method is used as a type parameter for the return type). Look for Collections.emptySet(), for example.

More often, the type parameters of a method are used in the parameter types of the method (only or additional to return type).

 public <A> A getFirstElement(Iterable<A> list);

This method takes an Iterable of some type A, and returns an object of this type A. (From the name, one would suppose it takes the first element of this iterable.) Here is an implementation:

 public <A> A getFirstElement(Iterable<A> list) {
     Iterator<A> it = list.iterator();
     if(it.hasNext()) {
         return it.next();
     }
     return null;
 }

Generally: If you have a type parameter (anywhere), please make sure you don't name it the same as some existing type (like you did here) - it will shadow your existing type, leading to great confusion because of strange error messages like Ackr is not assignable to Ackr.

This is the reason type parameters often have one (or seldom two) character names like E (element-type), K, V (key and value type for maps), T (type in general).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文