Идентификация типа во время выполнения RTTI
Механизм состоит из нескольких частей: Базовые средства RTTI лежат в основе механизма полиморфизма. При первом доступе к некоторому классу из программы, создается объект класса Class для данного класса. Механизмы определения типов (классов) объектов во время выполнения. Простейший из этих механизмов, операция instanceof. Наиболее сложным механизмом RTTI является рефлексия. Это набор средств, позволяющих получить полную информацию о классе, такую как список полей, конструкторов, методов и т.д. Полученная информация может быть использована для создания объектов этого класса, вызова его методов.
Базовые средства RTTI class Base {... int f();... } Его наследники классы: Derived1, Derived2, Derived3 ArrayList list; Далее в программе... Iterator iter = list.iterator(); while ( iter.hasNext() ) { ( (Base)iter.next()).f(); }
Объекты класса Class java.lang.Class Способы получить объект Class для какого-либо класса: При помощи статического метода класса Class public static Class forName(String className) throws ClassNotFoundException При помощи синтаксической конструкции, называемой литералы объектов класса Class. При помощи метода getClass класса Objeсt.
Литералы объектов класса Class Синтаксис:.class Например: ArrayList.class, int.class, Integer.TYPE
Определение типа объекта в программе 1 способ Issue[] catalog = new Issue[] { new Journal("Play Boy"), new Newspaper("Спид-Инфо"), new Book("Война и мир", "Л.Толстой"), }; for(int i = 0; i < catalog.length; i++) { if (catalog[i] instanceof Book ) ((Book) catalog[i]).printAuthors(System.out); catalog[i].printName(System.out); }
Определение типа объекта в программе 2 способ for(int i = 0; i < catalog.length; i++) { if(catalog[i].getClass () == Book.class) ((Book) catalog[i]).printAuthors(System.out); catalog[i].printName(System.out); } 3 способ for(int i = 0; i < catalog.length; i++) { if (Book.class.isInstance(catalog[i]) ) ((Book) catalog[i]).printAuthors(System.out); catalog[i].printName(System.out); }
Создание объектов с помощью метода newInstance public Object newInstance() throws InstantiationException, IllegalAccessException
public class NewInstanceDemo extends JFrame { private JTextField fid = new JTextField(30); private JTextArea msg = new JTextArea(8, 40); NewInstanceDemo() { super(Создание объектов"); try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch(Exception e) { } setSize(500, 250); Container с = getContentPane(); JPanel pn = new JPanel(); c.add(pn, BorderLayout.NORTH); pn.add(new Label("Имя класса")); pn.add(fid); fid.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { createObject(); } }); JScrollPane pane = new JScrollPane(msg); с.add(pane, BorderLayout.CENTER); WindowListener wndCloser = new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }; addWindowListener(wndCloser) ; setVisible(true ) ; }
void createObject() { String className = fid.getText(); try { Class els = Class.forName(className); Object obj = els.newInstance(); msg.append("Создан объект класса "+className+":\n"); msg.append(obj.toString()+"\n") ; } catch (Exception ex) { msg.append("Ошибка при создании объекта класса "+className+":\n"); msg.append(ex.toString ()+"\n") ; } public static void main(String args[]) { new NewInstanceDemo(); } }
Рефлексия
Reflection Пакеты java.lang.Class и java.lang.reflect Получение информации о методах, полях классов, динамическое создание объектов и классов
Основные возможности рефлексии Определить тип объекта Получить данные о методах, полях, конструкторах, родительском типе, модификаторах Выделить методы и константы интерфейса Создать объекты заранее неизвестного типа Получить,установить значения полей Вызвать метод Создать массив объектов неизвестного типа, изменять значения элементов
Методы класса Class getConstructors - возвращает массив объектов класса java.lang.reflect.Constructor, по одному объекту для каждого конструктора класса. getMethods - аналогичный массив объектов класса java. lang.reflect.Method, по одному - для каждого метода класса. getDeclaredConstructors и getDeclaredMethods – возвращают информацию по методам или конструкторам вне зависимости от их спецификаторов доступа
Методы класса Class getFields и getDeclaredFields - информация о полях класса getClasses и getDeclaringClass – информация о суперклассах данного класса getInterfaces - информация о реализуемых данным классом интерфейсах
java.lang.reflect класс Method – по объекту этого класса можно получить информацию о методе: имя (метод getName), тип возвращаемого значения (метод getReturnType) или список параметров (метод getParameterTypes ). Вызвать этот метод при помощи метода invoke
void reflectlnfo() { String className = fid.getText(); try { Class els = Class.forName(className); Method[] m = els.getMethods(); int lastLine = msg.getLineCount()-1; if ( lastLine >= 0 ) msg.replaceRange("", 0, msg.getLineEndOffset(lastLine) ); msg.append("Методы класса "+className+":\n"); for(int i = 0; i < m.length; i++) msg.append(m[i].toString()+"\n"); } catch (Exception ex) { msg.append("Ошибка при поиске класса "+className+":\n"); msg.append(ex.toString()+"\n") ; }
class SampleMethod { public static void main(String[] args) { Object p = new Object(); showMethods(p); } static void showMethods(Object o) { Class c = o.getClass(); Method[] theMethods = c.getMethods(); for (int i = 0; i < theMethods.length; i++) { String methodString = theMethods[i].getName(); System.out.println("Name: " + methodString); String returnString = theMethods[i].getReturnType().getName(); System.out.println(" Return Type: " + returnString); Class[] parameterTypes = theMethods[i].getParameterTypes(); System.out.print(" Parameter Types:"); for (int k = 0; k < parameterTypes.length; k ++) { String parameterString = parameterTypes[k].getName(); System.out.print(" " + parameterString); } System.out.println(); } } } Name: hashCode Return Type: int Parameter Types: Name: getClass Return Type: java.lang.Class Parameter Types: Name: wait Return Type: void Parameter Types: long int Name: wait Return Type: void Parameter Types: Name: wait Return Type: void Parameter Types: long Name: equals Return Type: boolean Parameter Types: java.lang.Object Name: toString Return Type: java.lang.String Parameter Types: Name: notify Return Type: void Parameter Types: Name: notifyAll Return Type: void Parameter Types:
import java.lang.reflect.*; class SampleInvoke { public static void main(String[] args) { String firstWord = "Hello "; String secondWord = "everybody."; String bothWords = append(firstWord, secondWord); System.out.println(bothWords); } public static String append(String firstWord, String secondWord) { String result = null; Class c = String.class; Class[] parameterTypes = new Class[] {String.class}; Method concatMethod; try { concatMethod = c.getMethod("concat", parameterTypes); result = (String) concatMethod.invoke(firstWord, secondWord); } catch (NoSuchMethodException e) { } catch (IllegalAccessException e) { } catch (InvocationTargetException e) { } return result; }} Выполнение методов Hello everybody.
class SampleConstructor { public static void main(String[] args) { Rectangle r = new Rectangle(); showConstructors(r); } static void showConstructors(Object o) { Class c = o.getClass(); Constructor[] theConstructors = c.getConstructors(); for (int i = 0; i < theConstructors.length; i++) { System.out.print("( "); Class[] parameterTypes = theConstructors[i].getParameterTypes(); for (int k = 0; k < parameterTypes.length; k ++) { String parameterString = parameterTypes[k].getName(); System.out.print(parameterString + " "); } System.out.println(")"); } }} ( java.awt.Point java.awt.Dimension ) ( ) ( java.awt.Rectangle ) ( int int int int ) ( int int ) ( java.awt.Point ) ( java.awt.Dimension )
class A { public int i, j; { i = 55; j = 66;} } class SampleGet { public static void main(String[] args) { A r = new A(); Class c = r.getClass(); Field f; Integer value; f = c.getField("i"); f.set(r, new Integer(99)); value = (Integer) f.get(r); System.out.println("I: " + value.toString()); } I: 99 Класс Field
class SampleField { public static void main(String[] args) { Button g = new Button("aaaaa"); printFieldNames(g); } static void printFieldNames(Object o) { Class c = o.getClass(); Field[] publicFields = c.getFields(); for (int i = 0; i < publicFields.length; i++) { String fieldName = publicFields[i].getName(); Class typeClass = publicFields[i].getType(); String fieldType = typeClass.getName(); System.out.println("Name: " + fieldName + ", Type: " + fieldType); } Name: TOP_ALIGNMENT, Type: float Name: CENTER_ALIGNMENT, Type: float Name: BOTTOM_ALIGNMENT, Type: float Name: LEFT_ALIGNMENT, Type: float Name: RIGHT_ALIGNMENT, Type: float Name: WIDTH, Type: int Name: HEIGHT, Type: int Name: PROPERTIES, Type: int Name: SOMEBITS, Type: int Name: FRAMEBITS, Type: int Name: ALLBITS, Type: int Name: ERROR, Type: int Name: ABORT, Type: int