Java 反射相关整理

1. Class 类

  • Class 是一个类,封装了当前对象所对应的类的信息,一个类中有属性,方法,构造器等。

    • 对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个类的有关信息。
    • Class 对象只能由系统建立对象,一个类(而不是一个对象)在 Java 虚拟机中只会有一个 Class 实例。
    • Class 对象的由来是将 class 文件读入内存,并为之创建一个 Class 对象。

获取 Class 类对象的三种方法

  • 使用 Class.forName 静态方法,当知道类的全路径名时,可以使用该方法获取 Class 类对象。
Class clz = Class.forName("java.lang.String");
  • 使用 .class 方法,这种方法适合在编译前就知道操作的 Class。
Class clz = String.class;
  • 使用类对象的 getClass() 方法。
String str = new String("Hello");
Class clz = str.getClass();

Class 类的常用方法

方法名 功能说明
static Class forName(String name) 返回指定类名 name 的 Class 对象。
Object newInstance() 调用缺省构造函数,返回该 Class 对象的一个实例。
getName() 返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。
Class getSuperClass() 返回当前 Class 对象的父类 Class 对象。
Class [] getInterfaces() 获取当前 Class 对象的接口。
ClassLoader getClassLoader() 返回该类的类加载器。

2. Java 反射(Reflection)

  • Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言的反射机制。

    • 反射是 Java 被视为动态语言的关键,反射机制允许程序在执行期借助于 Reflection API 取得任何类的內部信息,并能直接操作任意对象的内部属性及方法。
    • 反射机制就是可以把一个类、类的成员(函数,属性),当成一个对象来操作。
    • Java 反射主要提供以下功能。
      • 在运行时判断任意一个对象所属的类。
      • 在运行时构造任意一个类的对象。
      • 在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用 private 方法)。
      • 在运行时调用任意一个对象的方法。
      • 生成动态代理。

2.1 通过反射访问构造函数

  • 为了能够动态获取对象构造方法的信息,需要创建一个 Constructor 类型的对象或者数组。

    • getConstructors()
    • getConstructor(Class<?>…parameterTypes)
    • getDeclaredConstructors()
    • getDeclaredConstructor(Class<?>...parameterTypes)
  • 创建的每个 Constructor 对象表示一个构造方法,然后利用 Constructor 对象的方法操作构造方法。
Constructor 对象方法名称 说明
isVarArgs() 查看该构造方法是否允许带可变数量的参数,如果允许,返回 true,否则返回 false。
getParameterTypes() 按照声明顺序以 Class 数组的形式获取该构造方法各个参数的类型。
getExceptionTypes() 以 Class 数组的形式获取该构造方法可能抛出的异常类型。
newInstance(Object … initargs) 通过该构造方法利用指定参数创建一个该类型的对象,如果未设置参数则表示采用默认无参的构造方法。
setAccessiable(boolean flag) 如果该构造方法的权限为 private,默认为不允许通过反射利用 netlnstance() 方法创建对象。如果先执行该方法,并将入口参数设置为 true,则允许创建对象。
getModifiers() 获得可以解析出该构造方法所采用修饰符的整数。
public void testConstructor() throws Exception{
        String className = "com.java.test.Person";
        Class<Person> clazz = (Class<Person>) Class.forName(className);

        // 获取全部 Constructor 对象
        Constructor<Person> [] constructors = (Constructor<Person>[]) Class.forName(className).getConstructors();

        // 获取某一个,需要参数列表
        Constructor<Person> constructor = clazz.getConstructor(String.class, int.class);

        // 调用构造器的 newInstance() 方法创建对象
        Object obj = constructor.newInstance("test", 1);
}
Modifier 对象的静态方法名称 说明
isStatic(int mod) 如果使用 static 修饰符修饰则返回 true,否则返回 false。
isPublic(int mod) 如果使用 public 修饰符修饰则返回 true,否则返回 false。
isProtected(int mod) 如果使用 protected 修饰符修饰则返回 true,否则返回 false。
isPrivate(int mod) 如果使用 private 修饰符修饰则返回 true,否则返回 false。
isFinal(int mod) 如果使用 final 修饰符修饰则返回 true,否则返回 false。
toString(int mod) 以字符串形式返回所有修饰符。
int modifiers = con.getModifiers();    //获取构造方法的修饰符整数。
boolean isPubiic = Modifier.isPublic(modifiers);    //判断修饰符整数是否为 public。
public string ailModifSers = Modifier.toString(modifiers);

