gpt4 book ai didi

java - 如何避免接口(interface)的通用编译器警告

转载 作者:行者123 更新时间:2023-11-29 03:33:21 24 4
gpt4 key购买 nike

这可能以前曾以某种形式被问过,但我仍然无法解决,所以我想我会在这里询问集体智慧。我有一个这样的界面 - 我留下了一些评论,因为它们可能会有帮助。

/** Technical note: this generic binding is known as F-bound where class
* T is 'the worked-on class' by Splittable i.e. the implementing class.
*/
interface Splittable <T extends Element & Splittable<T>> {


/** Returns an object of the same class which has been split off at
* the point given.
*/
public T splitOff(double at);


/** Appends the object provided, which must be of the same class, to
* this object.
*/
public void append(T el);
}

然后我正在处理一个我在编译时不知道的元素:

if (el instanceof Splittable) {
if (nextEl.getClass == el.getClass) {
// same class so join them
((Splittable)el).append(nextEl);
}
}

这就是我收到编译器警告的地方 - 未经检查的对作为原始类型 Splittable 成员的 append(T) 的调用。

在 Element 子类中我都试过了

SubClassEl extends Element implements Splittable

SubClassEl extends Element implements Splittable<SubClassEl>

警告没有区别。

此外,在调用 append() 时,我尝试了

((Splittable)el).splitOff(x).append(nextElement)

但编译器无法识别 splitOff 应该返回一个 Splittable,而只返回一个元素。

有什么想法吗?

最佳答案

这里发生的事情是您正在使用原始类型,它“选择退出”通用类型检查。当发生这种情况时,Terased元素。来自 The Java Tutorials :

When a multiple bound is used, the first type mentioned in the bound is used as the erasure of the type variable.

至于如何让您的代码在没有警告的情况下编译,您当前的设计可能无法实现。使用 instanceof 和强制转换在纯 Element 上工作不会与在 Splittable 上声明的递归绑定(bind)类型参数很好地混合。

避免原始类型,我能得到的最接近的是:

static <T extends Element & Splittable<T>> void maybeAppend(T el1, Element el2) {
if (el1.getClass() == el2.getClass()) {
@SuppressWarnings("unchecked") // arguments' runtime types are equal
final T el2WithNarrowedType = (T)el2;
el1.append(el2WithNarrowedType);
}
}

...

if (el instanceof Splittable<?>) {
maybeAppend(el, nextEl); //compiler error
}

这仍然无法编译,因为没有类型参数就无法表达 el 既是 Element 又是 Splittable它自己的类型。

我在这里回答了类似的问题:Passing a runtime resolved parameter to a method which has multiple bound type, compilation error .我能想出的最接近的不使用原始类型的解决方案是一个主要的 hack,并且只适用于某些编译器。 OP 最终使用了原始类型。

我对你的建议是避免 self 打字并考虑实现这样的东西:

interface ElementSplitter<T extends Element> {

T splitOff(T element, double at);

void append(T element, T appendedElement);
}

如果实现的 splitOffappend 功能需要访问给定 Element 派生的私有(private)成员,解决方法是将其设为嵌套类,例如:

class SubClassEl extends Element {

...

static class Splitter implements ElementSplitter<SubClassEl> {
...
}
}

我在 Splittable javadoc 中注意到你写的:

Technical note: this generic binding is known as F-bound where class T is 'the worked-on class' by Splittable i.e. the implementing class.

您应该知道 Java 不支持真正的自类型化 - 您所拥有的是一个递归绑定(bind)的类型参数,应该是,但不一定是自类型。看我的回答here有关此模式及其陷阱的更多详细信息。

关于java - 如何避免接口(interface)的通用编译器警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16834286/

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