Изучение динамического определения типов
Класс Class. Динамическая загрузка и инстанцирование классов. В Java вся информация о классе хранится в специальном объекте типа Class. Для каждого класса в программе существует свой объект Class, который создается при загрузке класса, созданного на этапе компиляции и сохраненного на диске в файле с расширением class.
Класс Class. Динамическая загрузка и инстанцирование классов (2) Чтоб получить экземпляр Class, соответствующий данному классу (или интерфейсу): Добавить к имени класса суффикс.class, например: Class clazz = String.class; используем литерал объекта Сlass. Если есть экземпляр некоторого класса, может быть даже неизвестного в данной точке программы, можно вызвать метод getClass(), присутствующий в каждом Java-объекте (унаследованный от класса Object). Вызывать статический метод класса Class.forName(), который возвращает экземпляр Class: Class clazz = Class.forName("Полное_имя_класса");
Класс Class. Динамическая загрузка и инстанцирование классов (3) Литералы объектов Class работают с регулярными классами, а также с интерфейсами, массивами и примитивными типами. Class clazz = byte[].class; Существует стандартное поле называемое TYPE, которое существует для каждого примитивного класса- оболочки. Поле TYPE создает ссылку на объект Class для соответствующего примитивного класса.
Создание объектов В Java встроена возможность динамической загрузки произвольного класса по заданному имени, и реализуется классом Class. Метод отыскивает в системе (в пути поиска CLASSPATH) класс с заданным именем className и возвращает соответствующий экземпляр класса Class. Имя класса должно быть полным, т.е. включать имя пакета. Если такой класс отсутствует, возбуждается исключение ClassNotFoundException.
Создание объектов (2) После того как получен объект типа Class можно создать экземпляр этого класса. Для успешного выполнения этого метода у класса должен быть описан конструктор без параметров (конструктор по умолчанию), иначе будет возбуждено исключение InstantiationException.
Создание объектов (3) Чтобы работать с таким объектом необходимо знать методы класса, их параметры и возвращаемые значения. Для указания контракта класса используют интерфейсы.
Создание объектов (4) Пример: Необходимо реализовать приложение с возможностью перевода текста с одного языка на другой.
Создание объектов (5)
Создание объектов (6) Пример: Необходимо реализовать систему журналирования. Reflection_Example.htm
Исследование классов В классе Class существует специальный набор методов для исследования классов.
Исследование классов (2) И соответствующие методы проверки типа класса:
Исследование классов (3)
Работа с массивами Для работы с массивами в пакете существует специальный утилитный класс java.lang.reflect.Array. Для определения длинны массива существует метод: public static native int getLength(Object array) throw IllegalArgumentException; Массив в Java является объектом, его можно передать как параметр в метод.
Работа с массивами (2) Если аргумент не является массивом, то будет сгенерировано исключение IllegalArgumentException. public static Object get(Object array, int idx); public static char getXXX(Object array, int idx); public static void set(Object array, int idx, Object value); public static void setXXX(Object array, int idx, XXX value); public static Object newInstance(Class type, int length); public static Object newInstance(Class type, int[] dimensions);
Работа с массивами (3) Пример функции определяющей длину массива:
Раскрытие модификаторов класса. Для раскрытия модификаторов полученных членов класса используют метод int getModifiers (), который возвращает модификатор в виде целого. Все модификаторы определены в классе java.lang.reflect.Modifier PRIVATE, PROTECTED, PUBLIC ABSTRACT, FINAL, STATIC INTERFACE SYNCHRONIZED TRANSIENT, VOLATILE NATIVE Для каждого из модификаторов определен соответствующий метод boolean isXXXX(int m)
Примеры Пример раскрытия модификаторов класса: Reflection_Modif.htm Reflection_Modif.htm Вызов методов рассмотрим на примере класса, реализующего интроспекцию полей таблицы в свойства объекта: Reflection_Meth.htmReflection_Meth.htm Обозреватель JAR ClassDetail.java Lab1.java MyClassLoader.java
Примеры (1) Пример раскрытия модификаторов класса:
Примеры (2) package Labs; import java.lang.reflect.Field; public class ClassDetail { private ClassDetail() { } public static String getInfo(Class clazz){ StringBuffer buf = new StringBuffer(); if (clazz.isAnnotation()) buf.append("Annotation "); else if(clazz.isInterface()) buf.append("Interface "); else if(clazz.isEnum()) buf.append("Enum "); else buf.append("Class "); buf.append(clazz.getName()+" "); if (clazz.isArray()) buf.append("array"); if (clazz.isLocalClass()) buf.append("local"); buf.append("\n"); buf.append(getFieldNames(clazz)); return buf.toString(); }
Примеры (2) public static String getFieldNames(Class clazz) { StringBuffer buf = new StringBuffer(); try{ Field[] publicFields = clazz.getDeclaredFields(); for (int i = 0; i < publicFields.length; i++) { try { String fieldName = publicFields[i].getName(); buf.append("Name: " + fieldName); Class typeClass = publicFields[i].getType(); String fieldType = typeClass.getName(); buf.append(", Type: " + fieldType +"\n" ); }catch(Exception e){ buf.append( "\n" ); } } }catch(Throwable e){ } return buf.toString(); } }
Примеры (3) package Labs; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.lang.ClassLoader; public class Lab2 { /** args IOException FileNotFoundException ClassNotFoundException */ public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException { ClassLoader loader = new MyClassLoader(args[0]); JarFile f = new JarFile(args[0]); Enumeration enumiration = f.entries(); String s; Class c; JarEntry e;
Примеры (4) while(enumiration.hasMoreElements()){ e = enumiration.nextElement(); if (e.getName().contains(".class")) { System.out.print(e.getName()+":"); s = e.getName().replaceAll("/", "."); s = s.substring(0, s.length()-6); try{ c = Class.forName(s, false, loader); if (c!=null){ System.out.println(":"+ClassDetail.getInfo(c)); } }catch(Exception e2){ System.out.println("Error:"+e2.getMessage()); } }else{ //System.out.println(e.getName()); } } f.close(); } }
Примеры (5) package Labs; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; import java.util.jar.JarEntry; import java.util.jar.JarFile; class MyClassLoader extends ClassLoader { private String jarName; private JarFile jar; private Map loaded = new HashMap (); public MyClassLoader(String jarName) { super(MyClassLoader.class.getClassLoader()); this.jarName = jarName; try { this.jar = new JarFile( jarName ); } catch (IOException e) { e.printStackTrace(); } }
Примеры (6) public Class findClass(String name) throws ClassNotFoundException{ Class c = loaded.get(name); if (c!=null) return c; try{ return findSystemClass(name); }catch(Exception e){ } byte[] b; try{ b = loadClassData(name); c=defineClass(name, b, 0, b.length); loaded.put(name, c); }catch(Throwable e){ throw new ClassNotFoundException(e.getMessage()); } return c; }
Примеры (7) private byte[] loadClassData(String name) throws ClassNotFoundException { String entryName = name.replace('.', '/') + ".class"; byte buf[]=new byte[0]; try { JarEntry entry = jar.getJarEntry(entryName); if (entry==null){ throw new ClassNotFoundException(name); } InputStream input = jar.getInputStream( entry ); int size = new Long(entry.getSize()).intValue(); buf = new byte[size]; int count = input.read(buf/*, 0, size*/); if (count < size) throw new ClassNotFoundException("Error reading class '"+ name+"' from :"+jarName); } catch (IOException e1) { throw new ClassNotFoundException(e1.getMessage()); } return buf; } }