gpt4 book ai didi

java - 使用通用返回类型覆盖抽象枚举方法时出现编译错误

转载 作者:搜寻专家 更新时间:2023-11-01 03:33:01 24 4
gpt4 key购买 nike

这是一段可以正确编译的代码

public enum SupportedConversions {
INTEGER {
@Override
public Integer convert( String ion, Object[] aa) {
return null;
}
},
LONG {
@Override
public Long convert(final String ion, Object[] aa) {
return null;
}
};

public abstract <T> T convert(String val, Object[] aa);
}

但是当我将抽象函数参数更改为对象列表而不是数组时,出现编译错误“方法不从父类(super class)覆盖”。只有当返回类型是泛型时才会发生这种情况

错误代码示例

public enum SupportedConversions {
INTEGER {
@Override
public Integer convert( String ion, List<Object> aa) {
return null;
}
},
LONG {
@Override
public Long convert(final String ion, List<Object> aa) {
return null;
}
};

public abstract <T> T convert(String val, List<Object> aa);
}

有没有这行不通的原因。看起来更像是 Java 中的错误

最佳答案

问题应该是“为什么第一个可以编译”而不是“为什么第二个失败”。
两个都坏了。

像这样的方法签名

<T> T convert(String val, Object[] aa)

说“无论调用者用什么代替 T ,此方法将返回兼容的结果”。这不是很有用,因为唯一有效的返回值是 null ,但至少,当您尝试在以这种方式声明的方法中返回不兼容的结果时,编译器会告诉您。

但是子类重写这个方法就像

Long convert(final String ion, Object[] aa)

换句话说,用一个总是返回 Long 的方法覆盖一个 promise 返回调用者希望的任何方法的方法。 .首先应该感觉不对……返回时结果仍然兼容 null ,但当您返回非 null 时则不会Long值,编译器甚至不会警告你,因为 Long value 与 Long 的声明返回类型兼容.

然而,编译器本应发出有关方法声明本身的警告。为了演示这个问题,您可以使用该声明编写

String s = SupportedConversions.LONG.convert("bla", null);

编译器不会反对。如前所述,基本类型声明 <T> T convert(…) promise 返回调用者为 T 假设的任何内容在这里,T已被推断为String .当实现返回 Long 时,这显然会在运行时中断。实例。


之所以可以编译,是因为它与泛型之前的代码兼容。目的是让具有不同“泛化”状态的图书馆进行互动。例如。您可以使用最新的 jdk 编译 Java 1.4 应用程序代码,即使某些类覆盖了 now-Generic 方法。

所以 convert允许子类中不使用泛型的方法覆盖 convert基类的方法。相反,像

这样的方法声明
Long convert(final String ion, List<Object> aa)

正在使用泛型,因此不允许绕过泛型类型系统。如果使用原始类型 List取而代之的是,您再次拥有一个非泛型声明,它可以绕过泛型。


如果您现在想说,在这里假设泛型之前的行为是不合逻辑的,那么您并不孤单。不仅因为覆盖方法与被覆盖的通用声明在同一编译单元(enum 声明)内,两者都在 enum 内声明,一种在 Java 5(引入了泛型)之前不存在的句法结构。

此外,覆盖方法利用协变返回类型Long分别Integer其中方法声明的删除返回类型为 Object ,也不能出现在 Java 5 之前的代码中。

但这些(仍然)是规则。您应该注意此处的编译器警告。如果您没有收到警告(我知道 Netbeans IDE 的默认设置很草率),您应该尝试启用它们。


此代码没有修复。使用 enum 是不可能的秒。您可以删除类型参数 T并让基类型的方法声明返回 Object ,但是 enum 中的协变返回类型常量无关紧要,因为它们不是 public 的一部分应用程序接口(interface)。最好的选择是:

public interface SupportedConversions<T> {
SupportedConversions<Integer> INTEGER = (String ion, Object[] aa) -> {
return null;
};
SupportedConversions<Long> LONG = (String ion, Object[] aa) -> {
return null;
};
public abstract T convert(String val, Object[] aa);
}

回复

public interface SupportedConversions<T> {
SupportedConversions<Integer> INTEGER = (ion, aa) -> {
return null;
};
SupportedConversions<Long> LONG = (ion, aa) -> {
return null;
};
public abstract T convert(String val, List<Object> aa);
// we can support both variants
public default T convert(String val, Object[] aa) {
return convert(val, Arrays.asList(aa));
}
}

关于java - 使用通用返回类型覆盖抽象枚举方法时出现编译错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42605371/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com