След: API Reflection
Урок: Классы
Обнаружение Элементов Класса
Домашняя страница > API Reflection > Классы

Обнаружение Элементов Класса

Есть две категории методов, обеспеченных в Class для того, чтобы получить доступ к полям, методам, и конструкторам: методы, которые перечисляют эти элементы и методы, которые ищут определенные элементы. Также есть отличные методы для того, чтобы получить доступ к элементам, объявленным непосредственно на class против методов, которые ищут суперинтерфейсы и суперклассы для наследованных элементов. Следующие таблицы обеспечивают сводку всех определяющих местоположение элемента методов и их характеристик.


Методы класса для Определения местоположения Полей
Class API Список элементов? Наследованные элементы? Члены парламента, не занимающие официального поста?
getDeclaredField() нет нет да
getField() нет да нет
getDeclaredFields() да нет да
getFields() да да нет


Методы класса для Определения местоположения Методов
Class API Список элементов? Наследованные элементы? Члены парламента, не занимающие официального поста?
getDeclaredMethod() нет нет да
getMethod() нет да нет
getDeclaredMethods() да нет да
getMethods() да да нет


Методы класса для Определения местоположения Конструкторов
Class API Список элементов? Наследованные элементы? Члены парламента, не занимающие официального поста?
getDeclaredConstructor() нет N/A1 да
getConstructor() нет N/A1 нет
getDeclaredConstructors() да N/A1 да
getConstructors() да N/A1 нет

1 Конструктор не наследован.

Учитывая имя class и индикацию которого элементы представляют интерес, ClassSpy пример использует get*s() методы, чтобы определить список всех общедоступных элементов, включая любого, которые наследованы.


import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Member;
import static java.lang.System.out;

enum ClassMember { CONSTRUCTOR, FIELD, METHOD, CLASS, ALL }

