如何在Java中为两个同类型对象实现一个通用Setter方法?
解决通用Setter方法的几种Java 8+实现思路
嘿,这个面试场景挺有代表性的!我来给你分享几个实用的实现方案,都是Java 8及以上版本兼容的,帮你搞定这个通用Setter的瓶颈:
方案1:新增参数明确指定目标对象(最直观易读)
如果面试允许修改方法参数,这是最直接的方案——加一个标识参数,明确告诉方法要设置obj1还是obj2。比如用枚举来避免魔法值,可读性拉满:
// 定义枚举来标识目标对象 public enum TargetInstance { OBJ1, OBJ2 } public class Test { private MyClass obj1 = new MyClass(); private MyClass obj2 = new MyClass(); public void setGenericMyClass(IMyClass myClass, TargetInstance target) { // 先做类型校验,避免ClassCastException if (!(myClass instanceof MyClass)) { throw new IllegalArgumentException("传入的实例必须是MyClass类型"); } MyClass targetInstance = (MyClass) myClass; // 根据标识设置对应对象 switch(target) { case OBJ1: this.obj1 = targetInstance; break; case OBJ2: this.obj2 = targetInstance; break; default: throw new IllegalArgumentException("无效的目标对象标识"); } } }
这个方案的优点是逻辑清晰,维护成本低,面试官一眼就能看懂你的思路。
方案2:利用Java 8函数式接口(体现现代Java特性)
如果想展示你对Java 8新特性的掌握,这个方案会很加分。通过传入Consumer函数式接口,把"设置对象"的动作传递给方法,完全不需要硬编码判断:
public class Test { private MyClass obj1 = new MyClass(); private MyClass obj2 = new MyClass(); public void setGenericMyClass(IMyClass myClass, Consumer<MyClass> setterAction) { // 类型校验不能少 if (!(myClass instanceof MyClass)) { throw new IllegalArgumentException("传入的实例必须是MyClass类型"); } // 执行传入的设置动作 setterAction.accept((MyClass) myClass); } // 调用示例: // 方式1:用方法引用(如果给obj1/obj2加了Setter) // test.setGenericMyClass(new MyClass(), this::setObj1); // 方式2:直接用Lambda表达式 // test.setGenericMyClass(new MyClass(), mc -> this.obj1 = mc); // 可选:给obj1/obj2添加标准Setter(推荐,符合封装原则) public void setObj1(MyClass obj1) { this.obj1 = obj1; } public void setObj2(MyClass obj2) { this.obj2 = obj2; } }
这个方案的优势在于扩展性极强——以后如果新增obj3,完全不需要修改setGenericMyClass方法,只需要传对应的Lambda或方法引用就行,完美契合开闭原则。面试时写这个,能体现你对函数式编程思想的理解。
方案3:基于业务规则自动匹配(适用于有区分标识的场景)
如果obj1和obj2在业务上有明确的区分规则(比如对应不同的业务类型、属性值),可以通过判断传入实例的特征自动匹配目标对象:
public class Test { private MyClass obj1 = new MyClass(); // 比如对应"用户类型A" private MyClass obj2 = new MyClass(); // 对应"用户类型B" public void setGenericMyClass(IMyClass myClass) { if (!(myClass instanceof MyClass)) { throw new IllegalArgumentException("传入的实例必须是MyClass类型"); } MyClass mc = (MyClass) myClass; // 根据业务属性判断要设置的对象 if ("TYPE_A".equals(mc.getBizType())) { // 假设MyClass有getBizType()方法 this.obj1 = mc; } else if ("TYPE_B".equals(mc.getBizType())) { this.obj2 = mc; } else { throw new IllegalArgumentException("无法匹配对应的目标对象"); } } }
这个方案适合有明确业务逻辑支撑的场景,但前提是obj1和obj2有可被程序识别的区分特征。
面试小建议
如果面试时允许沟通,最好先确认几个关键点:是否允许修改方法参数?obj1和obj2有没有业务上的区分规则?如果没有限制,优先选方案2,既能展示Java 8特性,又能体现良好的编码设计思想。
内容的提问来源于stack exchange,提问作者mindOf_L
相关产品推荐
相关产品推荐

