使用Java中的List进行动态转换

时间:2017-01-18 23:44:29

标签: java list casting

我的API中的一个方法,不将Java.lang.Object类型作为参数,但它将所有子类型作为参数(java.lang.Integer,java.lang.String)等)。

现在,我想通过执行以下操作将DataType存储在列表中:

List<Object> listObjects = new ArrayList<Object>();
if(listObjects.get(0) instanceof Integer){
//then do
listDataTypesForCast.add(Integer);
}

所以,我可以这样投:

  

myMethod((listDataTypesForCast.get(0)&#34;返回Java.lang.Object数据类型&#34;))

但是,我不知道如何声明我的 List:listDataTypesForCast ,以便我可以将它用于Casting。如果你知道答案,请告诉我?

PS:我使用Apache POI库和setCellValue()方法,不能将java.lang.Object作为参数中的DataType,我当时无法检查DataType在单元格中插入值,因为它在一个循环中,它将添加太多的锅炉板代码。

2 个答案:

答案 0 :(得分:1)

如果要调用单参数方法的多个重载之一,但在运行时之前不知道参数类型,则可以使用反射来完成。

这是一个帮助方法:

private static void call(Object obj, String methodName, Object arg) {
    Class<?> argClass = arg.getClass();

    // Try simple approach
    Method methodToCall;
    try {
        methodToCall = obj.getClass().getMethod(methodName, argClass);
    } catch (@SuppressWarnings("unused") NoSuchMethodException unused) {
        methodToCall = null;
    }

    // Search for method, if simple approach didn't work
    if (methodToCall == null) {
        List<Method> candidates = new ArrayList<>();
        for (Method method : obj.getClass().getMethods()) { // Note: Public methods only
            if (method.getParameterCount() == 1 && method.getName().equals(methodName)) {
                Parameter parameter = method.getParameters()[0];
                if (parameter.getType().isAssignableFrom(argClass))
                    candidates.add(method);
            }
        }
        if (candidates.isEmpty()) {
            throw new NoSuchMethodError(obj.getClass().getName() + '.' +
                                        methodName + '(' + argClass.getName() + ')');
        }
        if (candidates.size() > 1) {
            // Implement extended overload resolution logic, if needed
            throw new NoSuchMethodError("Multiple candidates found for parameter type " +
                                        argClass.getName() + ": " + candidates);
        }
        methodToCall = candidates.get(0);
    }

    // Call method
    try {
        methodToCall.invoke(obj, arg);
    } catch (IllegalAccessException e) {
        throw new IllegalAccessError(e.getMessage());
    } catch (InvocationTargetException e) {
        throw new RuntimeException("Checked exception: " + e.getCause(), e);
    }
}

测试

public static void main(String[] args) {
    Test obj = new Test();
    for (Object arg : Arrays.asList("Foo", 42, 42L, 42f, 42d))
        call(obj, "myMethod", arg);
}

public void myMethod(String s) {
    System.out.println("String: " + s);
}
public void myMethod(Number s) {
    System.out.println("Number: " + s);
}
public void myMethod(Long s) {
    System.out.println("Long: " + s);
}

输出

String: Foo
Number: 42
Long: 42
Number: 42.0
Number: 42.0

答案 1 :(得分:0)

然而,我的问题可以使用Reflection解决(正如Andreas所建议的那样)但是,在这种特殊情况下,我决定不广泛使用反射,因为我有很多数据要写入excel单元格,因此,我使用了以下方法:

  1. 使用instanceof查找每个数据(类型为Object)的数据类型,对于第一行单元格,然后将结果保存到Enum。因为其余行在列之间共享相同的数据类型。

  2. 现在,循环遍历枚举并设置单元格值和数据类型。

  3. 我相信instaceof也在内部使用反射,但我只需要使用一次。