所以我有一个用例,其中我需要复制 4.2
个object
es(类可能因工厂中的输入类型而异。
这是我要做的事的一个示例
class
如果您查看public interface DataUtil {
// the main wrapper
static Object copyObject(Object payload){
if(payload instanceof Human))
return copyEntry((Human) payload);
if(payload instanceof Car))
return copyEntry((Car) payload);
if(payload instanceof Planet))
return copyEntry((Planet) payload);
return payload;
}
static Human copyEntry(Human human) {
return Human.builder()
.name(human.getName())
.age(human.getAge())
.build();
}
static Car copyEntry(Car car) {
return Car.builder()
.model(car.getModel())
.brand(car.getBrand())
.build();
}
static Planet copyEntry(Planet planet) {
// return builder like previous
}
}
函数,它会按预期完成工作,但是他发出的是返回类型。目前,要使其自身 compatible ,它返回一个copyObject
,但我宁愿返回它的特定类Object(例如Object
或Human
)
有没有一种方法可以通过泛型(使用Car
)来完成?还是这首先是一个不好的方法?
答案 0 :(得分:6)
有没有一种方法可以使用泛型完成此操作(使用)?还是这个 首先要采取不好的做法吗?
这是一种不好的方法,因为您会收到Object
作为参数。
您无法从该类型推断出具体的类型:而您使用的instanceof
。这不是一个好方法。
这里有两个想法(足够相关)
1)引入可复制界面
您可以引入一个接口,您要复制的对象的类可以实现该接口:
public interface Copyable<T> {
T copy(T t);
}
可以实现的:
public class Human implements Copyable<Human> {
@Override
public Human copy(Human t) {
return Human.builder()
.name(human.getName())
.age(human.getAge())
.build();
}
}
所以一般的copy()方法看起来像:
// the main wrapper
static <T extends Copyable<T>> T copyObject(T payload) {
return payload.copy(payload);
}
您可以通过这种方式使用它:
Human human = new Human();
// set some fields ...
Human copiedHuman = copyObject(human); // compile
Car copiedCar = copyObject(human); // doesn't compile
2)使用访问者模式
作为替代方案,这也是访问者模式的一个很好的例子:您要根据参数的具体类型进行处理。
它允许将复制操作分组到您的实际代码中。
一般的copyObject()
方法可以依靠CopyVisitor
来根据参数的具体类型进行复制:
@SuppressWarnings("unchecked")
static <T extends Visited> T copyObject(T payload) {
CopyVisitor visitor = new CopyVisitor();
payload.accept(visitor);
return (T) visitor.getCopy();
}
CopyVisitor
实现经典的Visitor
接口的地方:
public interface Visitor {
void visitHuman(Human human);
void visitCar(Car car);
void visitPlanet(Planet planet);
}
以这种方式:
public class CopyVisitor implements Visitor {
private Visited copy;
@Override
public void visitHuman(Human human) {
copy = Human.builder()
.name(human.getName())
.age(human.getAge())
.build();
}
@Override
public void visitCar(Car car) {
copy = Car.builder()
.model(car.getModel())
.brand(car.getBrand())
.build();
}
@Override
public void visitPlanet(Planet planet) {
//...
}
public Visited getCopy() {
return copy;
}
}
被访问的类(汽车,人,计划)将实现一个特定的接口来“接受”访问者:
public interface Visited {
void accept(Visitor visitor);
}
例如:
public class Human implements Visited {
@Override
public void accept(Visitor visitor) {
visitor.visitHuman(this);
}
}
因此,您可以通过以下方式使用copy()
方法:
Human human = new Human();
// set some fields ...
Human copiedHuman = copyObject(human); // compile
Car copiedCar = copyObject(human); // doesn't compile
答案 1 :(得分:1)
不幸的是,您必须执行一些未经检查的强制转换,例如:
static <TPayload> TPayload copyObject(Object payload) {
if (payload instanceof Human)
return (TPayload) copyEntry((Human) payload);
if (payload instanceof Car)
return (TPayload) copyEntry((Car) payload);
if (payload instanceof Planet)
return (TPayload) copyEntry((Planet) payload);
return (TPayload) payload;
}
但是正如评论中所提到的,这并不妨碍您写作:
Number n = DataUtil.copyObject("someString");
答案 2 :(得分:0)
如果您了解Object中的类型,则可以使用:
/settings
然后:
static <T> T copyObject(Object payload)
{
if (payload instanceof Human)
{
return (T) copyEntry((Human) payload);
}
if (payload instanceof Car)
{
return (T) copyEntry((Car) payload);
}
if (payload instanceof Planet)
{
return (T) copyEntry((Planet) payload);
}
return (T) payload;
};
即使Java的Type Erasure不适用,您也需要语言的运行时知识才能做到这一点,也就是“依赖类型”。
因此,在某些语言(例如C ++)中发现的返回类型重载对Human h1 = new ...
Human h2= copyObject(h1);
这样的运行时类型切换没有帮助。
但是为什么仍然需要这样做,您将在调用之后再次将所有对象实例收集到新的异构列表中