java - 在 Java 中运行时调用不同类的最佳方法
问题描述
假设我们必须在运行时根据定义从不同的类中调用一个方法。例如,我们收到这样的 JSON:
{"calculator": "MyClass1", "parameter1": 1.0, "parameter2": 2.0, ... }
MyClass1 和更多类要么扩展一些基类,要么实现一些接口(只是为了能够在运行时枚举它们)。我们必须创建对象,将参数传递给对象并调用 calculate() 方法。
我可以想到两种方法来做到这一点:
switch(calculatorString) { case "MyClass1":calculator = new MyClass1(); ...
使用 Java 反射
第一种方法非常愚蠢,因为每次将新的计算器类添加到项目中时都必须更新代码。第二种方法稍好一些,但 IDE 无法捕获我们在创建对象和调用方法时犯的任何类型错误。
还有其他方法可以做到这一点(可能更好)?
解决方案
反射是在运行时创建对象的最佳方式,但它完全取决于用例。您还可以使用工厂设计模式进行对象创建。
使用反射API
try {
cls = Class.forName(className);
instance = cls.newInstance();
instance = BeanUtils.populateBean(properties, cls);
} catch (Exception e) {
e.printStackTrace();
}
BeanUtil 类
public static Object populateBean(Map<String, Object> propertyMap, Class<?> clazz) throws Exception {
PropertyUtilsBean bean = new PropertyUtilsBean();
Object obj = null;
try {
obj = clazz.newInstance();
for(Map.Entry<String, Object> entrySet: propertyMap.entrySet()) {
PropertyDescriptor descriptor = null;
try {
descriptor =
bean.getPropertyDescriptor(obj, entrySet.getKey());
if (descriptor == null) {
continue;
}
Method writeMethod = bean.getWriteMethod(descriptor);
writeMethod.invoke(obj, convert(descriptor.getPropertyType(), entrySet.getValue(), DATE_PATTERN));
} catch (IncompatibleConversion e) {
throw e;
} catch (Exception e) {
throw new Exception("Unable to parse");
}
}
}catch(Exception e) {
throw e;
}
return obj;
}
转换类
private static Object convert(Class<?> clzz, Object value, String datePattern) throws Exception {
if (clzz.isAssignableFrom(BigInteger.class)) {
if (value == null) {
return value;
}
if (value instanceof BigInteger) {
return value;
}
try {
return new BigInteger(value.toString());
} catch (Exception e) {
throw new IncompatibleConversion(e);
}
} else if (clzz.isAssignableFrom(BigDecimal.class)) {
if (value == null) {
return value;
}
if (value instanceof BigDecimal) {
return parseBigDecimal(value.toString(), DECIMAL_PRECISION);
}
try {
return parseBigDecimal(value.toString(), DECIMAL_PRECISION);
} catch (Exception e) {
throw new IncompatibleConversion(e);
}
} else if (clzz.isAssignableFrom(Integer.class)) {
if (value == null) {
return value;
}
if (value instanceof Integer) {
return value;
}
try {
return new Integer(value.toString());
} catch (Exception e) {
throw new IncompatibleConversion(e);
}
} else if (clzz.isAssignableFrom(Long.class)) {
if (value == null) {
return value;
}
if (value instanceof Long) {
return value;
}
try {
return new Long(value.toString());
} catch (Exception e) {
throw new IncompatibleConversion(e);
}
} else if (clzz.isAssignableFrom(String.class)) {
if (value == null) {
return value;
}
if (value instanceof String) {
return value;
}
try {
return value.toString();
} catch (Exception e) {
throw new IncompatibleConversion(e);
}
} else if (clzz.isAssignableFrom(Date.class)) {
if (value == null) {
return value;
}
if (value instanceof Date) {
return value;
}
if (datePattern == null) {
throw new Exception("date pattern cannot be null");
}
try {
SimpleDateFormat sdf = new SimpleDateFormat(datePattern);
return sdf.parse(value.toString());
} catch (Exception e) {
throw new IncompatibleConversion(e);
}
} else if (clzz.isAssignableFrom(Byte.class)) {
if (value == null) {
return value;
}
if (value instanceof Byte) {
return (value);
} else if (value instanceof Number) {
return new Byte(((Number) value).byteValue());
}
try {
return (new Byte(value.toString()));
} catch (Exception e) {
throw new IncompatibleConversion(e);
}
} else if (clzz.isAssignableFrom(Float.class)) {
if (value == null) {
return value;
}
if (value instanceof Float) {
return (value);
}
try {
return new Float(value.toString());
} catch (Exception e) {
throw new IncompatibleConversion(e);
}
} else if (clzz.isAssignableFrom(Double.class)) {
if (value == null) {
return value;
}
if (value instanceof Double) {
return (value);
}
try {
return new Double(value.toString());
} catch (Exception e) {
throw new IncompatibleConversion(e);
}
}
throw new Exception("Incompactible Conversion");
}
推荐阅读
- javascript - 如何在html中添加视频
- java - 使用资源文件夹从 Eclipse 部署 AWS Lambda 函数的问题
- r - 如何为两列的唯一值汇总行
- android - 在 Sqlite Database Android 中使用 in 关键字获取 Summation
- python - 如何通过私有代理 selenium 进行连接
- r - 根据累积总和和另一个组创建分组
- adfs - 在 ADFS 中,如何删除登录页面中的“Active Directory”选项
- javascript - 复选框结构,如果选择了单个子复选框,则应自动选择父复选框
- java - 使用 Maven、Gauge-Java 框架在不同配置上运行并行测试
- apache-spark - 如何使用结构化流的 writestream 写入具有重新分区的文件?