【问题标题】:Why is it safe to suppress this unchecked warning?为什么抑制这个未经检查的警告是安全的?
【发布时间】:2013-02-25 16:41:00
【问题描述】:

考虑在Effective Java泛型章节中定义的UnaryFunction 接口。

public interface UnaryFunction<T> {
T apply(T arg);
}

以及返回UnaryFunction的以下代码

// Generic singleton factory pattern
private static UnaryFunction<Object> IDENTITY_FUNCTION = new UnaryFunction<Object>() {
  public Object apply(Object arg) { return arg; }
};

// IDENTITY_FUNCTION is stateless and its type parameter is
// unbounded so it's safe to share one instance across all types.
@SuppressWarnings("unchecked")
public static <T> UnaryFunction<T> identityFunction() {
  return (UnaryFunction<T>) IDENTITY_FUNCTION;
}

为什么IDENTITY_FUNCTION(UnaryFunction&lt;T&gt;) 的演员表是安全的?

这本书对我提出的问题进行了说明,但我无法遵循这里的逻辑。我们在哪里调用进行身份操作的apply 函数?我很困惑,因为它是返回传递给它的相同对象而不修改任何东西的函数。

将 IDENTITY_FUNCTION 转换为 (UnaryFunction&lt;T&gt;) 会生成一个 未经检查的强制转换警告,因为 UnaryFunction&lt;Object&gt; 不是 UnaryFunction&lt;T&gt; 对应每个 T。但恒等函数很特殊:它 返回未修改的参数,因此我们知道使用它是类型安全的 无论T 的值如何,它都是UnaryFunction&lt;T&gt;。因此,我们可以 自信地抑制由生成的未经检查的强制转换警告 这个演员表。完成此操作后,代码编译不会出错或 警告。

【问题讨论】:

  • 附带问题:您在使用什么书,它是否说明了这段代码的意义?
  • @Jeff Effective java 是书名,它在泛型章节中,特别是在描述泛型函数的部分。

标签: java generics effective-java


【解决方案1】:

强制转换是安全的,因为标识函数返回了最初传递给它的 exact 对象。因此,在运行时,泛型参数 T 的特殊化不会违反强制转换。

也就是说,您正在将对象转换为自己的类型。

【讨论】:

    【解决方案2】:

    类型擦除

    T apply(T arg);
    

    其实是

    Object apply(Object arg);
    

    现在是身份

    Abc x = ...;
    Abc y = IDENTITY.apply(x);
    

    人们可能会认为它总是正确的(相当于y = x;)。

    (非常务实。)

    【讨论】:

    • 每当应用 identityFunction (.apply) 时,都会为结果分配 T IDENTITY.apply(T),这通常无法完成,因为参数的 T 在运行时不存在。
    【解决方案3】:

    identityFunction() 只返回函数本身,用于不同的对象。

    以下是一个使用示例:

    String result = identityFunction().apply("Hello");
    

    类型安全警告很重要。它存在是因为 IDENTITY_FUNCTION 的实现使得编译器无法保证函数返回与输入相同的类型。 考虑以下替代实现:

    private static UnaryFunction<Object> CONST_FUNCTION = new UnaryFunction<Object>() {
        public Object apply(Object arg) { return "Default"; } 
    };
    

    这个实现总是返回一个字符串,因此将它作为泛型数据类型的一元函数返回显然是不安全的。

    在我们的例子中(IDENTITY_FUNCTION),返回类型与输入类型相同的证明在实现内部。我们返回相同的实例,因此保证具有相同的类型。当您禁止显示类型安全警告时,建议使用证明来证明它的合理性。

    【讨论】:

    • -1 令人困惑。 IdentityFunction() 不返回“函数本身”,它返回 argument 本身。我看不出为什么这个 T 类型的结果是“用于不同的对象”。在您的示例中,它是一个字符串,cannot used 在不同的对象上。
    • @user949300: identityFunction() 返回对存储在变量IDENTITY_FUNCTION 中的对象的引用。该引用允许您调用apply(),因此identityFunction() 有效地返回函数本身。如果名字不一样就更好了。例如getIdentityFunction()IDENTITY_FUNCTION。答案的第一行是指getter方法。
    • 谢谢 - 明白了。对于什么都不做的事情来说,整个问题/系统非常令人困惑:-)。由于 StackOverflow 的限制,在您编辑答案之前,我无法“撤消”我的反对票。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-22
    • 2019-02-09
    • 1970-01-01
    • 2010-09-16
    • 2013-11-24
    相关资源
    最近更新 更多