如何在Java中克隆类树并创建新继承类家族以同步运行时值?
看起来你是想基于现有的A、B继承类(A是父类,B继承A且带大量字段),搞一套对应的C、D继承体系,让D在运行时和B拥有完全一样的内容值,而且因为字段太多,不想手动复制一堆重复代码对吧?我给你几个实用的解决方案,按需选择:
先明确场景(补全你给出的代码示例)
假设原有继承结构是这样的:
package server.api.analytics; public class A { protected String param1; protected String param2; protected String param3; // 一堆getter/setter public String getParam1() { return param1; } public void setParam1(String param1) { this.param1 = param1; } public String getParam2() { return param2; } public void setParam2(String param2) { this.param2 = param2; } public String getParam3() { return param3; } public void setParam3(String param3) { this.param3 = param3; } } public class B extends A { protected String param4; protected String param5; // 更多字段+对应的getter/setter public String getParam4() { return param4; } public void setParam4(String param4) { this.param4 = param4; } // ...其他字段的方法 }
方案1:组合+委托+工具类复制(推荐,低耦合)
如果不需要D必须是A/B的子类,这种方式最灵活,不用重复定义所有字段:
package server.api.analytics; public class C { // 用组合的方式复用A的所有逻辑 private A aDelegate = new A(); // 把A的getter/setter委托给这个实例 public String getParam1() { return aDelegate.getParam1(); } public void setParam1(String param1) { aDelegate.setParam1(param1); } public String getParam2() { return aDelegate.getParam2(); } public void setParam2(String param2) { aDelegate.setParam2(param2); } public String getParam3() { return aDelegate.getParam3(); } public void setParam3(String param3) { aDelegate.setParam3(param3); } // 要是C需要自己的字段,直接加就行 } public class D extends C { // 同样组合B的实例,复用B的所有内容(包括继承A的部分) private B bDelegate = new B(); // 委托B新增的字段方法 public String getParam4() { return bDelegate.getParam4(); } public void setParam4(String param4) { bDelegate.setParam4(param4); } // ...其他B独有的字段方法 // 覆盖C里的A委托方法,确保用B的实例(因为B包含A的所有字段) @Override public String getParam1() { return bDelegate.getParam1(); } @Override public void setParam1(String param1) { bDelegate.setParam1(param1); } @Override public String getParam2() { return bDelegate.getParam2(); } @Override public void setParam2(String param2) { bDelegate.setParam2(param2); } @Override public String getParam3() { return bDelegate.getParam3(); } @Override public void setParam3(String param3) { bDelegate.setParam3(param3); } // 快速同步内容的方法,用工具类省得手动写一堆setter public void syncFromB(B source) { // Spring的BeanUtils,或者Apache Commons的都可以 org.springframework.beans.BeanUtils.copyProperties(source, this.bDelegate); } public void syncToB(B target) { org.springframework.beans.BeanUtils.copyProperties(this.bDelegate, target); } }
为啥推荐这个?
- 不用手动敲几十上百个字段和方法,直接复用原有类的逻辑
- 避免继承带来的紧耦合,原有类改了,只要接口不变,C/D基本不用动
- 工具类一键复制属性,省超多时间
方案2:直接继承原有类(简单粗暴,适合需要类型兼容的场景)
如果必须让C是A的子类、D是B的子类(比如需要D instanceof A这种类型判断),直接继承就行:
package server.api.analytics.newfamily; // C继承A,自动拿到所有字段和方法 public class C extends server.api.analytics.A { // 要加自定义逻辑就加,不用重复写原有字段 } // D继承B,自动拿到A+B的所有内容 public class D extends server.api.analytics.B { // 同样可以加自定义逻辑 }
然后同步内容超简单:
// 把B的内容复制到D B originalB = new B(); originalB.setParam1("value1"); originalB.setParam4("value4"); D newD = new D(); org.springframework.beans.BeanUtils.copyProperties(originalB, newD); // 这时候newD的所有字段值和originalB完全一致
注意事项
- 这种方式和原有类强绑定,原有类改字段或者方法,C/D会直接受影响
- 但胜在简单,要是只是需要一套“镜像”继承体系,这个最快
方案3:用Lombok减少重复代码(如果项目允许用工具库)
要是你项目里用Lombok,那简直是福音,不用手动写一堆getter/setter:
先给原有类加Lombok注解:
package server.api.analytics; @Data // 自动生成getter/setter、equals、hashCode等 public class A { protected String param1; protected String param2; protected String param3; } @Data @SuperBuilder // 支持子类继承父类的构建器 public class B extends A { protected String param4; protected String param5; }
然后新的C/D家族:
package server.api.analytics.newfamily; @Data public class C { // 复制A的字段,或者用组合的方式都行 protected String param1; protected String param2; protected String param3; } @Data @SuperBuilder public class D extends C { protected String param4; protected String param5; }
同步内容的话,要么用BeanUtils一键复制,要么用构建器:
B originalB = B.builder().param1("v1").param4("v4").build(); // 用构建器手动复制(字段少的时候用) D newD = D.builder() .param1(originalB.getParam1()) .param2(originalB.getParam2()) .param4(originalB.getParam4()) .build(); // 字段多就用BeanUtils BeanUtils.copyProperties(originalB, newD);
优点
- 代码量骤减,不用写一堆重复的getter/setter
@SuperBuilder构建实例的时候能直接继承父类的属性,超方便
最后总结一下
- 不需要类型兼容选方案1,灵活还低耦合
- 必须要继承关系选方案2,简单直接
- 项目用Lombok选方案3,省超多代码量
内容的提问来源于stack exchange,提问作者VitalyT
相关产品推荐
相关产品推荐

