Java 创建用于复制不同对象的通用函数
因此,我有一个用例,需要复制Java 创建用于复制不同对象的通用函数,java,object,java-8,copy,Java,Object,Java 8,Copy,因此,我有一个用例,需要复制类es的对象(类可能因工厂中的输入类型而异) 这是我尝试做的一个例子 public interface DataUtil { // the main wrapper static Object copyObject(Object payload){ if(payload instanceof Human)) return copyEntry((Human) payload); if(paylo
类
es的对象
(类可能因工厂中的输入类型而异)
这是我尝试做的一个例子
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
}
}
如果你看一下copyObject
函数,它会按预期完成任务,但问题是返回类型。目前,为了使自身兼容,它返回一个对象
,但我更愿意返回它特定的类对象(例如人类
或汽车
)
有没有一种方法可以通过泛型(使用
)实现这一点?或者这是一种糟糕的方法吗?不幸的是,您必须执行一些未经检查的强制类型转换,例如:
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;
}
有没有一种方法可以通过泛型(使用)来实现这一点
一开始是一个糟糕的方法吗
这是一种不好的方法,因为您将一个对象作为参数接收
您无法从中推断具体类型:而您使用的是instanceof
。这不是一个好方法。
这里有两个想法(足够相关)
1)引入可复制界面
您可以引入一个接口,该接口由要复制的对象类实现:
public interface Copyable<T> {
T copy(T t);
}
2)使用访客模式
作为替代方案,它也是访问者模式的一个好例子:您希望根据参数的具体类型应用处理。
它允许按照实际代码将复制操作分组在一起
常规的copyObject()
方法可以依赖于将根据参数的具体类型进行复制的CopyVisitor
:
@SuppressWarnings("unchecked")
static <T extends Visited> T copyObject(T payload) {
CopyVisitor visitor = new CopyVisitor();
payload.accept(visitor);
return (T) visitor.getCopy();
}
这样:
Human human = new Human();
// set some fields ...
Human copiedHuman = copyObject(human); // compile
Car copiedCar = copyObject(human); // doesn't compile
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;
}
}
Human human = new Human();
// set some fields ...
Human copiedHuman = copyObject(human); // compile
Car copiedCar = copyObject(human); // doesn't compile
所访问的类(车、人、计划)将实现一个特定的接口来“接受”访问者:
public interface Visited {
void accept(Visitor visitor);
}
例如:
public class Human implements Copyable<Human> {
@Override
public Human copy(Human t) {
return Human.builder()
.name(human.getName())
.age(human.getAge())
.build();
}
}
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
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;
}
}
Human human = new Human();
// set some fields ...
Human copiedHuman = copyObject(human); // compile
Car copiedCar = copyObject(human); // doesn't compile
如果您了解对象中的类型,可以使用:
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的类型擦除不适用,您的语言也需要运行时知识,即“依赖类型”
<> p>因此,在某些语言中,如C++中返回的重载将不利于运行时类型的切换,如List< /C> > < /P>
但是,不管怎样,为什么需要这样做呢?调用后,您将再次在一个新的异构列表中收集所有对象实例复制构造函数如何?@MuratK.:我希望copy
发生在util
中,所以要避免这种方法!!在当前状态下不需要此类。只需提供一个复制构造函数并调用新人类(人类)
。实际问题是人类
/汽车
等是不在我控制范围内的代码库,它们不具备复制
常量
的功能,因此这一切都很混乱。这就是为什么我想把它包含在Util
中的原因:|您应该得到一个库来为您进行克隆,这样您就不必浪费时间编写(糟糕的)代码。它们也是完全通用的!不需要Copyable
,有UnaryOperator
这是对的,但是公共类人类实现可复制{…}
比公共类人类实现UnaryOperator{…}
更有意义,只要想想我多么不喜欢/理解访问者模式,这就太棒了!加一@尤金:好的。但是,我也更喜欢human.copy(human)
而不是human.apply(human)`出于同样的原因:可读性更强:)谢谢:)我对访问者模式也不感兴趣,但在某些情况下可能没那么糟糕:)回答得很好。但我觉得将复制结果存储在实例变量copy
中,然后调用getCopy()
似乎很奇怪。。。有什么想法吗?变量的编译时类型可以比实际实例更广泛,就像使用Object o=“foo”代码>,因此这与类型擦除无关,如果要对实际的对象类型而不是编译时声明作出反应,则无论如何都需要检查instanceof
。除此之外,您的通用签名承诺返回调用方希望返回的任何内容,而不管他们传入了什么,这当然是根本性的破坏。例如,它允许写入Number n=copyObject(“someString”)代码>..@Holger right。从答案中删除了类型擦除
Human h1 = new ...
Human h2= copyObject(h1);