2.2 通过反射执行方法(获取方法)

  • 要动态获取一个对象方法的信息,需要创建一个 Method 类型的对象或者数组。

    • getMethods()
    • getMethods(String name,Class<?> …parameterTypes)
    • getDeclaredMethods()
    • getDeclaredMethods(String name,Class<?>...parameterTypes)
  • 如果是访问指定的构造方法,需要根据该方法的入口参数的类型来访问。
objectCiass.getDeclaredConstructor("max",int.class,String.class);
objectClass.getDeclaredConstructor("max",new Ciass[]{int.class,String.class});
Method 对象静态方法名称 说明
getName() 获取该方法的名称。
getParameterType() 按照声明顺序以 Class 数组的形式返回该方法各个参数的类型。
getRetumType() 以 Class 对象的形式获得该方法的返回值类型。
getExceptionTypes() 以 Class 数组的形式获得该方法可能抛出的异常类型。
invoke(Object obj,Object...args) 利用 args 参数执行指定对象 obj 中的该方法,返回值为 Object 类型。
isVarArgs() 查看该方法是否允许带有可变数量的参数,如果允许返回 true,否 则返回 false。
getModifiers() 获得可以解析出该方法所采用修饰符的整数。
public void testMethod() throws Exception{
        Class clazz = Class.forName("com.java.test.Person");

        // 获取取 clazz 对应类中的所有方法,但不能获取 private 方法,且获取从父类继承来的所有方法。
        Method[] methods = clazz.getMethods();

        // 获取所有方法,包括私有方法,获取所有声明的方法,且只获取当前类的方法
        methods = clazz.getDeclaredMethods();

        // 获取指定的方法,需要参数名称和参数列表,无参则不需要
        //  方法 public void setName(String name)
        Method method = clazz.getDeclaredMethod("setName", String.class);

        //  方法 public void setAge(int age)
        //  方法用于反射,只能对应 int.class,不能对应 Integer.class
        method = clazz.getDeclaredMethod("setAge", int.class);

        // 执行方法
        //  invoke 第一个参数表示执行某个对象的方法,剩下的参数是执行方法时需要传入的参数
        // 私有方法的执行,必须在调用 invoke 之前加上 method.setAccessible(true);
        Object obje = clazz.newInstance();
        method.invoke(obje,2);
}

2.3 通过反射访问成员变量

  • 通过方法访问成员变量时将返回 Field 类型的对象或数组。

    • getFields()
    • getField(String name)
    • getDeclaredFields()
    • getDeclaredField(String name)
  • 返回的 Field 对象代表一个成员变量。
object.getDeciaredField("price");
Field 的方法名称 说明
getName() 获得该成员变量的名称。
getType() 获取表示该成员变量的 Class 对象。
get(Object obj) 获得指定对象 obj 中成员变量的值,返回值为 Object 类型。
set(Object obj,Object value) 将指定对象 obj 中成员变量的值设置为 value。
getlnt(0bject obj) 获得指定对象 obj 中成员类型为 int 的成员变量的值。
setlnt(0bject obj,int i) 将指定对象 obj 中成员变量的值设置为 i。
setFloat(Object obj,float f) 将指定对象 obj 中成员变量的值设置为 f。
getBoolean(Object obj) 获得指定对象 obj 中成员类型为 boolean 的成员变量的值。
setBoolean(Object obj,boolean b) 将指定对象 obj 中成员变量的值设置为 b。
getFloat(Object obj) 获得指定对象 obj 中成员类型为 float 的成员变量的值。
setAccessible(boolean flag) 此方法可以设置是否忽略权限直接访问 private 等私有权限的成员变量。
getModifiers() 获得可以解析出该方法所采用修饰符的整数。
public void testField() throws Exception{
        String className = "com.java.test.Person";
        Class clazz = Class.forName(className); 

        // 获取所有字段,可以获取公用和私有的所有字段,但不能获取父类字段
        Field[] fields = clazz.getDeclaredFields();

        // 获取指定字段
        Field field = clazz.getDeclaredField("name");

        Person person = new Person("ABC",12);

        //获取指定对象的指定字段的值
        Object val = field.get(person);

        //设置指定对象的指定对象 Field 值
        field.set(person, "DEF");

        // 如果字段是私有的,不管是读值还是写值,都必须先调用 setAccessible(true) 方法
        field.setAccessible(true);
        field = clazz.getDeclaredField("age");

}

