反射用来生成JVM中的类、接口或者对象的信息
-
Field类:java.lang.reflect.Field,表示类的成员变量,可以用来获取和设置类之中的属性值。
-
Method类:java.lang.reflect.Method,表示类的方法,可以用来获取类中的方法信息或者执行方法。
-
Constructor类:java.lang.reflect.Constructor,表示类中的构造方法。
5、反射的使用步骤
-
获取想要 *** 作的类的class对象,它是反射的核心,通过class对象我们可以任意调用类的方法。
-
调用class类中的方法,就是反射的使用阶段
-
使用反射API来 *** 作这些信息
6、获取class对象的4种方法
- 调用某个对象的getClass()方法
Person person = new Student();
Class clazz = person.getClass();
- 调用某个类的class属性来获取该类对应的class对象
Class clazz = Student.class;
- 使用class类中的forName()静态方法(最常用|最安全|性能最高)
Class clazz = Class.forName(“类的全路径”);
- 使用类加载器获取
// Xxx为与需要获取类信息的类同级别的类加载器。类加载器的选择,要符合双亲委派机制
Class> clazz = Xxx.class.getClassLoader().loadClass(“类的全路径”);
当我们获得了想要 *** 作的类的Class的对象后,可以通过Class类中的方法获取并查看该类中的方法和属性
try {
// 获取Person的Class对象
Class> clazz = Class.forName(“com.liziba.reflect.Person”);
// 获取Person类的所有成员属性信息
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
// 获取Person类的所有方法信息
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
// 获取Person类的所有构造方法信息
Constructor>[] constructors = clazz.getDeclaredConstructors();
for (Constructor> constructor : constructors) {
System.out.println(constructor);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
7、创建对象的两种方法
- Class对象的newInstance()
// 使用Class对象的newInstance()方法来创建该Class对象对应类的实例,但是这种方法要求该Class对象对应的类有默认的空构造器
Person person = (Person)clazz.
《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》
【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享
newInstance();
// newInstance()方法的本质,仍然是下面的情况,只是传入的参数是(Object[])null
try {
return tmpConstructor.newInstance((Object[])null);
} catch (InvocationTargetException e) {
Unsafe.getUnsafe().throwException(e.getTargetException());
return null;
}
- 调用Constructor的newInstance()
// 先使用Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方发来创建Class对象对应类的实例,通过这种方法可以选定指定构造方法创建实例
Constructor> constructor = clazz.getConstructor(String.class, int.class, String.class, int.class);
constructor.newInstance(“李子捌”, 1, “深圳宝安”, 23);
8、反射到底慢在哪里
-
寻找类Class字节码的过程
-
安全机制的权限校验
-
可能需要调用native方法时调用JNI接口
// 安全机制校验,Field/Method/Constructor
private void checkMemberAccess(int which, Class> caller, boolean checkProxyInterfaces){
final SecurityManager s = System.getSecurityManager();
if (s != null) {
final ClassLoader ccl = ClassLoader.getClassLoader(caller);
final ClassLoader cl = getClassLoader0();
if (which != Member.PUBLIC) {
if (ccl != cl) {
s.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
}
}
this.checkPackageAccess(ccl, checkProxyInterfaces);
}
}
9、反射单例模式的漏洞
简单单例
public class SingletonFactory {
private volatile static SingletonFactory singletonFactory = null;
private SingletonFactory() {
}
public static SingletonFactory getInstance() {
if(singletonFactory == null) {
synchronized (SingletonFactory.class) {
if(singletonFactory == null) {
singletonFactory = new SingletonFactory();
}
}
}
return singletonFactory;
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)