【Java技术-反射】Java反射机制

        包名: java.lang.reflect.*
        Java反射机制是在运行状态(Runtime)中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法,获取它的成员变量;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。

        Java反射机制是Java语言被视为"准动态"语言的关键性质。Java反射机制的核心就是允许在运行时通过Java Reflection APIs来取得已知名字的class类的内部信息(包括其modifiers(诸如public, static等等)、superclass(例如Object)、实现interfaces(例如Serializable),也包括fields和 methods的所有信息),动态地生成此类,并调用其方法或修改其域(甚至是本身声明为private的域或方法)。

        Java反射机制主要提供了以下功能:在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。


1. Object
     1.1 ClassgetClass()
    Returns the runtime class of this Object.
例: KeyBoard k = new KeyBoard();
     Class clazz = k.getClass(); 或 Class clazz = k.getClass();

2. Class
         Class对象是Java反射的基础,它包含了与类相关的信息,事实上,Class对象就是用来创建类的所有对象的。Class对象是java.lang.Class这个类生成的对象,其中类型参数T表示由此 Class 对象建模的类的类型。例如,String.class的类型是 Class;如果将被建模的类未知,则使用Class。以下是Java API的描述:

        Class类的实例表示正在运行的 Java应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为Class对象的一个类,所有具有相同元素类型和维数的数组都共享该Class对象。基本的Java类型(booleanbyte、 char、shortintlongfloatdouble)和关键字void也表示为Class对象。

        Class没有公共构造方法。Class对象是在加载类时由Java虚拟机以及通过调用类加载器中的defineClass方法自动构造的。

        每个类都有一个Class对象。换言之,每当编写并且编译了一个新类,就会产生一个Class对象(更恰当的说,是被保存在一个同名的.class文件中)。如果我们想生成这个类的对象,运行这个程序的Java虚拟机(JVM)将使用类加载器子系统,类加载器首先检查这个类的Class对象是否已经加载。如果尚未加载,默认的类加载器就会根据类名查找.class文件,并将其载入,一旦某个类的Class对象被载入内存,它就被用来创建这个类的所有对象。

获取Class对象有三种方式:

       (1) Object类的getClass()方法,例:

            Class c1 = new String("").getClass();

       (2) Class类的静态方法forName(),例:
            Class c2 = Class.forName(className);

        当使用Class.forName()方法时,必须提供完全限定类名。即类名要包括所有包名。

       (3) 使用类字面常量或TYPE字段,例:
            Class c3 = Manager.class;

            Class c4 = int.class;

            Class c5 = Double[].class;

        这种方式不仅更简单,而且更安全,因为它在编译时就会受到检查,并且根除了对forName方法的调用,也更高效,建议使用“.class”的形式
        TYPE是基本数据类型的包装类型的一个标准字段,它是一个引用,指向对应的基本数据类型的Class对象,附表如下:     

boolean.class

Boolean.TYPE

char.class

Character.TYPE

byte.class

Byte.TYPE

short.class

Short.TYPE

int.class

Integer.TYPE

long.class

Long.TYPE

float.class

Float.TYPE

double.class

Double.TYPE

void.class

Void.TYPE

   

    使用Java反射,你可以在运行时检查Java类。检查类是使用反射时经常做的第一件事情。从类中可以获取以下信息:

(1) 类名

(2) 类修饰符 (public, private, synchronized)

(3) 包信息

(4) 父类

(5) 实现的接口

(6) 构造函数

(7) 方法

(8) 字段

(9) 注解