2.4 通过反射访问注解

  • 定义一个注解。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(value={ElementType.METHOD})
public @interface AgeValidator {
    public int min();
    public int max();
}
  • 应用于方法上。
@AgeValidator(min=18,max=35)
public void setAge(int age) {
        this.age = age;
}
  • 通过反射的方式为属性赋值,获取注解。
public void testAnnotation() throws Exception{
        String className = "com.java.test.Person";

        Class clazz = Class.forName(className);
        Object obj = clazz.newInstance();    

        Method method = clazz.getDeclaredMethod("setAge", int.class);
        int val = 6;

        //获取指定名称的注解
        Annotation annotation = method.getAnnotation(AgeValidator.class);
        if(annotation != null){
            if(annotation instanceof AgeValidator){
                AgeValidator ageValidator = (AgeValidator) annotation;
                if(val < ageValidator.min() || val > ageValidator.max()){
                    throw new RuntimeException("年龄非法");
                }
            }
        }
        method.invoke(obj, 20);
}
  • 如果在程序中需要获取注解,然后根据获取注解的值进而判断赋值是否合法,那么类对象的创建和方法的创建必须通过反射而来。

3. 实现原理

3.1 Method 的获取

  • 通过调用 Class 类的 getDeclaredMethod() 方法可以获取指定方法名和参数的方法对象 Method。
  • 调用 checkMemberAccess() 方法进行一些权限检查。
@CallerSensitive
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
        throws NoSuchMethodException, SecurityException {
        checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
        Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
        if (method == null) {
            throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
        }
        return method;
}
  • 调用 privateGetDeclaredMethods() 方法从缓存或 Java 虚拟机获取 Class 中申明的方法列表。
  • 调用 searchMethods() 方法从返回的方法列表里找到一个匹配名称和参数的方法对象(Method)。
private static Method searchMethods(Method[] methods,
                                        String name,
                                        Class<?>[] parameterTypes)
{
        Method res = null;
        String internedName = name.intern();
        for (int i = 0; i < methods.length; i++) {
            Method m = methods[i];
            if (m.getName() == internedName
                && arrayContentsEq(parameterTypes, m.getParameterTypes())
                && (res == null
                    || res.getReturnType().isAssignableFrom(m.getReturnType())))
                res = m;
        }

        return (res == null ? res : getReflectionFactory().copyMethod(res));
}
  • 如果找到一个匹配的方法对象(Method),则重新拷贝一份返回。

    • 实际调用了 Method.copy() 方法。
Method copy() {
        // This routine enables sharing of MethodAccessor objects
        // among Method objects which refer to the same underlying
        // method in the VM. (All of this contortion is only necessary
        // because of the "accessibility" bit in AccessibleObject,
        // which implicitly requires that new java.lang.reflect
        // objects be fabricated for each reflective call on Class
        // objects.)
        if (this.root != null)
            throw new IllegalArgumentException("Can not copy a non-root Method");

        Method res = new Method(clazz, name, parameterTypes, returnType,
                                exceptionTypes, modifiers, slot, signature,
                                annotations, parameterAnnotations, annotationDefault);
        res.root = this;
        // Might as well eagerly propagate this if already present
        res.methodAccessor = methodAccessor;
        return res;
}
  • 因为每次调用 getDeclaredMethod() 方法返回的方法对象(Method)都是一个新的对象,且新对象的 root 属性都指向原来的 Method 对象,如果频繁的调用,则最好的方式就是将 Method 缓存起来。

