2010-05-06 120 views
3

//遗留代码将java遗留代码转换为泛型 - 如何用类型替换Object?

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? 
} 

//这是我在清洁呼叫代码中实现的目标:

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

}

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

回答

3

这确实不可能。您需要以某种方式将“具体”T作为方法参数传递,以便在运行时知道实际类型。常用的方法是把它当作Class<T>,这样就可以利用Class#cast()

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

+1常见问题 - 标准方法 – leonbloy 2010-05-06 19:02:05

+0

很好。我发现类投射做了两件事:它抑制了编译警告,并且它在运行时检查了类型 - 尽管它可能为时已晚,但总比不检查更好。 (价格不得不通过一个额外的参数) – joejax 2010-05-06 19:34:02

0

地图泛型支持在地图上的所有值的类型:

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

您可以按如下方式使用它,对于特定的值而言不是一种不同类型。你可以看到如何伪造here。基本上这个想法是你必须在键上具有类型安全性,其中键有一个通用类型,只存在与值关联。

在一天结束时,如果没有不安全的演员,你将无法做到这一点,但是你可以这样做,使演员出现问题的可能性极小,对班级的用户是类型安全的。

+0

有趣的想法。请注意,servlet上下文的属性映射只接受String键。您需要在其中放置另一个地图并相应地使用它。 - – BalusC 2010-05-06 19:20:16

0

事实上,编译,太:

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"); 
    } 
} 

这是一种毫无意义的(也许如果你添加一个类型检测),但我觉得它很有趣知道。