问题标签 [unbounded-wildcard]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - 通过转换为具体(无界通配符)类型产生的意外未经检查的转换警告
我曾认为强制转换为无界通配符类型永远不会产生“未经检查的强制转换”警告,因为无界通配符类型已被具体化,因此安全完成强制转换所需的类型信息将在运行时出现,即“强制转换为泛型类”任何(未知)类型的实例。”
此方法在指示的行产生未经检查的强制转换警告:
该方法obtainMetadata()
返回一个Optional<T>
where<T>
是有界类型的参数<T extends DateSerial<T>>
。正如您可以从上面的代码中推断出的,提供的类型参数<T>
是? extends DateSerial
. 该方法的片段obtainMetadata
如下所示:
此方法反射性地查找元数据对象访问器方法并调用它。调用的方法必须具有 Metadata.class 的返回类型。请注意,局部变量k
是通过强制转换分配给无界通配符类型的。此行不生成警告。
在这个方法结束时,我已经证明元数据对象与提供的Class<D>
参数具有相同的类型,因此我可以安全地转换为返回类型(警告被抑制,因为我已经证明它是安全的)。如果<D>
是? extends DateSerial
,我希望返回类型是,Optional<Metadata<? extends DateSerial>>
但它不是。由于我不清楚的原因,带有上述类型参数的返回类型是原始类型Optional
。
两个问题:
- 为什么强制转换为无界通配符类型会在 in
metadataForName()
而不是 in生成警告obtainMetadata()
? - 当 type 参数为时
obtainMetadata()
,? extends DateSerial
为什么该方法返回原始类型Optional
?
java - 如何指定无界通配符类型参数?
我无法为这个问题选择正确的词语。
我有一个类和一个工厂方法。
现在我想再添加两个工厂方法,每个方法只需要U
or V
。
那将是这样的。这意味着那些被忽略的V
,或者U
仍然是未设置的(null
)。
我试过这个但没有成功。
编译器抱怨以下消息。
没有为 of(java.lang.Class,U, <nulltype>) 找到合适的方法
正确的方法是什么?
java - 如何避免返回类型中的通配符
给定以下类型层次结构:
SomeProvider
应该公开可SpecializedClass
用于具体类型的列表Foo
。(为了简化这个例子,这里只给出了一个类型的具体内容Bar
。)
根据https://rules.sonarsource.com/java/RSPEC-1452
不应在返回参数中使用通用通配符类型
此片段被声纳标记为关键代码异味。
到目前为止,我无法在这里摆脱通配符。将 getter 方法更改为
将避免警告,但客户端会丢失该列表仅包含SpecializedClass
.
基本上我在这里有两个问题:
在这种情况下,这真的是一种糟糕的代码气味吗?在这里使用这个 getter 方法的客户可能会遇到什么陷阱?
在返回类型中不使用通配符的情况下,getter 应该是什么样子?
非常感谢您的帮助。
java - 在不丢失类型信息的情况下获取类 List 的类对象的正确方法是什么?
作为我的问题的前言,请注意我知道擦除类型是什么。我觉得有必要说明这个有用的答案,不要埋在基本的解释中。
我想获取类 List 的类对象。对于非泛型类型,我会使用像 String.class 这样的类文字,但对于 List,即使我可以获得正确的行为,我仍然会收到警告说我做错了。
据我了解, List 的类对象将是 type Class<List>
,但即使写下该类型,
给出警告:“参数化类 'List' 的原始使用”。由于类型擦除,类对象无法了解列表元素,所以我的下一个猜测是
作为一种类型被接受。接下来我必须获取类对象,但是尝试写下类文字的每一种方式都失败了:
给出一个硬类型错误,而
说“无法从参数化类型中选择”。
失败并出现与没有强制转换相同的硬类型错误(预期因为强制转换是多余的),并且
说“不可转换的类型”。
接下来,我尝试了以下无效代码片段以从编译器错误中了解一些信息:
现在编译器给出了一个类型错误Class<? extends java.util.List>
——暂时忽略“扩展”部分,这很明显,因为getClass()
可以返回一个子类,这告诉我.getClass()
只想谈论原始 List 类型,而不是List<?>
或类似的。在某种程度上,这对我来说似乎是正确的,因为类对象代表任何 List 实例,而不是“类型未知的列表”。但是,我现在又回到了原点,因为仅仅写下原始类型就会发出警告,所以我显然不应该这样做(我知道原始类型可用于处理遗留代码,但我在这里不这样做)。
我知道我可以像这样丢弃有关类对象的所有静态类型信息:
但这通常是不可行的,实际上我正在尝试解决需要该类型信息的更大问题。
虽然我知道我可以轻松禁用警告或使用类似的肮脏技巧,但我想知道获取 List 的类对象的正确方法是什么。
java - Java 中的泛型 - 通配符用例
当我们想要传递包含子类对象的列表时,我们在方法 args 中使用通配符。但如下所示,我们可以使用 Type 参数实现相同的功能。那么为什么我们需要通配符呢?
场景
假设我们有一个名为Department的基类及其名为Development & Sales的子类。Development & Sales 是 Department 的子类型,但 List 和 List 不是 List 的子类型。
因此,当我们想将 Development 或 Sales 对象列表作为方法 arg 传递时,该方法接受任何类型的部门列表,我们使用通配符。但是在代码中我们可以看到我们可以在不使用通配符的情况下实现相同的效果。
根据 Effective Java 在返回类型中使用通配符确实是一个糟糕的选择。通配符真正有用的其他用例是什么?
在 notWorkingMethods1 和 notWorkingMethods2 内部,为什么我们不能直接传递 Bounded Type 参数,但我们可以通过在返回类型之前先声明它来做到这一点?
java - #HyperSkill Type Erasure(JAVA) Violator 问题,为什么我的解决方案不起作用?
问题陈述:
您被要求在一家烘焙公司进行安全审计。他们的产品以 Bakery 类及其不同的子类(如 Cake 和 LemonTart)为代表。所有的糕点都装在漂亮的盒子里出售。在向客户发布之前,所有盒子都经过精心设计的 NaiveQualityControl 类检查。然而,最近发生了一些错误,无法食用的东西被装在盒子里,逃脱了质量检查。
对 NaiveQualityControl 的简短了解使您得出结论,为 NaiveQualityControl 提供装满纸的盒子非常容易,这将通过 QC。现在你的任务是证明这个错误。这是代码:
您需要将实现添加到 Violator.defraud() 方法,该方法将执行以下操作:
- 创建框列表<? 根据方法签名扩展 Bakery>
- 将 Paper 对象放入列表中的至少一个 Box 中
- 结果列表应通过 NaiveQualityControl 检查
我的解决方案:
我的解决方案正在运行,但我使用命中和试用方法想出了它,所以我不知道为什么会这样。Paper 类如何即使没有扩展 Bakery 类仍然设法添加到框列表中?
还有一个疑问,为什么这个解决方案不起作用?
错误:
java - Java:泛型,具有多个边界的通配符
首先祝大家新年快乐!我想编写一个具有多个边界参数的方法,如下所示:
但不幸的是,这段代码无法编译,有人可以向我解释为什么无法编写具有多个边界的通配符参数吗?
谢谢
java - 从通配符转换为特定的泛型参数化类型是 Java 中捕获转换的示例吗?
对于以下编译无误、无异常运行的代码:
上面的代码片段是在 Java 中工作的捕获转换的示例吗?
据 JLS 报道,
存在从参数化类型 G<T1,...,Tn> (§4.5) 到参数化类型 G<S1,...,Sn> 的捕获转换,其中,对于 1 ≤ i ≤ n :
- 如果 Ti 是 ? 形式的通配符类型参数(第 4.5.1 节),则 Si 是一个新类型变量,其上限为 Ui[A1:=S1,...,An:=Sn],下限为空类型(§4.1)。
我对上述语句的理解如下:如果通配符的形式为“?”,则只要“S”在Object的范围内(上限) ,就存在从 G<T> 到 G<S> 的捕获转换和空(下限)。
那么,例如在上面的代码片段中,将 'List<?>' 转换为 'List<Integer>' 将是一个捕获转换,它不会抛出任何运行时异常(这在 JLS 中也有说明)?那是对的吗?另外,说它不会由于类型擦除而引发运行时异常是否正确?
如果是这样,捕获转换不会破坏类型安全吗?根据 JLS,引入捕获转换是为了在不破坏类型系统的情况下使通配符更有用?
java - 将泛型 lambda 用于具有无界通配符类型的方法参数的 Java 编译错误
我目前正在使用一个库方法,该方法将具有通用通配符类型的功能接口作为方法参数(特别是在AssertJ库中)。我发现当我传递一个使用除通配符类型参数以外的任何类型的 lambda 方法参数时,我得到一个编译错误。例如,如果方法是,当我调用.RecursiveComparisonAssert.withEqualsForFields(BiPredicate<?,?> equals, String... fieldLocations)
Object
sameInstant(Instant i1, Instant i2)
withEqualsForFields(this::sameInstant, "someField")
简化示例
作为这种现象的一个更简单的示例,不需要使用任何特定的库来重现,请使用Predicate<?>
方法参数采取以下场景:
尝试将 lambda 传递给Predicate<String>
接受 a 的方法会Predicate<?>
导致编译错误:
但是,传递一个 lambdaPredicate<Object>
或显式转换 lambda 以Predicate<String>
成功。此外,如果将其传递给需要Predicate<T>
.
为什么这种 lambda 用法会导致编译错误?我在JLS中是否忽略了某些内容,表明这应该无法编译?