【问题标题】:.Generic casting to do test inputs for a Method.Generic casts 为方法做测试输入
【发布时间】:2018-05-25 01:17:51
【问题描述】:

我需要帮助使用泛型将字符串转换为不同的变量类型。我要做的是帮助初学者编码人员学习,方法是给他们一个方法实现不正确或只有骨架的类(只有方法名称没有别的)并让他们修复它,然后针对该类和每个方法进行测试具有相同方法的量规类。在 rubric 类中,每种方法的测试输入都以 cmets 形式给出,但我找不到将输入从字符串转换为所需类型的方法。我可以通过使用Method.getGenericParameterTypes() 并设置一个与其相等的泛型来获得所需的类型,但是当我尝试使用它进行转换时它不起作用...... 这是我的代码:

    name = className.substring(0,className.indexOf("Copy"))+"Rubric";
    String param = ReadWrite.readData("src/"+name+".java").get(methLoc);
    Type B = meth.getGenericReturnType();
    Type E;
    Type [] params = meth.getGenericParameterTypes();
    String [] para = param.substring(param.indexOf("(")+1,param.indexOf(")")).split(",");
    @SuppressWarnings("rawtypes")
    Class myClass = null;
    Object obj = null;
    classNamer();
    try {
        myClass = Class.forName(name);
        obj = myClass.newInstance();
    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    if (params.length != para.length) {
        Console.log("Rubric test parameters are wrong");
    }
    else if (obj==null){
        Console.log("Error instantiating objects");
    }
    else {
        Object [] parames = new Object [params.length];
        for (int i =0; i<para.length; i++) {
            E = params[i];
            parames[i] = ((E)para[i]);
            System.out.println(params[i] + " " + para[i] + " " + parames[i] + " " + parames[i].getClass() + " " + E);
        }
        try {
            B rtrn = (B) meth.invoke(obj, parames);

            B rtrn2 = (B) testMethods[testNum].invoke(obj, parames);

            if (rtrn.equals(rtrn2)) {
                count++;
            }
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

对于我的代码难以阅读,我深表歉意,如果您需要知道我在任何地方尝试做什么,请询问我尝试清除它。 而Console.log 是我用来将东西打印到我作为视觉效果的一部分制作的控制台的东西。

【问题讨论】:

  • 如果我理解正确,您是在尝试将字符串转换为任意类型的对象吗?输入字符串及其预期类型有哪些示例?
  • 是的,这就是我想要做的,例如将“(1,1)”转换为两个整数或值为 1 的整数。

标签: java generics methods casting


【解决方案1】:

你试图用Type E 做的事情是不可能的,你不能在一个方法中创建一个泛型类型变量并转换为它。更重要的是,转换不会将一个对象转换为另一个不同类型的对象,它只是告诉编译器假设该对象已经是您要转换的类型。在运行时,如果对象不是真正的那种类型,你会得到一个 ClassCastException 抛出。

你需要做的是将字符串解析成各种类型的对象,使对象的运行时类型与方法参数相匹配。编译时类型只能是Object,因为Method.invoke 无论如何都将它们视为Object[]

public static Object parseParam(String str, Type type) {
    if (type.equals(String.class)) {
        return str.replaceAll("^\"(.+)\"$", "$1"); // assumes strings are quoted
    } else if (type.equals(int.class) || type.equals(Integer.class)) {
        return Integer.parseInt(str);
//  } else if (type.equals(...)) {
//      return ... // implement more as needed
    } else {
        throw new RuntimeException("Class not supported: " + type);
    }
}

请参阅此处了解更多信息:Parsing Objects from String in Java(请注意,接受的答案不适用于没有 String 构造函数的类)。您可能需要考虑将值存储为测试类中的字段,或者将它们序列化,或者使用某种测试框架。一旦你实现了这个,这样的事情应该可以工作:

name = className.substring(0, className.indexOf("Copy")) + "Rubric";
String input = ReadWrite.readData("src/" + name + ".java").get(methLoc);
Type[] params = meth.getGenericParameterTypes();
String[] para = input.substring(input.indexOf("(") + 1, input.indexOf(")")).split(",");
Class<?> myClass = null;
Object obj = null;
classNamer();
try {
    myClass = Class.forName(name);
    obj = myClass.newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

if (params.length != para.length) {
    Console.log("Rubric test parameters are wrong");
} else if (obj == null) {
    Console.log("Error instantiating objects");
} else {
    Object[] parames = new Object[params.length];
    for (int i = 0; i < para.length; i++) {
        parames[i] = parseParam(para[i], params[i]); // convert string to object
        System.out.println(params[i] + " " + para[i] + " " + parames[i] + " " + parames[i].getClass());
    }
    try {
        Object rtrn = meth.invoke(obj, parames);

        Object rtrn2 = testMethods[testNum].invoke(obj, parames);

        if (rtrn.equals(rtrn2)) {
            count++;
        }
    } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-18
    • 2019-06-08
    • 1970-01-01
    • 2014-01-01
    • 1970-01-01
    • 2012-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多