[英]Why can't I use wildcard with methods receiving a parameterized argument?
例如,我使用Measure.doubleValue(Unit<?> unit)
方法,该方法返回以指定Unit
表示的度量的double
Measure.doubleValue(Unit<?> unit)
值。 如果我将Unit<?>
变量传递给它,则会收到仍然非常隐秘的错误消息:
The method doubleValue(Unit<capture#27-of ?>) in the type Measurable<capture#27-of ?> is not applicable for the arguments (Unit<capture#28-of ?>)
如果有人可以解释#27-of ?
内容,我将不胜感激#27-of ?
(或任何其他数字)的意思,并且是否有一种优雅的方法可以消除这种情况。 到目前为止,我删除了<?>
并设置了调用方法@SuppressWarnings("unchecked")
(因此我传递了一个未经检查的Unit
而不是Unit<?>
),并且一切都按预期进行,但是我对此感到很好奇,我觉得抑制警告不是一个好习惯(不是有点像空的捕获块吗?)。
谢谢!
编辑:添加一些代码。
(很抱歉,这很长,但是详细说明了我遇到的问题。)
所以...如果我写这个(非常愚蠢的例子):
Measure measure = Measure.valueOf("3 m");
measure = Measure.valueOf(measure.doubleValue(Unit.valueOf("km")), Unit.valueOf("km"));
System.out.println(measure);
它可以工作并打印“ 0.0030 km”。 但我得到警告“ 措施是一个原始类型引用泛型类型测量<Q>应进行参数设置。”在第一Measure
发生和警告“ 类型安全:该方法的doubleValue(单位)所属的原始类型可测量引用通用。类型Measurable <Q>应该在 “ measure.doubleValue(Unit.valueOf("km"))
”上进行参数化 。
看到这些警告,我想我可以这样调整(仅第一行):
Measure<Length> measure = Measure.valueOf("3 m");
然后我在分配的右侧收到错误消息“ 类型不匹配:无法从Measure <capture#1-of?>转换为Measure <Length> ”。 它(Eclipse)为我提供了将正确的部分转换为(Measure<Length>)
。 但是然后我在右侧部分收到警告消息“ 类型安全:未经检查的从Measure <capture#1-of转换为Measure <Length> ”。 建议修复: @SuppressWarnings
,我希望避免使用(我想是出于偏执的原因)。
因此,我返回到Measure measure = Measure.valueOf("3 m");
并尝试将通配符赋予Measure
,显然,此刻不知道“ 3 m”是什么意思。 它可以是Length
,也可以是Mass
或Time
。 所以我得到:
Measure<?> measure = Measure.valueOf("3 m");
在这条线上没有警告或错误; 太棒了。 但是,在第二行:
measure = Measure.valueOf(measure.doubleValue(Unit.valueOf("km")), Unit.valueOf("km"));
我收到doubleValue
错误消息:“ 类型为Measurable <capture#3-of的方法doubleValue(Unit <capture#3-of?>)不适用于参数(Unit <capture#4-of? >) “。 建议将Unit.valueOf("km")
为(Unit<?>)
。 精细。 现在,我在完全相同的位置收到错误消息:“ 类型为Measurable <capture#3-of?>的方法doubleValue(Unit <capture#3-of?>)不适用于参数(Unit <capture#5 -of?>) ”。 请注意,数字已更改,因此这不是完全相同的参数,而是相似的原因。 然后,它执行完全相同的建议,因为它已经完成了,因此不会导致代码中的任何更改。
这就是困扰我的原因。 使它工作的唯一方法似乎是@SuppressWarnings
或忽略它们。 奇怪吗?
度量值类看起来像这样吗?
class Measure<T> {
double doubleValue(Unit<T> unit) {
...
}
}
在这种情况下,引用类型为Measure<?>
并不意味着您可以将任何类型的Unit
传递给doubleValue
方法。 相反,这意味着Measure
实例具有未知的泛型类型,并且将Unit
传递给其doubleValue
方法并不安全,因为编译器无法确保类型兼容。
通配符并不意味着“任何类型”; 它的意思是“未知类型”。
更新:
valueOf(CharSequence)
返回未知类型的Measure
Measure<?>
。 要将其安全地转换为所需的Measure
类型,必须使用Measure.asType()
方法。 与由Unit.valueOf(CharSequence)
方法创建的目标Unit
Unit.valueOf(CharSequence)
。
Measure<?> unknownMeasure = valueOf("3 m");
Unit<?> unknownUnit = Unit.valueOf("km");
Measure<Length> length = unknownMeasure.asType(Length.class);
Unit<Length> kilometer = unknownUnit.asType(Length.class);
length.doubleValue(kilometer);
查看Measure
类文档中的示例。 它们将提供一些额外的深度。
Java泛型中的通配符表示“未知类型”。 在这里,将doubleValue()
方法定义为接受Unit<something1>
,其中方法未指定something1
。 然后,您将一些未知的something2
的值传递给调用方,它称为Unit<something2>
。 编译器错误消息表示没有任何东西可以保证something1
和something2
指定相同的内容。
尝试这个:
<T> double doubleValue(Unit<T> unit)
{
...
}
这意味着doubleValue()
不在乎 T
是什么。
为了扩展其他(出色的)答案,但是要具体一些JSR-275(我现在正在将其用于项目)。
这一点很有趣
建议修复:@SuppressWarnings,我希望避免使用(我想是出于偏执的原因)。
您是对偏执的想法是正确的,但是请考虑一下:您要告诉Measure
类解析任意String
,并返回任何类型的Measure
。 显然,在这种情况下,您可能会或可能不会获得Measure<Length>
(可能会传递“ 3 kg”),因此,留给库的唯一选择是返回Measure<?>
。 如果您想要一个Measure<Length>
,那么您必须以某种方式将其强制为-可能无法保证在编译时是安全的。
在这种情况下,我认为@SuppressWarnings是完全可以接受的, 假设您知道字符串将始终是有效长度。 如果不是这样,您将不可避免的ClassCastException
推迟到以后,这很糟糕。
但是 ,更好的(呼啦!)JSR-275确实为您提供了解决方法,将错误处理推到了正确的位置(在获得Measure
,而不是在使用它后的某个时候)。 尝试
Measure<Length> = Measure.valueOf("3 m").asType(Length.class);
asType
返回相应的Measure
通用类型,或者如果解析的单元的尺寸不是length,则失败,但异常-这几乎可以肯定是您想要的,对吧?
我认为这可以解决您的问题。
我无法重现您的问题,即以下代码可以正常编译(至少使用eclipse):
static double doubleValue(Unit<?> unit) {
return 0;
}
static void bla(Unit<?> u) {
doubleValue(u);
}
public static void main(String[] args) {
doubleValue(new Unit<String>());
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.