标签:ace java static 形式 ++ util style tmp 编译
获取 Class 类对象的三种方法
Class clz = Class.forName("java.lang.String");
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() | 返回该类的类加载器。 |
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);
要动态获取一个对象方法的信息,需要创建一个 Method 类型的对象或者数组。
如果是访问指定的构造方法,需要根据该方法的入口参数的类型来访问。
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); }
通过方法访问成员变量时将返回 Field 类型的对象或数组。
返回的 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"); }
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); }
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.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; }
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); }
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; } }
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; }
// 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; } }
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); }
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; }
newMethodAccessor()
方法生成一个 MethodAccessor 对象。
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; } }
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; } }
invoke()
方法,实际调用了 DelegatingMethodAccessorImpl 对象的 invoke()
方法,最终调用了被代理的 NativeMethodAccessorImpl 对象的 invoke()
方法。
invoke()
方法中会判断调用次数是否超过阀值(numInvocations)。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); }
Inflation 机制
Method.invoke()
和 Constructor.newInstance()
加载花费的时间是使用原生代码加载花费时间的 3 - 4 倍,这使得那些频繁使用反射的应用需要花费更长的启动时间。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
标签:ace java static 形式 ++ util style tmp 编译
原文地址:https://www.cnblogs.com/youngao/p/12576512.html