java动态模型转换
我是Baeldung博客的忠实粉丝。 他的最新文章之一是有关Java的转换。 不幸的是,我觉得它错过了一个重要点:动态转换。 由于那是(非常) 相对较新的,因此本文将尽力填补这一空白。
不要使用投射
第一件事是避免铸造应该相对容易。
使用多态
多态是不强制转换的好方法。 考虑以下代码:
Listanimals=newArrayList();
animals.add(newCat());
animals.add(newDog());
for(Animalanimal:animals){
if(animalinstanceofCat){
((Cat)animal).mew();
}elseif(animalinstanceofDog){
((Dog)animal).bark();
}elseif(animalinstanceofSnake){
((Snake)animal).hiss();
}
}
如果集合中的所有对象类型都继承自单个类型,则可以使用多态。 只需在此单一类型中添加一个方法并在子类型中覆盖它即可。
publicabstractclassAnimal{
publicabstractvoidmakeSound();
}
publicclassDog{
@OverridepublicvoidmakeSound(){
bark();
}
}
publicclassCat{
@OverridepublicvoidmakeSound(){
mew();
}
}
使用泛型
多态不能总是应用。 例如,在以下情况下就是这种情况:
- 项目不是相关类型的实例
- 父类型不在我们的控制范围内
- 等等
在这些情况下,泛型是避免强制转换的另一种方法。
在Java 5之前,以下代码将成为规范:
Listdates=newArrayList();
dates.add(newDate());
Objectobject=dates.get(0);
Datedate=(Date)object; (1)
- 需要投放。 尽管运行时类型为
Date
,但编译器无法了解它。
使用泛型,可以重写以上代码:
List<Date>dates=newArrayList<>();
dates.add(newDate());
Datedate=dates.get(0); (1)
- 无需强制转换:由于泛型,编译器具有足够的信息。
强制转换时
尽管有一些狂热者认为,但有时铸件不容忽视。
这样的用例之一就是Servlet API。 Servlet上下文/请求/会话中的映射存储对象不使用泛型 。 即使这样做,他们也会使用Object
。
// In a servlet
ServletContextcontext=getServletContext();
context.put("date",newDate());
// Somewhere else
ServletContextcontext=getServletContext();
Objectobject=context.get("date");
Datedate=(Date)object;
动态铸造
最初可用的唯一铸造形式是静态铸造。 这意味着在编译时需要知道转换类型。 例如,让我们想象一个方法,该方法接受Stream<Object>
,过滤特定类型的所有元素并以正确的类型返回这些元素。 这是用法示例:
List<?>items=...
List<Date>dates=filter(Date.class,items);
无法通过静态转换来实现filter方法。 实际上有两个问题:
-
instanceof
运算符需要类型,而不是Class
实例, 例如item instanceof Date
- 强制转换语法, 例如
(Date) item
可以用对Class.isInstance(Object)
的调用来替换instanceof
运算符(自JDK 1.1开始)。 如果没有广泛使用,这是众所周知的。
但是,用于替换强制转换语法的API更为“最新”。 自JDK 1.5起就有一个Class.cast(Object)
方法。它是围绕旧语法的简单包装。
使用这两种方法,最终可以实现上面的filter
方法。
static<T>List<T>filter(Class<T>clazz,List<?>items){
returnitems.stream()
.filter(clazz::isInstance)
.map(clazz::cast)
.collect(Collectors.toList());
}
使用强制转换API允许动态强制转换。 没有它,就不可能实现上述方法。
结论
尽管生态系统之外的许多人都认为Java是进化的,即使不是很快。 但是,开发人员需要熟悉每个版本提供的新功能。
java动态模型转换