以下代码来自一个名为ButterKnife的Android库。我正在弄清楚它是如何工作的。
@SuppressWarnings("unchecked") // That's the point.
public <T> T castParam(Object value, String from, int fromPosition, String to, int toPosition) {
try {
return (T) value;
} catch (ClassCastException e) {
throw new IllegalStateException("Parameter #"
+ (fromPosition + 1)
+ " of method '"
+ from
+ "' was of the wrong type for parameter #"
+ (toPosition + 1)
+ " of method '"
+ to
+ "'. See cause for more info.", e);
}
}
我试图重新创建此函数的行为:
@SuppressWarnings("unchecked")
public static <T> T cast(Object o){
try {
return (T) o;
} catch (ClassCastException e){
throw new AssertionError("Error");
}
}
和用法:
Object o = new String("test");
Double d = cast(o);
但是异常并非永远不会被捕获,它在调用该方法时会抛出该行。这是为什么?
另外,这究竟如何工作?该方法如何知道要转换为什么?
正如SJuan67解释的那样,您不能真正使用泛型类型的强制类型转换,因为Java编译器会
如果类型参数不受限制,则将通用类型中的所有类型参数替换为其边界或对象。因此,产生的字节码仅包含普通的类,接口和方法。
有关所有仿制药限制的更多信息,请参见此处。
因此,ButterKnife代码如下所示:
public Object castParam(Object paramObject, String paramString1, int paramInt1, String paramString2, int paramInt2)
{
return paramObject;
}
所以对你的问题:
问:但是并非永远不会捕获异常,在调用该方法时,它会抛出异常。这是为什么?
答:嗯,甚至没有在字节码中。
问:此外,这是如何工作的?该方法如何知道要转换为什么?
答:不是。至少不像您想的那样。在实践中,它将抛出ClassCastException,而不是您观察到的IllegalStateException或AssertionError。您甚至可以使用ButterKnife示例应用程序尝试将其绑定到CheckBox并将其与TextView绑定:
@Bind(R.id.title) CheckBox title;
问:图书馆如何工作?
答:好吧,永远不会调用IllegalStateException,并且您有ClassCastException。我不确定为什么会这样。但是,当ButterKnife生成代码时,这可能是为了防止编译错误。
例如:
public interface Some {
}
public static void weWantSome(Some d) {
}
public static void test() {
String o = "test";
weWantSome((Some)o); //<-- compile error
weWantSome(Main.<Some>cast(o)); //<-- runtime error
}
这就是为什么在前面的示例代码中编译但无法运行的原因。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句