2014-11-17 5 views
1

Я пытаюсь написать java-программу, в которую пользователь входит в testclass, а затем мою программу убедитесь, что это testclass. То есть, проверяя конструктор без параметра и проверяя методы, чтобы они работали (возвращаем true или false).Ошибка отражения API

Теперь я смущен, это отражение API. Я пытаюсь следовать учебнику, расположенному по адресу https://docs.oracle.com/javase/tutorial/reflect/index.html, но я смущаюсь, и мне интересно, может ли кто-нибудь объяснить это и, может быть, помочь мне начать. В учебнике сказано, например, как получить testclass, но вы можете сделать это по-разному. Я пробовал использовать

... 
Class c = str.getClass(); 
... 

где str - это название класса, на котором я хочу посмотреть. Как я могу перейти отсюда, чтобы получить информацию о методах, конструкторе и их параметрах класса? Я просто хочу примеров и объяснений. Не полностью написанная программа. Заранее спасибо.

+1

str.getClass() вернет класс String, который вы хотите Class. \t forName (str); – Tom

ответ

0

Получение класс

Class.forName(str) возвращает класс с заданным именем. Вы должны передать полное имя, например «org.example.MyTestSuite». В других случаях, когда вы хотите создать другой экземпляр данного объекта, вы можете просто позвонить Object#getClass().

Конструкторов и Инстанцирование

Вы можете получить весь конструктор с Class#getConstructors(), так что вы можете проверить, если в нульарном конструкторе (без параметров) доступны. Class#newInstance() попытается создать экземпляр с помощью конструктора с нулевым значением и выбросить исключение IllegalAccessException, если оно не доступно. Конструкторы с параметрами могут быть вызваны с помощью Constructor#newInstance(Object...).

Методы

Класс, методы будут перечислены Class#getDeclaredMethods(). Для дальнейшего изучения Method#getGenericParameterTypes() возвращает классы параметров. Вы можете даже сделать частные методы invokable, используя Method#setAccessible(true). Затем, наконец, Method#invoke(Class) выполняет метод для данного экземпляра класса. Используйте методыдля методов с аргументами, тогда как var-args представляет аргументы.

Пример

Документационный Java содержит некоторую good examples, я изменил один немного для случая использования:

try { 
    // retrieving class 
    Class<?> c = Class.forName(str); 

    // will throw IllegalAccessException if the class 
    // or its nullary constructor is not accessible: 
    Object t = c.newInstance(); 

    Method[] allMethods = c.getDeclaredMethods(); 
    for (Method m : allMethods) { 
     String mname = m.getName(); 

     // run only test methods 
     if (!mname.startsWith("test")) { 
      continue; 
     } 

     Type[] pType = m.getGenericParameterTypes(); 
     if (pType.length != 0) { 
      throw new RuntimeException("Test methods must not have parameters."); 
     } 

     try { 
      // you can call private methods by setting this flag 
      m.setAccessible(true); 

      // invoking method m of instance t 
      m.invoke(t); 

     } catch (InvocationTargetException x) { 
      // Handle any exceptions thrown by method to be invoked. 
      Throwable cause = x.getCause(); 
      err.format("invocation of %s failed: %s%n", 
       mname, cause.getMessage()); 
     } 
    } 

    // production code should handle these exceptions more gracefully 
} catch (ClassNotFoundException x) { 
    x.printStackTrace(); 
} catch (InstantiationException x) { 
    x.printStackTrace(); 
} catch (IllegalAccessException x) { 
    x.printStackTrace(); 
} 
+0

Как мне сделать, если я не хочу вместо «Обработать любые исключения, вызванные методом, который вызывается», и вместо этого он будет печатать, что метод завершился неудачно и распечатать исключение? – Fjodor

+0

@Fjodor: вам нужно распечатать его в блоке catch, и пример точно распечатает метод и исключение. Вы можете добавить стек, который вы хотите. То, что происходит в блоке catch, не имеет никакого отношения к размышлению. –

+0

Хорошо, спасибо. И если в классе есть метод, который я хочу вызвать каждый раз, с именем «привет» (он не должен существовать). Могу ли я каким-то образом сохранить этот метод в переменной, чтобы этот метод существовал, я вызываю его каждый раз перед другим методом? – Fjodor

0

Вы можете просто вызвать соответствующие методы из класса класса, найденного Here. А именно, getDeclaredFields() и getDeclaredMethods()

1

Во-первых, с помощью Class c = str.getClass(); не будет делать то, что вы хотите. Он вернет класс объекта str, который равен String. Вместо этого вы должны использовать Class.forName(str); обратите внимание, что для этого потребуется полное имя класса.

Как только у вас есть объект класса, вы можете использовать его методы для получения соответствующей информации. Похоже, что наиболее полезным для вас будет .getConstructors().При этом вы можете использовать (например) метод .getParameterCount() для Constructor s для поиска любых конструкторов, которые не принимают никаких параметров. Для получения дополнительной информации я советую посмотреть на the documentation.

Смежные вопросы