【问题标题】:Convert java legacy code to generic - how to replace Object with type?将 Java 遗留代码转换为泛型 - 如何用类型替换 Object?
【发布时间】:2010-05-06 18:51:06
【问题描述】:

// 遗留代码

void setCacheValue(String name, Object value){
    getServletContext().setAttribute(name, value);
}
Object getCacheValue(String name){
    return getServletContext().getAttribute(name);
}

// 所以我想为“类型安全”使用泛型

// first, set method seems working perfectly
<T> void setCacheObject(String name, T value){
    getServletContext().setAttribute(name, value);
}

//那么麻烦来了

<T> T getCacheValue(String name){    
    // of course, I cannot change servlet class - it returns Object type
    Object value = getServletContext().getAttribute(name);
    // would this work:     
    return  (T) value;
    // this cast is meaningless... but how should I do it?
}

// 这就是我在 clean 调用代码中要实现的目标:

{
    double x = 1.2;
    setCacheValue("x", x);
    //...
    // later
    Double value = getCacheValue("x");
    // too bad cannot use primitive type - it cannot handle null

}

那么,这样做的正确方法是什么?

【问题讨论】:

    标签: java generics legacy type-safety


    【解决方案1】:

    这确实是不可能的。您需要以某种方式将“具体”T 作为方法参数传递,以便在运行时知道实际类型。常用的方法是将其传递为Class&lt;T&gt;,以便您可以使用Class#cast()

    <T> T getCacheValue(String name, Class<T> type) {
        return type.cast(getServletContext().getAttribute(name));
    }
    

    你可以按如下方式使用它:

    Double value = getCacheValue("x", Double.class);
    

    【讨论】:

    • 太棒了。我发现类转换有两件事:它抑制编译警告,并在运行时检查类型——虽然可能为时已晚,但总比不检查好。 (代价是必须传递一个额外的参数)
    【解决方案2】:

    映射泛型支持映射所有值的类型,而不是特定值的不同类型。你可以看看如何伪造它here。基本上这个想法是你必须在键上具有类型安全性,其中键上有一个泛型类型,它的存在只是为了与值相关联。

    归根结底,如果没有不安全的演员表,你将无法做到这一点,但你可以通过一种极不可能出现演员表问题的方式来做到这一点。对您班级的用户来说类型安全。

    【讨论】:

    • 有趣的想法。只注意servlet上下文的属性映射只接受String键。您需要在其中放置另一个 Map 并相应地使用它。 ——
    【解决方案3】:

    其实也可以编译:

    public class Test
    {
        <T> T getCacheValue(String name){    
            // of course, I cannot change servlet class - it returns Object type
            Object value = getServletContext().getAttribute(name);
            // would this work:     
            return  (T) value;
            // this cast is meaningless... but how should I do it?
        }
    
        public static void main(String... args)
        {
            Test t = new Test();
            Double double = t.<Double>getCacheValue("Double");
        }
    }
    

    这有点无意义(也许如果你添加一个类型检查),但我发现它很有趣。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多