我真的很想尝试仿制药,但到目前为止,他们造成的麻烦超过了任何好处。拜托,请告诉我,我错了。
我理解在使用无通用框架(Spring,Hibernate)时添加@SuppressWarnings(“unchecked”)的必要性。仅这一点确实降低了泛型的价值,因为要求将类传递给构造函数以避免擦除的缺陷。然而,真正的刺似乎总是在铸造。我通常会尝试一段时间来使语法正确,但随后放弃我对纯度的尝试,添加@SuppressWarnings,继续我的生活。
这是一个例子:我正在反思一个bean来寻找两个实例之间的差异。一些属性实现Comparable,使得(a.equals(b)== false)但是(a.compareTo(b)== 0)(例如BigDecimal,Date)。在这些情况下,我希望该属性被认为是相同的。
MyObject original = getOriginal();
MyObject updated = getUpdated();
for (PropertyDescriptor pd : BeanUtils.getPropertyDescriptors(MyObject.class)) {
// Assume I'm putting in the try/catch block
Object pOriginal = pd.getReadMethod().invoke(original, (Object[]) null);
Object pUpdated = pd.getReadMethod().invoke(updated, (Object[]) null);
boolean isPropertySame;
if (Comparable.class.isAssignableFrom(pOriginal.getClass())) {
// Type safety: The method compareTo(Object) belongs to the raw type Comparable. References to generic type Comparable<T> should be parameterized
isPropertySame = Comparable.class.cast(pOriginal).compareTo(Comparable.class.cast(pUpdated)) == 0;
// The method compareTo(capture#19-of ?) in the type Comparable<capture#19-of ?> is not applicable for the arguments (capture#21-of ? extends Comparable)
Comparable<?> comparable = Comparable.class.cast(pOriginal);
isPropertySame = comparable.compareTo(comparable.getClass().getTypeParameters()[0].getGenericDeclaration().cast(pUpdated)) == 0;
// Even if I get the generics right, I still get an error if pOriginal is java.sql.Timestamp and pUpdated is java.util.Date (happens all the time with Hibernate).
isPropertySame = (help);
} else {
isPropertySame = pOriginal.equals(pUpdated);
}
if (!isPropertySame) {
PropertyDelta delta = new PropertyDelta(pd, pOriginal, pUpdated);
dao.save(delta);
}
}
关于我可以投入的任何想法(帮助)?
答案 0 :(得分:4)
这让我觉得这很难走。你可以让你的bean实现可比性,在这种情况下你只是直接比较它们,或者你创建一个比较器 -
public class Bean implements Comparable<Bean> {...}
public int compareTo(Bean other){ ... }
}
或
public int compare(Bean a, Bean b){
Comparator<Bean> c = new Comparator<Bean>(){
public int compareTo(Bean a, Bean b){ ... }
public boolean equals(Object o){.. }
};
return c.compare(a, b);
}
我同意你的观点,java泛型可以得到一点点,呃......令人费解。
答案 1 :(得分:2)
我只是简单地执行以下操作,我不太明白这是什么问题:
MyObject original = getOriginal();
MyObject updated = getUpdated();
for (PropertyDescriptor pd : BeanUtils.getPropertyDescriptors(MyObject.class)) {
// Assume I'm putting in the try/catch block
Object pOriginal = pd.getReadMethod().invoke(original, (Object[]) null);
Object pUpdated = pd.getReadMethod().invoke(updated, (Object[]) null);
boolean isPropertySame;
if (pOriginal instanceof Comparable) {
@SuppressWarnings("unchecked")
Comparable<Object> originalValue = (Comparable<Object>) pOriginal;
@SuppressWarnings("unchecked")
Comparable<Object> updatedValue = (Comparable<Object>) pUpdated;
isPropertySame = originalValue.compareTo(updatedValue) == 0;
} else {
isPropertySame = pOriginal.equals(pUpdated);
}
if (!isPropertySame) {
PropertyDelta delta = new PropertyDelta(pd, pOriginal, pUpdated);
dao.save(delta);
}
}
在你的案例中使用Class.cast
对类型安全没有任何帮助。
答案 2 :(得分:1)
看起来假设如果一个类实现Comparable
,那么type参数就是类本身。也就是说,“class X implements Comparable<X>
”。如果是这种情况,那么说,
X a = new X(1), b = new X(2);
a.compareTo(b);
但是,绝对可以定义类似“class X implements Comparable<Y>
”的类。然后人们可以尝试这样的事情......
X a = new X(1), b = new X(2);
a.compareTo((Y) b);
...但显然会引发ClassCastException
,因为b
不是Y
的实例。
所以,警告是有效的。使用原始类型的代码不是类型安全的,并且可能在运行时引发异常。
答案 3 :(得分:0)
好吧,鉴于我无法找到一种“纯粹”的方法来做到这一点,而且我一直遇到角落的情况(比如,除此之外,处理属性集合的难度) ,我决定让我的delta生成方法方式 dumber。我意识到我只测试了9种不同类型的对象,所以我可以测试我正在比较的9个对象中的哪一个,然后转换为该对象并进行特定于对象的测试。
以这种方式实现大约花了一个小时,即使每次任何对象都发生变化我都要重新编译,我觉得即使我花了几天时间进行维护,我仍然处于黑色状态。
所以,最后,我想答案是没有答案。 Java泛型以这样的方式实现,即不可能避免偶尔抑制编译器警告并冒险运行时类转换异常。