【问题标题】:Solve "unchecked warning" in Java avoiding @suppressWarnings解决 Java 中的“未经检查的警告”,避免使用 @suppressWarnings
【发布时间】:2014-12-31 11:06:23
【问题描述】:

这是一个试图改进我的代码的问题。关于泛型和未经检查的警告;我确实知道@suppresswarnings 注释。问题是我应该编写什么代码来抑制它。请使用以下代码。

public class NumericBox<T extends Number> implements Box<T> {

    private T element;


    public NumericBox(T element) {
        this.element = element;
    }

    @Override public T getElement() {
        return element;
    }

    public T insert(Number newElement) {
        T oldElement = this.element;
        this.element = (T) newElement; // warning("unchecked")
        return oldElement;
    }
}

执行此操作的编码方式是什么(不是注释)。在我找到的文档中 术语“未检查”意味着编译器没有足够的类型信息来执行所有必需的类型检查以确保类型安全。但是,不要明白。这对我来说似乎没问题:

void foo(Number n) {
    Short asShort = (Short) n; //OK
    T  asTypeWhichExtendsNumber = (T) n; // warning
}

额外。如果我想添加一个空的构造函数,有什么方法可以在元素中保持“零”?

NumeircBox<Short> o = new NumericBox<>(); // expectes 0 in the element

【问题讨论】:

  • 为什么方法签名不是T insert(T newElement)
  • 想象一下,您真的想要一个仅用于 NumericBoxes 的方法,而不是每个框,并且该方法需要接收一个数字,而不是每个 T。也许我应该使用 compareTo() 更改为某些东西
  • 我为警告寻找了一个场景,试着想象你真的想要签名。如有必要,我会更改场景。

标签: java generics unchecked


【解决方案1】:

让我们看看有问题的代码,你的class 声明:

public class NumericBox<T extends Number> implements Box<T>

所以我们有一些类型 Textends Number。这可能是LongInteger 等。但有些特定在编译时定义类型。

现在你有了一个方法:

public T insert(Number newElement) {
    T oldElement = this.element;
    this.element = (T) newElement;
    return oldElement;
}

这需要任何类型的Number - 既不是specfic 也不是在编译时定义的,然后您将其强制转换为T这是一个等待发生的ClassCastException

final NumericBox<BigDecimal> box = new NumericBox<>();
box.insert(3);
final BigDecimal val = box.getElement();  <-- OOPS!

没有办法避免这个警告,因为编译器告诉你这个例子,你有一个未经检查的强制转换,在运行时可能会导致ClassCastException。编译器正在洗手那一行。

所以,要解决您的问题,请将代码更改为:

public T insert(T newElement) {
    T oldElement = this.element;
    this.element = (T) newElement;
    return oldElement;
}

由于泛型在编译时被删除,因此没有真正的任何方法来修复该 hack。如果要保证运行时类型安全,则需要更改签名。如果你想拿“任何旧的Number”,那么你将不得不处理后果。

【讨论】:

  • 喜欢你的回复。但是让我问两件事。那么是否可以使用 Number (我的类中我的泛型类型的超类)。其次,您的代码(OOPS 代码)对我有用,我尝试了两次(bigdecimal 和 short):S
  • @manutero,稍微误读了您的原始代码 - 更新了错误情况。不明白你的第一点回复Number
  • 查看异常。关于另一点。如果你有类 A 你如何在类中使用 S (超类)(例如在方法的签名中)。希望这是正确的问题:)
  • 您使用S inside class A - 它保证S 上可用的方法可用于任何T。在class 之外,您使用具体类型T。例如,查看Collection API 的用法。
【解决方案2】:

将“插入”方法声明为采用 T 类型的参数,而不是数字。现在调用者可以传递任何数字,而不仅仅是与您的类的 T 类型参数匹配的数字,如果类型不匹配,您将在运行时收到 ClassCastException。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-05
    • 1970-01-01
    相关资源
    最近更新 更多