. Общее приведение к выполнению тестовых входных данных для метода. - PullRequest
0 голосов
/ 22 мая 2018

Мне нужна помощь в приведении строки к различным типам переменных с использованием универсального.Я пытаюсь сделать что-то, чтобы помочь начинающим программистам учиться, давая им класс с неправильной реализацией методов или просто со скелетом (только метод не называет ничего другого) и заставляя их это исправить, а затем проверяя класс и каждый метод на соответствиекласс рубрики с теми же методами.В тестовой рубрике входные данные для каждого метода представлены в виде комментариев, но я не могу найти способ приведения входных данных из строк в нужные типы.Я могу получить нужные типы, используя 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();
        }
    }

Iизвиняюсь за то, как тяжело читать мой код, если вам нужно знать, что я пытаюсь сделать где-то, просто попросите, чтобы я попытался разобраться.И Console.log - это то, что я использую для печати материала на консоль, которую я сделал как часть визуальных эффектов.

1 Ответ

0 голосов
/ 24 мая 2018

То, что вы пытаетесь сделать с 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);
    }
}

Для получения дополнительной информации см. Здесь: Парсинг объектов из строки в 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();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...