1、什么是反射?
反射是运行之间把类中的成员抽取为其它类的过程。
2、为什使用反射?
反射是为了解决在运行期,对某个实例一无所知的情况下,如何调用其方法或属性。
3、反射的应用场景?
idea通过反射获取类中所有的method方法对象以提示框的形式列出
jdbc对数据库的操作
mybatis中
spring容器根据传入的类路径创建对象
工厂模式中的简单工厂模式优化
代理模式中的动态代理方式实现
4、获取Class反射类的三种方式
//通过类直接获取反射类
Class<People> peopleClass = People.class;
//通过类路径获取反射类
Class<?> aClass = Class.forName("com.tian.entity.People");
//通过对象获取反射类
People people = new People();
Class<? extends People> aClass1 = people.getClass();
5、Class.newInstance()和Constructor.newInstance() 的区别
class.newInstance()方法自9被弃用了
@CallerSensitive
@Deprecated(since="9")
public T newInstance()
throws InstantiationException, IllegalAccessException
{
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), false);
}
// Constructor lookup
Constructor<T> tmpConstructor = cachedConstructor;
if (tmpConstructor == null) {
if (this == Class.class) {
throw new IllegalAccessException(
"Can not call newInstance() on the Class for java.lang.Class"
);
}
try {
Class<?>[] empty = {};
final Constructor<T> c = getReflectionFactory().copyConstructor(
getConstructor0(empty, Member.DECLARED));
// Disable accessibility checks on the constructor
// access check is done with the true caller
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<>() {
public Void run() {
c.setAccessible(true);
return null;
}
});
cachedConstructor = tmpConstructor = c;
} catch (NoSuchMethodException e) {
throw (InstantiationException)
new InstantiationException(getName()).initCause(e);
}
}
try {
Class<?> caller = Reflection.getCallerClass();
return getReflectionFactory().newInstance(tmpConstructor, null, caller);
} catch (InvocationTargetException e) {
Unsafe.getUnsafe().throwException(e.getTargetException());
// Not reached
return null;
}
}
通过该方法只能创建无参的对象实例
Constructor.newInstance()方法是JDK9以及更高版本使用的,该方法根据构造函数创建对象实例,可以根据任意的构造函数创建对象。
Class.newInstance()和Constructor.newInstance()的用法:
//jdk 8版本以后过时了
People people1 = peopleClass.newInstance();
System.out.println(people1);
//通过无参构造器创建对象实例
Constructor<People> constructor = peopleClass.getConstructor();
People people2 = constructor.newInstance();
System.out.println(people2);
//有参构造器创建对象实例
Constructor<People> constructor1 = peopleClass.getConstructor(String.class,
LocalDate.class);
People people3 = constructor1.newInstance("Run",LocalDate.now());
System.out.println(people3);
6、如何通过反射获取类上面的注解
//获取该类上的所有注解对象
Annotation[] annotations = peopleClass.getAnnotations();
System.out.println(annotations);
//通过注解类型获取注解类对象
MyAnnotation annotation = peopleClass.getAnnotation(MyAnnotation.class);
System.out.println(annotation.value());
7、如何通过反射获取 Method方法类对象
//获取该类中所有方法的对象
Method[] declaredMethods = peopleClass.getDeclaredMethods();
for (Method m:declaredMethods) {
System.out.println(m);
}
//通过方法名和参数类型获取该类指定的方法对象
Method getName = peopleClass.getDeclaredMethod("getName");
System.out.println("==============getName=================");
System.out.println(getName);
//获取自己和长辈中所有的public的方法对象
Method[] methods = peopleClass.getMethods();
System.out.println("============getMethods====================");
for (Method m:methods) {
System.out.println(m);
}
//通过方法名和参数获取自己和长辈中指定的public的方法对象
//注意:【People类没有重写equals方法】
Method equals = peopleClass.getMethod("equals",Object.class);
System.out.println("=================equals======================");
System.out.println(equals);
8、Method类对象中常用的方法
//?代表通配符
Class<?> aClass = Class.forName("com.tian.entity.People");
Constructor<?> constructor = aClass.getConstructor();
Object o = constructor.newInstance();
//通过getMethod()方法获取到setName方法对象,再通过invoke()方法执行setName方法为属性赋值
//Object invoke(Object obj, Object... args) 其中invoke(创建的实例对象,参数) ...代表
//着可变参数
aClass.getMethod("setName", String.class).invoke(o, "tian");
//通过getMethod()方法获取到getName方法对象,再通过invoke()方法执行getName方法获取属性的值
System.out.println(aClass.getMethod("getName").invoke(o));
System.out.println(aClass.getDeclaredMethod("getName").invoke(o));
//注意:【show方法是无参无返回值私有方法】
Method show = aClass.getDeclaredMethod("show");
//设置可以访问私有方法
show.setAccessible(true);
show.invoke(o);
9、如何通过反射获取Field属性对象的方式
//获取该类的所有属性对象
Field[] declaredFields = peopleClass.getDeclaredFields();
//获取本类指定的属性对象
Field name = peopleClass.getDeclaredField("name");
//获取该类和长辈中所有public修饰的属性对象
Field[] fields = peopleClass.getFields();
//获取该类和长辈中指定的public修饰的属性对象
Field name1 = peopleClass.getField("name");
10、Field类中常用的方法
for (Field f:declaredFields) {
//String getName() 获取属性名
System.out.println(f.getName());
//<T extends Annotation> T getAnnotation(Class<T> annotationClass) 获取对象中的
//注解对象
MyAnnotation annotation = f.getAnnotation(MyAnnotation.class);
System.out.println(annotation.value());
}
name.setAccessible(true);
//void set(Object obj, Object value) 为属性赋值 obj是创建的实例对象 value要赋的值
name.set(people,"tian");
System.out.println(name.get(people));