privateGetDeclaredMethods 的缓存实现

  • privateGetDeclaredMethods() 方法会从缓存或 Java 虚拟机获取 Class 中申明的方法列表。
private Method[] privateGetDeclaredMethods(boolean publicOnly) {
        checkInitted();
        Method[] res;
        ReflectionData<T> rd = reflectionData();
        if (rd != null) {
            res = publicOnly ? rd.declaredPublicMethods : rd.declaredMethods;
            if (res != null) return res;
        }
        // No cached value available; request value from VM
        res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly));
        if (rd != null) {
            if (publicOnly) {
                rd.declaredPublicMethods = res;
            } else {
                rd.declaredMethods = res;
            }
        }
        return res;
}
  • 延迟创建和缓存 ReflectionData 数据对象。
private ReflectionData<T> reflectionData() {
        SoftReference<ReflectionData<T>> reflectionData = this.reflectionData;
        int classRedefinedCount = this.classRedefinedCount;
        ReflectionData<T> rd;
        if (useCaches &&
            reflectionData != null &&
            (rd = reflectionData.get()) != null &&
            rd.redefinedCount == classRedefinedCount) {
            return rd;
        }
        // else no SoftReference or cleared SoftReference or stale ReflectionData
        // -> create and replace new instance
        return newReflectionData(reflectionData, classRedefinedCount);
}
  • ReflectionData 数据对象,用来缓存从 Java 虚拟机中读取类的一些属性数据。
private static class ReflectionData<T> {
        volatile Field[] declaredFields;
        volatile Field[] publicFields;
        volatile Method[] declaredMethods;
        volatile Method[] publicMethods;
        volatile Constructor<T>[] declaredConstructors;
        volatile Constructor<T>[] publicConstructors;
        // Intermediate results for getFields and getMethods
        volatile Field[] declaredPublicFields;
        volatile Method[] declaredPublicMethods;
        volatile Class<?>[] interfaces;

        // Value of classRedefinedCount when we created this ReflectionData instance
        final int redefinedCount;

        ReflectionData(int redefinedCount) {
            this.redefinedCount = redefinedCount;
        }
}
  • ReflectionData 数据对象实现为 SoftReference 类型,在内存紧张时可能会被回收,也可以通过 -XX:SoftRefLRUPolicyMSPerMB 参数控制回收时机,发生 GC 就将其回收。
  • 如果 ReflectionData 数据对象被回收后又执行了反射方法,那只能通过 newReflectionData() 方法重新创建一个新的 ReflectionData 对象。
private ReflectionData<T> newReflectionData(SoftReference<ReflectionData<T>> oldReflectionData,
                                                int classRedefinedCount) {
        if (!useCaches) return null;

        while (true) {
            ReflectionData<T> rd = new ReflectionData<>(classRedefinedCount);
            // try to CAS it...
            if (Atomic.casReflectionData(this, oldReflectionData, new SoftReference<>(rd))) {
                return rd;
            }
            // else retry
            oldReflectionData = this.reflectionData;
            classRedefinedCount = this.classRedefinedCount;
            if (oldReflectionData != null &&
                (rd = oldReflectionData.get()) != null &&
                rd.redefinedCount == classRedefinedCount) {
                return rd;
            }
        }
}
  • 通过 unsafe.compareAndSwapObject() 方法重新设置 reflectionData 字段。
reflectionDataOffset = objectFieldOffset(fields, "reflectionData");
......
static <T> boolean casReflectionData(Class<?> clazz,
                                             SoftReference<ReflectionData<T>> oldData,
                                             SoftReference<ReflectionData<T>> newData) {
            return unsafe.compareAndSwapObject(clazz, reflectionDataOffset, oldData, newData);
}
  • privateGetDeclaredMethods() 方法中如果通过 reflectionData() 方法获得的 ReflectionData 数据对象不为空,则尝试从 ReflectionData 数据对象中获取 declaredMethods 属性。
if (rd != null) {
      res = publicOnly ? rd.declaredPublicMethods : rd.declaredMethods;
      if (res != null) return res;
}
  • 如果是第一次创建 ReflectionData 数据对象或者 ReflectionData 对象已被 GC 回收过,重新初始化后的类属性为空,则需要重新到 Java 虚拟机中获取一次,并赋值给 ReflectionData,便于下次调用使用缓存数据。