(10) 内部类


    2.1 类名(getName(), getSimpleName())

    从Class对象中可以获取两个不同的类名。完全限定类名(包括包名)可以使用getName()getCanonicalName()方法获取,例如:

        Class myClazz = MyObject.class;

        String className = myClazz.getName();

        String className1 = myClazz.getCanonicalName();

    如果想要获取不含包名的类名可以使用getSimpleName() 方法,如下:

        String simpleClassName = myClazz.getSimpleName();


    2.2 修饰符(getModifiers())

    使用Class对象可以获取一个类的修饰符类的修饰符即关键字"public","private", "static". 如下:

        int modifiers = myClazz.getModifiers();

    修饰符被包装进一个int内,每一个修饰符都是一个标志位(置位或清零)。可以使用java.lang.reflect.Modifier中的以下方法来检验修饰符:

        Modifier.isAbstract(int modifiers)

        Modifier.isFinal(int modifiers)

        Modifier.isInterface(int modifiers)

        Modifier.isNative(int modifiers)

        Modifier.isPrivate(int modifiers)

        Modifier.isProtected(int modifiers)

        Modifier.isPublic(int modifiers)

        Modifier.isStatic(int modifiers)

        Modifier.isStrict(int modifiers)

        Modifier.isSynchronized(int modifiers)

        Modifier.isTransient(int modifiers)

        Modifier.isVolatile(int modifiers)


    2.3 包信息(getPackage())

    使用Class对象可以获取包信息java.lang.Package,如下:

        Package package = myClazz.getPackage();

        String packageName = package.getname();

    从Package对象中你可以访问诸如名字等包信息。您还可以访问类路径上这个包位于JAR文件中Manifest这个文件中指定的信息。


    2.4 父类(getSuperclass())

    通过Class对象可以获取类的父类,如下:

        Class superclass = myClazz.getSuperclass();

    父类的Class对象和其它Class对象一样是一个Class对象,可以继续使用反射。


    2.5 实现的接口(getInterfaces()), 只有给定类声明实现的接口才会返回

    通过给定的类可以获取这个类所实现的接口列表,如下:

        Class[] interfaces = myClazz.getInterfaces();

    一个类可以实现多个接口。因此返回一个Class数组。在Java反射机制中,接口也由Class对象表示。

    只有给定类声明实现的接口才会返回。例如,如果类A的父类B实现了一个接口C,但类A并没有声明它也实现了C,那么C不会被返回到数组中。即使类A实际上实现了接口C,因为它的父类B实现了C。

    为了得到一个给定的类实现接口的完整列表,需要递归访问类和其超类。


    2.6 构造函数

//获取一个公有的构造函数,参数为指定参数
public Constructor getConstructor (Class... parameterTypes)
//获取目标类所有的公有构造函数
public Constructor[] getConstructors ()
// 获取目标类的一个构造函数,参数为指定参数
public Constructor get
DeclaredConstructor (Class... parameterTypes)
// 获取目标类所有的公有构造函数
public Constructor[] getDeclaredConstructors ()
    2.7 方法
    这里需要注意的是 getDeclaredMethod 和 getDeclaredMethods 包含private、protected、default、public的函数,并且通过这两个函数获取到的只是在自身中定义的函数,也包括自己实现的接口,从父类和接口中继承的函数不能够获取到。而 getMethod 和 getMethods 只包含 public 函数,父类和接口继承的公有函数也能够获取到。

//获取该类中的指定参数的某一方法, 可以是private、protected、default、public的, (不包含从父类和接口继承的).
public Method getDeclaredMethod (String name, Class... parameterTypes)
//获取该类中的所有函数(不包含从父类继承的函数).
public Method[] getDeclaredMethods ()

//获取该类指定参数的某一公有函数, (包含从父类和接口类继承下来的)
public Method getMethod (String name, Class... parameterTypes)
//
获取该类所有公有函数, (包含从父类和接口类集成下来的函数)
public Method[] getMethods ()
    2.8 字段
    getDeclaredField 和 getDeclaredFields 包含 private、protected、default、public 的属性,并且通过这两个函数获取到的只是在自身中定义的属性,从父类中集成的属性不能够获取到。而 getField 和 getFields 只包含 public 属性,父类中的公有属性也能够获取到。
// 获取 Class 对象中指定属性名的某一属性
public Method getDeclaredField (String name)
// 获取该 Class 对象中的所有属性( 不包含从父类继承的属性 )
public Method[] getDeclaredFields ()
// 获取指定的Class对象中指定属性名的某一公有属性
public Method getField (String name)
// 获取该Class对象中的所有公有属性 ( 包含从父类和接口类继承下来的公有属性 )
public Method[] getFields ()
    2.9 注解
// 获取该类某一指定公有注解
public Annotation> A getAnnotation(Class annotationClass)
// 获取该类所有公有注解
public Annotation[] getAnnotations()

// 获取该类某一注解
public Annotation> A getDeclaredAnnotation(Class annotationClass)

// 获取该类所有注解
public Annotation[] getDeclaredAnnotations()

    2.10 内部类

// 获取该类公有内部类(包含父类)
public Class[] getClasses()
// 获取该类所有内部类,包含私有内部类。
public Class[] getDeclaredClasses()
// 获取该类的外部类
public Class getDeclaringClass()

    2.11 其它方法

// ([自身类.class]).isAssignableFrom([自身类.class]或[其子类.class])  返回true

isAssignableFrom(Class cls)


// ([自身类.class]).isInstance([自身类的实例obj]或[其子类的实例obj])  返回true

isInstance(Object obj)

// 这里不是Class成员方法,是一个运算符,放在这里一起比较;
// [实例obj] instanceof [自身类、其父类、抽象类接口],右边使用的是简单类名,而不是Class。
instanceof

