例如,我使用方法Measure.doubleValue(Unit<?> unit)
返回测量的double
值,以指定的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 ?
(或任何其他数字)意味着什么,以及是否有一种优雅的方式来摆脱这种情况,我将不胜感激。到目前为止,我删除了<?>
并设置了调用方法@SuppressWarnings("unchecked")
(因此我传递了未经检查的Unit
而不是Unit<?>
),一切都按预期工作,但我'我只是好奇这个,我觉得压制警告不是一个好习惯(不是有点像空挡块吗?)。
谢谢!
编辑:添加一些代码。
(对不起,这很长,但它详细解释了我所坚持的内容。)
我正在使用JSR-275 version 0.9.4(最近)。
所以...如果我写这个(非常愚蠢的例子):
Measure measure = Measure.valueOf("3 m");
measure = Measure.valueOf(measure.doubleValue(Unit.valueOf("km")), Unit.valueOf("km"));
System.out.println(measure);
工作并打印“0.0030 km”。但是我收到警告“ Measure是一种原始类型。在第一次Measure
出现时引用通用类型Measure&lt; Q&gt;参数化”并警告“类型安全:方法doubleValue(Unit)属于原始类型Measurable。对泛型类型的参考可测量&lt; Q&gt;应参数化“over measure.doubleValue(Unit.valueOf("km"))
。
看到这些警告,我想我可以这样调整(仅限第一行):
Measure<Length> measure = Measure.valueOf("3 m");
然后我在分配的右侧部分收到错误消息“类型不匹配:无法从Measure&lt; capture#1-of?&gt;转换为Measure&lt; Length&gt; ”。它(Eclipse)让我把正确的部分投射到(Measure<Length>)
。但后来我在右边的部分得到了警告信息“类型安全:从测量&lt;捕获#1-of?&gt;中未经检查的强制转换为测量&lt;长度&gt; ”。修正建议:@SuppressWarnings
我更愿意避免(因为我想是偏执的原因)。
所以,我回到Measure measure = Measure.valueOf("3 m");
并尝试给Measure
添加通配符,显然,它不知道此时“3米”是什么意思。它可以是Length
,也可以是Mass
或Time
。所以我得到了:
Measure<?> measure = Measure.valueOf("3 m");
此线上没有任何警告或错误;太棒了。但是,在第二行:
measure = Measure.valueOf(measure.doubleValue(Unit.valueOf("km")), Unit.valueOf("km"));
我收到了doubleValue
的错误消息:“类型为Measurable&lt; capture#3-of?&gt;的方法doubleValue(Unit&lt; capture#3-of?&gt;)不适用对于参数(单位&lt; capture#4-of?&gt;)“。它建议将Unit.valueOf("km")
转换为(Unit<?>)
。精细。现在我在完全相同的位置收到错误消息:“类型Measurable&lt; capture#3-of?&gt;中的方法doubleValue(Unit&lt; capture#3-of?&gt;)不适用于参数(单位&lt;捕获#5-of?&gt;)“。请注意,数字已经改变,因此不是完全相同的参数,而是类似的原因。然后它执行完全相同的建议,这导致代码中没有任何变化,因为它已经完成。
这就是困扰我的事情。让它工作的唯一方法似乎是@SuppressWarnings
或者只是忽略它们。这不奇怪吗?
答案 0 :(得分:3)
度量类看起来像这样吗?
class Measure<T> {
double doubleValue(Unit<T> unit) {
...
}
}
在这种情况下,引用类型Measure<?>
并不意味着您可以将任何类型的Unit
传递给doubleValue
方法。相反,它意味着Measure
实例具有未知的泛型类型,并且将Unit
传递给其doubleValue
方法是不安全的,因为编译器无法确保类型是兼容的
通配符不表示“任何类型”;它的意思是“未知类型”。
<强>更新强>
valueOf(CharSequence)
会返回未知类型的Measure
- Measure<?>
。要将此安全地转换为您期望的Measure
类型,您必须使用Measure.asType()
方法。与目标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
类文档中的示例。它们将提供一些额外的深度。
答案 1 :(得分:2)
Java泛型中的通配符表示“未知类型”。在这里,您将doubleValue()
方法定义为接受Unit<something1>
,其中方法未指定something1
。然后,您将调用者知道的值Unit<something2>
传递给某个未知something2
。编译器错误消息表示没有任何内容可以保证something1
和something2
指定相同的内容。
试试这个:
<T> double doubleValue(Unit<T> unit)
{
...
}
这意味着doubleValue()
不关心 T
是什么。
答案 2 :(得分:1)
要扩展其他(优秀)答案,但要更具体JSR-275(我现在正在将它用于项目)。
这一点很有意思
修复建议:@SuppressWarnings,我宁愿避免(因为偏执的原因,我猜)。
你是偏执狂是正确的,但要想一想:你告诉Measure
班解析任意String
,并返回任何类型的Measure
。显然,在这种情况下,您可能会或可能不会得到Measure<Length>
(您可能会传递“3公斤”),因此留给图书馆的唯一选择是返回Measure<?>
。如果你想要一个Measure<Length>
,那么你必须以某种方式强制它 - 这在编译时不可能保证安全。
在这种情况下,我认为@SuppressWarnings是完全可以接受的,假设你知道字符串将始终是有效长度。如果没有,你就会推迟一个不可避免的ClassCastException
直到以后,这是非常糟糕的。
但是甚至更好(万岁!)JSR-275确实为您提供了解决方法,将错误处理推送到“正确”的位置(在获取{{1}时) },在使用它之后的某个时刻。尝试
Measure
Measure<Length> = Measure.valueOf("3 m").asType(Length.class);
返回asType
的相应通用版本,如果解析单元的维度不是长度,则会失败并出现异常 - 这几乎可以肯定你想要的,对吗?
我认为这可以解决您的问题。
答案 3 :(得分:0)
我无法重现你的问题,即以下编译好(至少使用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>());
}