1. 使用反射实现泛型方法
import java.lang.reflect.Method;
public class GenericMath {
public static <T> T performOperation(T a, T b) {
if (a instanceof Integer && b instanceof Integer) {
Integer result = ((Integer) a) + ((Integer) b);
return (T) result;
} else if (a instanceof Long && b instanceof Long) {
Long result = ((Long) a) + ((Long) b);
return (T) result;
} else if (a instanceof Float && b instanceof Float) {
Float result = ((Float) a) + ((Float) b);
return (T) result;
} else if (a instanceof Double && b instanceof Double) {
Double result = ((Double) a) + ((Double) b);
return (T) result;
} else {
try {
Class<?> aClass = a.getClass();
Method method = aClass.getMethod("doubleValue");
double valueA = (double) method.invoke(a);
double valueB = (double) method.invoke(b);
double result = valueA + valueB;
if (aClass == Integer.class) {
return (T) (Integer) (int) result;
} else if (aClass == Long.class) {
return (T) (Long) (long) result;
} else if (aClass == Float.class) {
return (T) (Float) (float) result;
} else if (aClass == Double.class) {
return (T) (Double) result;
}
} catch (Exception e) {
throw new IllegalArgumentException("Unsupported types for addition", e);
}
}
return null;
}
}
2. 泛型场景下基本数据类型转换规则面临的挑战
- 类型擦除:Java泛型在编译时会进行类型擦除,运行时无法获取确切的泛型类型参数,这使得直接根据泛型类型进行特定类型操作变得困难。
- 自动装箱拆箱:对于基本数据类型,在泛型中需要进行装箱(转换为包装类)和拆箱(从包装类转换回基本类型)操作。这不仅增加了性能开销,还可能导致空指针异常,比如对
null
值的包装类进行拆箱。
- 精度丢失:在进行不同数值类型运算时,如从
double
转换为 float
,long
转换为 int
等,可能会发生精度丢失。
3. 解决方案
- 显式类型检查:在方法内部通过
instanceof
关键字对传入参数的实际类型进行检查,然后根据不同类型进行相应的操作,如上述代码中对 Integer
、Long
、Float
和 Double
的分别处理。
- 反射机制:当无法通过
instanceof
覆盖所有可能的数值类型时,可以使用反射获取对象的方法(如 doubleValue
),将其转换为通用的 double
类型进行运算,最后再根据原始类型进行转换回合适的类型。
- 使用
Number
类:所有数值类型的包装类都继承自 Number
类。可以利用 Number
类的方法,如 doubleValue
、intValue
等,将不同数值类型统一转换为一种类型进行运算,然后再根据需要转换回合适的类型。这可以减少重复代码并处理多种数值类型。