// 生成本类的对象,只能调用无参构造。我们使用new的时候,这个要new的类可以没有加载。使用newInstance时候,就必须保证:1、这个类已经加载;2、这个类已经连接了。Class的静态方法forName()调用了启动类加载器(就是加载javaAPI的那个加载器)。newInstance实际上是把new这个方式分解为两步,即,首先调用class的加载方法加载某个类,然后实例化。这样分步的好处是显而易见的。我们可以在调用Class的静态加载方法forName()时获得更好的灵活性(传入的className可以是从任何地方获取的),提供给了我们降耦的手段。
newInstance()

// 返回当前clazz是否为成员类;

isMemberClass()


// 返回当前类是否为接口;
isInterface()


3. Constructor
// 返回当前Constructor实例所在的Class.
Class<TgetDeclaringClass()

// 返回当前Constructor实例参数个数.
int getParameterCount()

// 返回当前Constructor实例各参数对应的Class类型.
Class[] getParameterTypes()

// 返回当前Constructor实例的各参数类型.
TypeVariable<Constructor<T>>[] getTypeParameters()

//  返回当前Constructor实例对应的方法修饰符.
int getModifiers()

// 返回当前方法名.
String getName()

// 使用当前Constructor实例构造一个该Constructor实例所在的Class的实例,相当于调用其对应参数个数的构造方法.
T newInstance(Object... initargs)


4. Field
// 返回指定对象obj上此Field对象表示的字段的值。
Object get(Object obj)

// 将指定对象变量obj上此Field对象表示的字段设置为指定的新值。
void set(Object obj, Object value)

// 返回一个Class对象,它标识了此Field对象所表示字段的声明类型。
Class getType()

// 返回表示类或接口的Class对象,该类或接口声明了由此Field对象表示的字段。
Class getDeclaringClass()

// 返回此Field对象表示的字段的名称。
String getName()

// 以整数形式返回由此Field对象表示的字段的 Java 语言修饰符。
int getModifiers()


5. Method
// 以指定参数调用obj对象的此Method所表示的方法。
Object invoke(Object obj, Object... args)

// 返回此Method实例参数个数.
int getParameterCount()

// 返回Method实例各参数对应的Class类型.
Class[] getParameterTypes()

// 返回Method实例的各参数类型.
TypeVariable<Constructor<T>>[] getTypeParameters()

// 返回Method实例的返回值类型.
Class getReturnType()

// 返回表示类或接口的Class对象,该类或接口声明了由此Method对象表示的方法。
Class getDeclaringClass()

// 返回此Method对象表示的方法的名称。
String getName()

// 以整数形式返回由此Method对象表示的方法的 Java 语言修饰符。
int getModifiers()


6. Modifier
// 一个的修饰符的按位或组合, 参考Java Language Specification 8.1.1, 可能为 Annotation, public, protected,  private, abstract, static, final, strictfp.
static int classModifiers()

// 一个构造函数修饰符的按位或组合,参考Java Language Specification 8.8.3, 可能为Annotation, public, protected, private.
static int constructorModifiers()

// 一个成员变量修饰符的按位或组合,参考Java Language Specification 8.3.1, 可能为Annotation, public, protected, private,  static, final, transient, volatile.
static int fieldModifiers()

// 一个接口的修饰符的按位或组合, 参考Java Language Specification 9.1.1, 可能为Annotation, public, protected, private, abstract, static, strictfp.
static int interfaceModifiers()

// 一个方法修饰符的按位或组合,参考Java Language Specification 8.4.3, 可能为Annotation, public, protected, private, abstract, static, final,
synchronized,native, strictfp.
static int methodModifiers()

// 一个参数变量修饰符的按位或组合,参考Java Language Specification 8.4.1.
static int parameterModifiers()

abstract
static int ABSTRACT
static boolean isAbstract(int mod)
final
static int FINAL
static boolean isFinal (int mod)
interface
static int INTERFACE
static boolean isInterface (int mod)
native
static int NATIVE
static boolean isNative (int mod)
private
static int PRIVATE
static boolean isPrivate (int mod)
protect
static int PROTECT
static boolean isProtect (int mod)
public
static int PUBLIC
static boolean isPublic (int mod)
static
static int STATIC
static boolean isStatic (int mod)
strictfp
static int STRICT
static boolean isStrict (int mod)
synchronized
static int SYNCHRONIZED
static boolean isSynchronized (int mod)
transient
static int TRANSIENT
static boolean isTransient (int mod)
volatile
static int VOLATILE
static boolean isVolatile (int mod)


参考: 
1. http://blog.csdn.net/jackiehff/article/details/8509075
2. http://p.codekk.com/blogs/detail/5596953ed6459ae7934997c5
3. http://docs.oracle.com/javase/8/docs/api/
4. http://docs.oracle.com/javase/specs/jls/se8/html/

http://blog.csdn.net/tbwood/article/details/40739947

你可能感兴趣的:(Java技术)