我有一个错误创建的容器对象,它将不同java类型(字符串、布尔值等)的值保存在一起。
public class BadlyCreatedClass {
public Object get(String property) {
...;
}
};
我们以这种方式从其中提取值
String myStr = (String) badlyCreatedObj.get("abc");
Date myDate = (Date) badlyCreatedObj.get("def");
我不得不用这个对象写一些新的代码,我想看看有没有干净的方法来做到这一点。更具体地说,下面哪种方法是首选的?
显式转换
String myStr = (String) badlyCreatedObj.get("abc")
Date myDate = (Date) badlyCreatedObj.get("def");
使用通用cast的
public <X> X genericGet(String property) {
}
public String getString(String property) {
return genericGet(property);
}
public Date getDate(String property) {
return genericGet(property);
}
使用Class.cast的
<T> T get(String property, Class<T> cls) {
;
}
我已经在SO Java generic function: how to return Generic type上看了几个相关的问题,他们似乎都说这样的类型转换是危险的,ALthough我看不出三者之间有太大的区别,考虑到这一点,你更喜欢哪种方法?
谢谢
发布于 2013-04-20 17:18:59
为了给出一个快速的答案,而不是深入讨论良好的编程实践...
我将使用:
private <X> X genericGet(String property) {
}
public String getString(String property) {
//... checks on property (String specific)...
Object obj = genericGet(property);
//... checks if obj is what is expected and if good return it
return obj;
}
public Date getDate(String property) {
//... checks on property (Date specific)...
Object obj = genericGet(property);
//... checks if obj is what is expected and if good return it
return obj
}
向私有genericGet发出通知。这样,我就可以检查get属性是否是我等待接收的东西,并以正确的方式处理它。
我可以根据属性在getString依赖中添加检查,以确保答案将是String对象。
我可以对属性中的getDate做其他检查,以确保它将是将返回的日期。
等等。
发布于 2013-04-20 17:25:08
就我个人而言,将许多不同的对象放在一个地方,然后检查您想要返回的内容似乎有点错误。也许你可以将持有者存储在那个BadlyCreatedClass中。
类似于:
class Holder {
private long id;
private String name;
private Date dateofBirth;
//getters and setters
}
然后根据id进行检索,因此不需要强制转换。
你也可以告诉我们你想做什么。
发布于 2013-04-20 19:16:41
泛型强制转换方法会导致编译器发出未经检查的警告。未经检查的警告表明,在运行时没有(完全)检查强制转换,即,即使值不是正确的类型,它也可能成功。这可能导致变量保存的值与其声明的类型不兼容,这种情况被Java Language Specification称为heap pollution。
下面的程序演示了这一点:
class Holder {
Object value;
Holder(Object value) {
this.value = value;
}
<T> T get() {
return (T) value;
}
}
class C<T> {
T value;
C(Holder h) {
value = h.get();
}
}
public class Test {
public static void main(String [] args) throws IOException {
Holder holder = new Holder("Hello");
C<Integer> c = new C<Integer>(holder);
System.out.println("I just put a String into a variable of type Integer");
// much later, possibly in a different part of your program
c.value.longValue(); // throws ClassCastException
}
}
因此,我强烈建议使用检查类型转换。检查普通类型转换(第一种方法)和反射类型转换(第三种方法)。但是,反射强制转换不适用于参数化类型(List<String>.class
无法编译...)。
因此,最简单和最灵活的安全解决方案是普通的强制转换。
https://stackoverflow.com/questions/16118578
复制相似问题