Java中能否将类类型存入变量以复用逻辑消除重复代码?
问题说明
- 业务场景需要实现多个逻辑完全一致的
getData()方法,仅返回类型分别为无公共父类、不可修改的存量类ClassX、ClassY、ClassZ - 初始实现为每个类型单独编写对应类,存在大量重复代码:
public class ClassA { String tableName = "T1"; public ClassX getData () { ClassX cls = fetchFromDB(tableName); return cls; } } public class ClassB { String tableName = "T2"; public ClassY getData () { ClassY cls = fetchFromDB(tableName); return cls; } } public class ClassC { String tableName = "T3"; public ClassZ getData () { ClassZ cls = fetchFromDB(tableName); return cls; } }
- 最初的优化思路是定义通用父类,将类类型存储为变量复用逻辑,但不清楚Java中类类型变量的定义方式,也不确定方案可行性,思路代码如下:
public class Root { ClassType classType = null; String tableName = null; public classType getData () { classType cls = fetchFromDB(tableName); return cls; } } public class ClassA extends Root { String tableName = "T1"; ClassType classType = ClassX; } public class ClassB extends Root { String tableName = "T2"; ClassType classType = ClassY; } public class ClassC extends Root { String tableName = "T3"; ClassType classType = ClassZ; }
- 预期调用方式:
ClassX cls = new ClassA().getData(); ClassY cls = new ClassB().getData(); ClassZ cls = new ClassC().getData();
- 核心疑问:Java是否支持将类类型存储到变量实现上述逻辑?如果不支持,有什么方案可以消除重复代码?
解决方案
你设想的直接用类类型变量充当方法返回值的写法在Java中不成立——Java是静态强类型语言,方法返回值必须在编译期确定类型,不能把变量名直接当类型声明使用。但可以通过泛型完全实现你要的复用效果,不需要重复编写getData()逻辑。
泛型通用父类实现
定义泛型基类,通过构造方法传入表名和目标类型,把通用逻辑全部收敛到父类:
public class DataFetcher<T> { private final String tableName; private final Class<T> targetType; public DataFetcher(String tableName, Class<T> targetType) { this.tableName = tableName; this.targetType = targetType; } public T getData() { return fetchFromDB(tableName, targetType); } private T fetchFromDB(String tableName, Class<T> targetType) { // 在这里实现原有数据库查询、结果映射为目标类型的逻辑即可 } }
子类只需要指定泛型类型、通过构造方法传入对应参数,不需要重写任何业务逻辑:
public class ClassA extends DataFetcher<ClassX> { public ClassA() { super("T1", ClassX.class); } } public class ClassB extends DataFetcher<ClassY> { public ClassB() { super("T2", ClassY.class); } } public class ClassC extends DataFetcher<ClassZ> { public ClassC() { super("T3", ClassZ.class); } }
调用方式和你预期完全一致,编译期自动做类型检查,不需要手动强转:
ClassX x = new ClassA().getData(); ClassY y = new ClassB().getData(); ClassZ z = new ClassC().getData();
注意事项
- 不要用子类重声明同名字段的方式赋值:Java字段不存在多态重写特性,子类声明和父类同名的字段只会隐藏父类字段,父类方法读取到的永远是父类字段的初始null值,会触发空指针,通过构造方法传参是最稳妥的实现方式。
- 如果原有
fetchFromDB方法返回值是Object,只需要在方法内部完成类型转换即可,由于传入的targetType和泛型T绑定,不会出现类型转换异常。 - 如果不需要单独定义ClassA/ClassB/ClassC三个类,可以直接在使用时实例化泛型基类,代码更简洁:
DataFetcher<ClassX> xFetcher = new DataFetcher<>("T1", ClassX.class); ClassX x = xFetcher.getData();
内容的提问来源于stack exchange,提问作者user2125853
相关产品推荐
相关产品推荐