public class ClassSpy {
    public static void main(String... args) {
	try {
	    Class<?> c = Class.forName(args[0]);
	    out.format("Class:%n  %s%n%n", c.getCanonicalName());

	    Package p = c.getPackage();
	    out.format("Package:%n  %s%n%n",
		       (p != null ? p.getName() : "-- No Package --"));

	    for (int i = 1; i < args.length; i++) {
		switch (ClassMember.valueOf(args[i])) {
		case CONSTRUCTOR:
		    printMembers(c.getConstructors(), "Constructor");
		    break;
		case FIELD:
		    printMembers(c.getFields(), "Fields");
		    break;
		case METHOD:
		    printMembers(c.getMethods(), "Methods");
		    break;
		case CLASS:
		    printClasses(c);
		    break;
		case ALL:
		    printMembers(c.getConstructors(), "Constuctors");
		    printMembers(c.getFields(), "Fields");
		    printMembers(c.getMethods(), "Methods");
		    printClasses(c);
		    break;
		default:
		    assert false;
		}
	    }

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

    private static void printMembers(Member[] mbrs, String s) {
	out.format("%s:%n", s);
	for (Member mbr : mbrs) {
	    if (mbr instanceof Field)
		out.format("  %s%n", ((Field)mbr).toGenericString());
	    else if (mbr instanceof Constructor)
		out.format("  %s%n", ((Constructor)mbr).toGenericString());
	    else if (mbr instanceof Method)
		out.format("  %s%n", ((Method)mbr).toGenericString());
	}
	if (mbrs.length == 0)
	    out.format("  -- No %s --%n", s);
	out.format("%n");
    }

    private static void printClasses(Class<?> c) {
	out.format("Classes:%n");
	Class<?>[] clss = c.getClasses();
	for (Class<?> cls : clss)
	    out.format("  %s%n", cls.getCanonicalName());
	if (clss.length == 0)
	    out.format("  -- No member interfaces, classes, or enums --%n");
	out.format("%n");
    }
}

Этот пример относительно компактен; однако printMembers() метод является немного неуклюжим вследствие того, что java.lang.reflect.Member интерфейс существовал начиная с самых ранних реализаций отражения и он не мог быть изменен, чтобы включать более полезное getGenericString() метод, когда обобщения были представлены. Единственные альтернативы должны протестировать и бросить как показано, заменить этот метод printConstructors(), printFields(), и printMethods(), или быть удовлетворенным относительно запасными результатами Member.getName().

Выборки вывода и их интерпретации следуют. Ввод данных пользователем курсивом.

$ java ClassSpy java.lang.ClassCastException CONSTRUCTOR
Class:
  java.lang.ClassCastException

Package:
  java.lang

Constructor:
  public java.lang.ClassCastException()
  public java.lang.ClassCastException(java.lang.String)

Так как конструкторы не наследованы, исключение, объединяющее конструкторов механизма в цепочку (те с a Throwable параметр), которые определяются в непосредственном class высшего качества RuntimeException и другие классы высшего качества не находятся.

$ java ClassSpy java.nio.channels.ReadableByteChannel METHOD
Class:
  java.nio.channels.ReadableByteChannel

Package:
  java.nio.channels

Methods:
  public abstract int java.nio.channels.ReadableByteChannel.read
    (java.nio.ByteBuffer) throws java.io.IOException
  public abstract void java.nio.channels.Channel.close() throws
    java.io.IOException
  public abstract boolean java.nio.channels.Channel.isOpen()

Интерфейс java.nio.channels.ReadableByteChannel определяет read(). Остающиеся методы наследованы от интерфейса высшего качества. Этот код мог легко быть изменен, чтобы перечислить только те методы, которые фактически объявляются в class, заменяя get*s() с getDeclared*s().

$ java ClassSpy ClassMember FIELD METHOD
Class:
  ClassMember

Package:
  -- No Package --

Fields:
  public static final ClassMember ClassMember.CONSTRUCTOR
  public static final ClassMember ClassMember.FIELD
  public static final ClassMember ClassMember.METHOD
  public static final ClassMember ClassMember.CLASS
  public static final ClassMember ClassMember.ALL

Methods:
  public static ClassMember ClassMember.valueOf(java.lang.String)
  public static ClassMember[] ClassMember.values()
  public final int java.lang.Enum.hashCode()
  public final int java.lang.Enum.compareTo(E)
  public int java.lang.Enum.compareTo(java.lang.Object)
  public final java.lang.String java.lang.Enum.name()
  public final boolean java.lang.Enum.equals(java.lang.Object)
  public java.lang.String java.lang.Enum.toString()
  public static <T> T java.lang.Enum.valueOf
    (java.lang.Class<T>,java.lang.String)
  public final java.lang.Class<E> java.lang.Enum.getDeclaringClass()
  public final int java.lang.Enum.ordinal()
  public final native java.lang.Class<?> java.lang.Object.getClass()
  public final native void java.lang.Object.wait(long) throws
    java.lang.InterruptedException
  public final void java.lang.Object.wait(long,int) throws
    java.lang.InterruptedException
  public final void java.lang.Object.wait() hrows java.lang.InterruptedException
  public final native void java.lang.Object.notify()
  public final native void java.lang.Object.notifyAll()

В полевой части этих результатов перечисляются перечислимые константы. В то время как они - технически поля, могло бы быть полезно отличить их от других полей. Этот пример мог быть изменен, чтобы использовать java.lang.reflect.Field.isEnumConstant() с этой целью. EnumSpy пример в более позднем разделе этого следа, Исследуя Перечисления, содержит возможную реализацию.

В разделе методов вывода заметьте, что имя метода включает имя объявления class. Таким образом, toString() метод реализуется Enum, не наследованный от Object. Код мог быть исправлен, чтобы сделать это более очевидным при использовании Field.getDeclaringClass(). Следующий фрагмент иллюстрирует часть потенциального решения.

if (mbr instanceof Field) {
    Field f = (Field)mbr;
    out.format("  %s%n", f.toGenericString());
    out.format("  -- declared in: %s%n", f.getDeclaringClass());
}

Проблемы с примерами? Попытайтесь Компилировать и Выполнить Примеры: FAQ.
Жалобы? Поздравление? Предложения? Дайте нам свою обратную связь.

Предыдущая страница: Исследование Модификаторов Класса и Типов
Следующая страница: Поиск и устранение неисправностей



Spec-Zone.ru - all specs in one place