// No cached value available; request value from VM
res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly));
if (rd != null) {
        if (publicOnly) {
             rd.declaredPublicMethods = res;
         } else {
             rd.declaredMethods = res;
         }
}

3.2 Method 的调用

  • 获取到指定的方法对象(Method)后,调用执行 invoke() 方法。
  • 调用 quickCheckMemberAccess() 方法进行一些权限检查。
@CallerSensitive
public Object invoke(Object obj, Object... args)
        throws IllegalAccessException, IllegalArgumentException,
           InvocationTargetException
{
        if (!override) {
            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
                Class<?> caller = Reflection.getCallerClass();
                checkAccess(caller, clazz, obj, modifiers);
            }
        }
        MethodAccessor ma = methodAccessor;             // read volatile
        if (ma == null) {
            ma = acquireMethodAccessor();
        }
        return ma.invoke(obj, args);
}
  • 实际最终执行的是 MethodAccessor 对象的 invoke() 方法。acquireMethodAccessor() 方法可以生成 MethodAccessor 对象。
private MethodAccessor acquireMethodAccessor() {
        // First check to see if one has been created yet, and take it
        // if so
        MethodAccessor tmp = null;
        if (root != null) tmp = root.getMethodAccessor();
        if (tmp != null) {
            methodAccessor = tmp;
        } else {
            // Otherwise fabricate one and propagate it up to the root
            tmp = reflectionFactory.newMethodAccessor(this);
            setMethodAccessor(tmp);
        }

        return tmp;
}
  • 判断是否存在对应的 MethodAccessor 对象,如果存在则复用,否则调用 ReflectionFactory 对象的 newMethodAccessor() 方法生成一个 MethodAccessor 对象。

    • 其中 noInflation 为关闭 Inflation 机制,可通过 -Dsun.reflect.noInflation=true 设置。
public MethodAccessor newMethodAccessor(Method var1) {
        checkInitted();
        if (noInflation && !ReflectUtil.isVMAnonymousClass(var1.getDeclaringClass())) {
            return (new MethodAccessorGenerator()).generateMethod(var1.getDeclaringClass(), var1.getName(), var1.getParameterTypes(), var1.getReturnType(), var1.getExceptionTypes(), var1.getModifiers());
        } else {
            NativeMethodAccessorImpl var2 = new NativeMethodAccessorImpl(var1);
            DelegatingMethodAccessorImpl var3 = new DelegatingMethodAccessorImpl(var2);
            var2.setParent(var3);
            return var3;
        }
}
  • 如果使用了 Inflation 机制(noInflation = false),那么这里的实现使用了代理模式,将 NativeMethodAccessorImpl 对象交给 DelegatingMethodAccessorImpl 对象代理。
class DelegatingMethodAccessorImpl extends MethodAccessorImpl {
    private MethodAccessorImpl delegate;

    DelegatingMethodAccessorImpl(MethodAccessorImpl var1) {
        this.setDelegate(var1);
    }

    public Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException {
        return this.delegate.invoke(var1, var2);
    }

    void setDelegate(MethodAccessorImpl var1) {
        this.delegate = var1;
    }
}
  • 那么 MethodAccessor 调用的 invoke() 方法,实际调用了 DelegatingMethodAccessorImpl 对象的 invoke() 方法,最终调用了被代理的 NativeMethodAccessorImpl 对象的 invoke() 方法。

    • NativeMethodAccessorImpl 对象的 invoke() 方法中会判断调用次数是否超过阀值(numInvocations)。
    • 如果超过该阀值,会生成另外一个 MethodAccessor 对象,并将原来 DelegatingMethodAccessorImpl 对象中的 delegate 属性指向最新的 MethodAccessor 对象。
    • numInvocations 默认为 15,可以通过 -Dsun.reflect.inflationThreshold= 设置次数。
private static int inflationThreshold = 15;
......
class NativeMethodAccessorImpl extends MethodAccessorImpl {
    private final Method method;
    private DelegatingMethodAccessorImpl parent;
    private int numInvocations;

