gpt4 book ai didi

java - “redundant cast to java.lang.Object”警告需要强制转换

转载 作者:行者123 更新时间:2023-12-03 07:35:18 25 4
gpt4 key购买 nike

考虑这个Minimal, Reproducible Example :

interface Code {
static void main(String[] args) {
symbol(
String.valueOf(
true ? 'a' :
true ? 'b' :
true ? 'c' :
fail()
)
);
}
private static void symbol(String symbol) {
System.out.println(symbol);
}
private static <R> R fail() {
throw null;
}
}
( true接近最小,是一个有用的 boolean 表达式的代表。我们可以忽略第一个 ? :(在实际代码中,有很多)。)
这“显然”给出了错误。
4: reference to valueOf is ambiguous
both method valueOf(java.lang.Object) in java.lang.String and method valueOf(char) in java.lang.String match
好,让我们修复它。这是我想要的 String.valueOf(Object)重载-我稍后可能想要添加:
            true ? "sss" :
(实际上,我之前确实有类似的东西,但是现在删除了该功能。)
        String.valueOf((Object)(
true ? 'a' :
fail()
))
这给出了警告:
4: redundant cast to java.lang.Object
这是编译器中的错误警告或错误吗?如何解决该错误,使代码合理且没有警告或错误?
(编辑:我对MRE进行了些微更改。 throws Throwable来自 template。实际代码确实使用文字字符*和 String.valueOf,而其他地方使用了 String.valueOf(char)重载,因此 toString()有问题(哦Java!)。该代码避免了全局操作状态,例如 System.outsymbolfail在不同的类中。“switch”是不可枚举的类型。 fail是类似assert方法的伴侣,所以这就是为什么它抛出(未经检查的非null)内部异常。
不相关的是,我实际上是如何重新排列代码的,因此其中也包含一些文字字符串。否则,我将使用与 Object.class.cast等效的毫无意义的 (Object)。我真正想知道的是:wtf?
*实际上,真正的真实代码会通过一种词法分析器针对另一种语言进行处理,这种语言无法区分文字字符,字符串,各种数字, boolean 值,枚举等。为什么呢? )

最佳答案

从Java 8开始,有关``歧义方法调用''的错误是正确的。
甚至在Java 8之前,您都可以编写

char c = fail();
Object o = fail();
没有编译器错误。当您将诸如 condition? 'a': genericMethod()之类的条件传递给诸如 String.valueOf(…)之类的方法时,由于其类型推断有限,编译器会为 <Object>推断 fail()并选择 String.valueOf(Object)
但是Java 8引入了 Poly Expressions:

The type of a standalone expression can be determined entirely from the contents of the expression; in contrast, the type of a poly expression may be influenced by the expression's target type (§5 (Conversions and Contexts)).


泛型方法的调用和包含多边形表达式的条件(即泛型方法的调用)都是多边形表达式。
因此,尝试调用 String.valueOf(char)在该条件下有效,因为我们可以推断 <Character>fail()。请注意,这两种方法都不适用于 strict invocation context,因为这两种变体都需要装箱或拆箱操作。在 loose invocation context中, String.valueOf(Object)String.valueOf(char)均适用,因为在调用 Character之后取消对 fail()的包装还是对文字 char'a'进行包装都无所谓。
由于 char不是 Object的子类型,并且 Object不是 char的子类型,因此 String.valueOf(Object)String.valueOf(char)都不是 more specific,因此会生成编译器错误。

由于没有正式的警告标准,因此判断警告更为困难。在我看来,每一个声称源代码工件已过时的编译器警告都是错误的,尽管该代码在删除代码后将不会做同样的事情(或者删除它甚至会引入错误)。有趣的是,警告在Java 7版本的 javac中已经存在,在其中删除强制转换实际上没有任何作用,因此,也许这是一个需要更新的内容。

该问题的解决方法取决于具体情况,并且没有足够的信息。请注意,只有一个分支需要分配给 char,以使 String.valueOf(char)方法不适用。只要插入评估结果为 String的分支,就会发生这种情况。您还可以使用 SurroundingClass.<Object>fail()来获得与Java 8之前的编译器推断的类型相同的类型。
或者完全删除通用签名,因为这里不需要。通用方法 fail()似乎是一种解决方法,可以在表达式上下文中使用throwing方法。更干净的解决方案将是表达的工厂方法,例如
class Code {
public static void main(String[] args) throws SpecificExceptionType {
System.out.println(
String.valueOf(switch(0) {
case 0 -> 'a';
case 1 -> 'b';
case 2 -> 'c';
default -> throw fail();
})
);
}
private static SpecificExceptionType fail() {
return new SpecificExceptionType();
}
static class SpecificExceptionType extends Exception {
}
}
如果开关表达式不可行,则可以使用
System.out.println(
String.valueOf(
true ? 'a' :
true ? 'b' :
true ? 'c' :
Optional.empty().orElseThrow(Code::fail)
)
);
两者都具有特定于可能引发的异常的实际类型的优点,并且无需求助于未经检查的异常或 throws Throwable声明。第二种方法可能会让人觉得很笨拙,但不只是定义一个永不返回任何内容的通用方法。
当然,如果您只接受引入更多的代码,还有其他解决方案,例如专用于字符串转换的辅助方法(没有重载)或非泛型包装方法(用于throwing方法)。或临时变量或类型强制转换或用于通用调用的显式类型等。此外,当使用 "" + (expression)(expression).toString()而不是 String.valueOf(expression)时,该表达式不是多边形表达式,因此不会产生“歧义方法调用”错误。
当然,由于这是一个错误的警告,因此您还可以保留强制类型转换并将 @SuppressWarnings("cast")添加到方法中(并等待直到编译器开发人员将其修复为止)。

关于java - “redundant cast to java.lang.Object”警告需要强制转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64839117/

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