浏览一些代码我遇到了以下代码
trTuDocPackTypdBd.update(TrTuDocPackTypeDto.class.cast(packDto));
我想知道这种方式铸造是否有任何优势
trTuDocPackTypdBd.update((TrTuDocPackTypeDto)packDto);
我已经询问了负责的开发人员,他说他使用它是因为它是新的(这对我来说似乎不是一个特别好的理由),但是当我想要使用该方法时我很感兴趣。
这些陈述并不相同。cast 方法是一种普通的方法调用(invokevirtual
JVM 指令),而另一个是一种语言构造(checkcast
指令)。在上面显示的情况下,您应该使用第二种形式:(TrTuDocPackTypeDto) packDto
cast
当您有某个变量类型的 Class 实例时,该方法用于使用泛型进行反射式编程。你可以像这样使用它:
public <T> Set<T> find(Class<T> clz, Filter criteria) {
List<?> raw = session.find(clz, criteria); /* A legacy, un-generic API. */
Set<T> safe = new HashSet<T>();
for (Object o : raw)
safe.add(clz.cast(o));
return safe;
}
这为您提供了一种安全的方法来避免将原始类型简单地转换为泛型类型的错误选择:
/* DO NOT DO THIS! */
List raw = new ArrayList();
...
return (List<Widget>) raw;
编译器会警告您,Unchecked cast from List to List<Widget>
,这意味着在省略号中,有人可能已将 a 添加Gadget
到原始列表中,这最终将导致 aClassCastException
当调用者迭代返回的(假定的)Widget
实例列表时。
这样做的主要情况(IME)是当您需要安全地转换为通用类/方法时。由于类型擦除,您无法转换为,T
但如果您已获得Class<? extends T>
参数,则可以使用该参数进行转换,结果将可分配给 type 的变量T
。
我找不到一个可以使用 cast 方法而不能使用 cast 语法的示例。但是,查看代码,似乎在无法进行强制转换的情况下,强制转换方法会抛出没有附加类型信息的 ClassCastException,而强制转换语法会给您一些提示(例如,“无法将 Snoopy 强制转换为 TyrannosorusRex ") :
/**
* Casts an object to the class or interface represented
* by this <tt>Class</tt> object.
*
* @param obj the object to be cast
* @return the object after casting, or null if obj is null
*
* @throws ClassCastException if the object is not
* null and is not assignable to the type T.
*
* @since 1.5
*/
public T cast(Object obj) {
if (obj != null && !isInstance(obj))
throw new ClassCastException();
return (T) obj;
}
用第一种形式
trTuDocPackTypdBd.update(TrTuDocPackTypeDto.class.cast(packDto));
你可以这样做:
public void dynamicCast( Class clazz, Object o ) {
this.x = clazz.cast( o );
}
用第二个你不能。铸造类应该是硬编码的。
为什么要首先使用变量进行转换?那是另一个问题。:) 首先想到的是,您不知道(在编译时)将被转换为的类。
这两个陈述是相同的。选择您认为更具可读性的那个。第二种方法在我的经验中更常见,也是我更喜欢的一次。
我倾向于仅在使用反射时才使用 cast 方法,并且在这种情况下读起来更好。在所有其他时间,我发现自己使用的是第二种投射方式。