    NativeMethodAccessorImpl(Method var1) {
        this.method = var1;
    }

    public Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException {
        if (++this.numInvocations > ReflectionFactory.inflationThreshold() && !ReflectUtil.isVMAnonymousClass(this.method.getDeclaringClass())) {
            MethodAccessorImpl var3 = (MethodAccessorImpl)(new MethodAccessorGenerator()).generateMethod(this.method.getDeclaringClass(), this.method.getName(), this.method.getParameterTypes(), this.method.getReturnType(), this.method.getExceptionTypes(), this.method.getModifiers());
            this.parent.setDelegate(var3);
        }

        return invoke0(this.method, var1, var2);
    }

    void setParent(DelegatingMethodAccessorImpl var1) {
        this.parent = var1;
    }

    private static native Object invoke0(Method var0, Object var1, Object[] var2);
}
  • 实际的 MethodAccessor 接口实现有两个版本,一个是 Native 版本,一个是 Java 版本。

    • Native 版本的实现是 NativeMethodAccessorImpl 对象。
    • Java 版本的实现是 MethodAccessorImpl。

Inflation 机制

  • 初次加载字节码实现反射,使用 Method.invoke()Constructor.newInstance() 加载花费的时间是使用原生代码加载花费时间的 3 - 4 倍,这使得那些频繁使用反射的应用需要花费更长的启动时间。
  • 为了避免这种痛苦的加载时间,第一次加载的时候重用了 Java 虚拟机的入口,之后再切换到字节码实现的实现。

  • Native 版本一开始启动很快,随着运行时间变长,速度变慢。
  • Java 版本一开始加载慢,随着运行时间变长,速度变快。
  • 所以当第一次加载时会发现使用的是 NativeMethodAccessorImpl 对象的实现,当反射调用次数超过 15(numInvocations) 次之后,则使用 MethodAccessorGenerator 生成的 MethodAccessorImpl 对象去实现反射。
    • generateMethod() 方法在生成 MethodAccessorImpl 对象时,会在内存中生成对应的字节码,并调用 ClassDefiner.defineClass() 创建对应的 class 对象。
return (MagicAccessorImpl)AccessController.doPrivileged(new PrivilegedAction<MagicAccessorImpl>() {
                public MagicAccessorImpl run() {
                    try {
                        return (MagicAccessorImpl)ClassDefiner.defineClass(var13, var17, 0, var17.length, var1.getClassLoader()).newInstance();
                    } catch (IllegalAccessException | InstantiationException var2) {
                        throw new InternalError(var2);
                    }
                }
});
  • ClassDefiner.defineClass() 方法实现中,每被调用一次都会生成一个 DelegatingClassLoader 类加载器对象。

    • 每次生成新的类加载器是为了性能考虑(从设计来看,本身不希望这些类一直存在于内存当中,在需要的时候存在即可)。

      • 在某些情况下可以直接卸载这些生成的类,因为类的卸载是只有在类加载器可以被回收的情况下才会被回收的,如果使用原来的类加载器,可能导致这些新创建的类一直无法被卸载。
static Class<?> defineClass(String var0, byte[] var1, int var2, int var3, final ClassLoader var4) {
        ClassLoader var5 = (ClassLoader)AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
            public ClassLoader run() {
                return new DelegatingClassLoader(var4);
            }
        });
        return unsafe.defineClass(var0, var1, var2, var3, var5, (ProtectionDomain)null);
}
  • invoke() 方法的内部使用了代理的设计模式来实现最大化性能。

参考资料

https://www.cnblogs.com/chanshuyi/p/head_first_of_reflection.html
http://www.importnew.com/23902.html
http://www.importnew.com/23560.html
http://www.importnew.com/21211.html

原文地址:https://www.cnblogs.com/youngao/p/12576512.html

时间: 2024-10-28 23:51:41

Java 反射相关整理的相关文章

Java 泛型相关整理

1. 概述 Java 泛型(generics)是 JDK 5 中引入的一个新特性,泛型提供了 编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型. 泛型,即 参数化类型.将类型由原来的具体的类型(类似于方法的变量参数,该变量定义了具体的类型),也定义成参数形式(可以称之为类型形参),然后在使用/调用时再传入具体的类型(类型实参). 泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型). 在泛型使用过程中,操作的数据类型被指定为一个参

Java反射相关-通过class得到一个类的全部架构

package com.huawei.pia; import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Modifier; public class Person extends SuperClass1 implements Inter1,Inter2 { private String name; private int age;  public Person(Str

粗浅看 java反射机制

什么是  Java 反射是 Java 被视为动态(或准动态)语言的一个关键性质.这个机制允许程序在运 行时透过 Reflection APIs 取得任何一个已知名称的class 的内部信息,包括其 modifiers( 诸如 public, static 等 ).superclass (例如 Object). 实现之 interfaces(例如 Cloneable),也包括 fields 和 methods 的所有信息,并可于运行时改变 fields 内容或唤起 methods. Java 反射

Java反射机制大神必学系列之 ,高级与低级的差别在哪里?

Java反射机制大神必学系列之 ,高级与低级的差别在哪里?java学习爱好者 2019-05-20 19:08前言今天介绍下Java的反射机制,以前我们获取一个类的实例都是使用new一个实例出来.那样太low了,今天跟我一起来学习学习一种更加高大上的方式来实现. 正文Java反射机制定义 Java反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制.

Java反射

1. 介绍 反射是一种能够在程序运行时动态访问.修改某个类中任意属性和方法的机制. 具体:对于任意一个类,都能够知道这个类的所有属性和方法对于任意一个对象,都能够调用它的任意一个方法和属性 在运行时,当加载完类之后,JVM在堆内存中会自动产生一个Class类型的对象,这个对象包含了完整的类的结构信息 这个Class对象就像一面镜子,透过这个镜子看到类的结构 那么,如何得到这个Class对象呢?以下可否 Class c = new Class(); 答案是不行的,因为Class的构造函数定义为私有

JAVA基础知识整理 常用框架

JAVA反射---相关资料: 1.Java反射机制可以让我们在编译期(Compile Time)之外的运行期(Runtime)检查类,接口,变量以及方法的信息 2.反射还可以让我们在运行期实例化对象,调用方法,通过调用get/set方法获取变量的值. 参考框架:Butterfly Persistence 构建 这里搜集了用来构建应用程序的工具. Apache Maven:Maven使用声明进行构建并进行依赖管理,偏向于使用约定而不是配置进行构建.Maven优于Apache Ant.后者采用了一种

java基础知识(十一)java反射机制(下)

1.什么是反射机制? java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用他的属性和方法,这种动态获取属性和方法的功能称为java的反射机制. 也就是说,java程序可以加载一个运行时才得知名称的class,获悉该类的完整构造(但不包括methods定义),并生成其对象实体,或对其fields设值,或唤起其methods.总之,就是JVM可以在运行时加载.探知.使用编译期完全未知的classes. 2.jdk提供的反射api Java反射相

非常好的Java反射例子

1.Java反射的概念 反射含义:可以获取正在运行的Java对象. 2.Java反射的功能 1)可以判断运行时对象所属的类 2)可以判断运行时对象所具有的成员变量和方法 3)通过反射甚至可以调用到private的方法 4)生成动态代理 3.实现Java反射的类 1)Class:它表示正在运行的Java应用程序中的类和接口 2)Field:提供有关类或接口的属性信息,以及对它的动态访问权限 3)Constructor:提供关于类的单个构造方法的信息以及对它的访问权限 4)Method:提供关于类或

浅说Java反射机制

工作中遇到,问题解决: JAVA语言中的反射机制: 在Java 运行时 环境中,对于任意一个类,能否知道这个类有哪些属性和方法? 对于任意一个对象,能否调用他的方法?这些答案是肯定的,这种动态获取类的信息,以及动态调用类的方法的功能来源于JAVA的反射.从而使java具有动态语言的特性. JAVA反射机制主要提供了以下功能: 1.在运行时判断任意一个对象所属的类 2.在运行时构造任意一个类的对象 3.在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法) 4.在运