什么是反射
在程序动态运行时,动态加载并获取类的信息,从而操作类的属性和方法,本质是通过JVM的class对象的反编译,获取类的各种信息,不关注对象是谁
原理
优缺点
优点:
- 方便灵活
缺点:
- 消耗系统资源
- 可以忽略权限检查,破坏安全性
反射优化
如何提高反射性能:
- 通过setAccessible(true)关闭JDK的安全检查来提升反射速度
- 多次创建一个类的实例时,有缓存会快很多
- ReflflectASM工具类,通过字节码生成的方式加快反射速度
反射应用场景
- spring的AOP
- 动态加载mysql驱动
反射机制常用的类
- Java.lang.Class;
- Java.lang.reflect.Constructor;
- Java.lang.reflect.Field;
- Java.lang.reflect.Method;
- Java.lang.reflect.Modifier;
基本使用
1、Java.lang.Class;
public class ClassTest {
public static void main(String[] args) throws ClassNotFoundException{
Person person = new Student();
System.out.println("这个人是"+person.name);
//方式一:通过对象获得
Class c1 = person.getClass();
System.out.println(c1.hashCode());///result: 2101842856
//方式二:forName获得
Class c2 = Class.forName("com.jasmine.reflect.Student");
System.out.println(c2.hashCode());///result: 2101842856
//方式三:通过类名.Class获得
Class c3 = Student.class;
System.out.println(c3.hashCode());///result: 2101842856
//方式四:基本内置类型的包装类都有一个Type属性
Class c4 = Integer.TYPE;
System.out.println(c4.hashCode());///result: 1151020327
//获得父类
Person person1 = new Person();
Class superclass1 = c1.getSuperclass();
Class c5 = person1.getClass();
System.out.println(superclass1.hashCode());///result: 1225616405
System.out.println(c5.hashCode());///result: 1225616405
}
}
class Person{
public String name;
public Person() {
}
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
class Student extends Person{
public Student(){
this.name = "学生";
}
}
class Teacher extends Person{
public Teacher(){
this.name="老师";
}
}
Java.lang.reflect.Constructor;
public class ConstructorTest {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
/**
* 1、创建对象
*/
Class personClazz = Class.forName("com.jasmine.reflect.dto.Person");//通过【Class.forName】创建Person对象
/**
* 2、获得类名
*/
System.out.println("=============================获得类的名字");
System.out.println(personClazz.getName()); //获取类的完整名字(即:包名+类名),结果为:reflection.User
System.out.println(personClazz.getSimpleName()); //获取类的简单名字(即:类名),结果为:User
System.out.println(personClazz.getSuperclass()); //获取父类
System.out.println(personClazz.getSuperclass().getName()); //获取父类
System.out.println(personClazz.getInterfaces()); //获取接口
System.out.println(personClazz.getAnnotations()); //获取注解
Class<?> aClass = Class.forName(personClazz.getSuperclass().getName());
Constructor<?>[] constructors1 = aClass.getConstructors();
for (Constructor constructor : constructors1) {
System.out.println("获得父类的构造器"+constructor);
}
System.out.println("=============================获得构造器");
Constructor[] constructors = personClazz.getConstructors();
for (Constructor constructor : constructors) {
System.out.println("获得public的构造器"+constructor);
}
Constructor[] declaredConstructors = personClazz.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println("获得任意范围的构造器"+declaredConstructor);
}
}
}
Java.lang.reflect.Field;
public class FieldTest {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
/**
* 1、创建对象
*/
Class c1 = Class.forName("com.jasmine.reflect.dto.Person");//通过【Class.forName】创建Person对象
System.out.println("=============================获得类的所有public属性");
Field[] fields = c1.getFields();
for (Field f1 : fields) {
System.out.println(f1); //结果为:只获得了Person类中的oublic属性
}
System.out.println("==============================获得类的所有任意属性");
Field[] declaredFields = c1.getDeclaredFields(); //注:getDeclaredFields有s
for (Field f2 : declaredFields) {
System.out.println(f2); //结果为:获得了Person类中的所有属性
}
System.out.println("=============================获得类的某个public属性");
Field wangming = c1.getField("id");
System.out.println(wangming);
System.out.println("=============================获得类的某个任意属性");
Field name = c1.getDeclaredField("name");
System.out.println(name);
com.jasmine.reflect.dto.Person person = (com.jasmine.reflect.dto.Person) c1.newInstance();
name.setAccessible(true);
name.set(person, "张三");
System.out.println(person.getName());
}
}
Java.lang.reflect.Method;
public class MethodTest {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
/**
* 1、创建对象
*/
Class c1 = Class.forName("com.jasmine.reflect.dto.Person");//通过【Class.forName】创建Person对象
/**
* 4、获得类的方法
*/
System.out.println("=============================获得类的所有方法");
Method[] ms = c1.getMethods();
for (Method m : ms){
System.out.println(m); //获得和本类和父类的所有public方法:equals、toString、hashCode、get&set、notify、notifyAll
}
//又是相见恨晚哪!!!先实战用了,才在视频里学到这个。
System.out.println("=============================获得指定方法");
//前一个参数是方法名,后一个参数是方法需要传入的参数的类型(没有就填null)。要抛出异常
Method getName = c1.getMethod("getName", null);
Method setName = c1.getMethod("setName", String.class);
System.out.println(getName);
System.out.println(setName);
System.out.println("=============================执行指定方法");
Method walk = c1.getMethod("walk", String.class);
com.jasmine.reflect.dto.Person person = (com.jasmine.reflect.dto.Person) c1.newInstance();
walk.invoke(person,"哈哈");
}
}
Java.lang.reflect.Modifier;
public class ModifierTest {
public static void main(String[] args) throws ClassNotFoundException {
Class c1 = Class.forName("com.jasmine.reflect.dto.Person");//通过【Class.forName】创建Person对象
Method[] methods = c1.getMethods();
System.out.println("=============方法展示=============");
for (Method method : methods) {
System.out.println("方法名:" + method.getName());
System.out.println("返回值类型:"+method.getReturnType().getName());
Class[] params = method.getParameterTypes();
if (params.length == 0) {
System.out.println("该方法没有参数");
}else {
System.out.print("该方法的参数类别为:[");
for (int i = 0; i < params.length; i++) {
if (i != 0) {
System.out.print(", ");
System.out.print(params[i].getName());
}
}
System.out.println("]");
System.out.println("-----------------------------------");
}
int modifier = method.getModifiers();
if ((modifier & Modifier.STATIC) == Modifier.STATIC) {
System.out.println("这是一个静态方法");
}
if ((modifier & Modifier.FINAL) == Modifier.FINAL) {
System.out.println("这是一个FINAL方法");
}
if ((modifier & Modifier.ABSTRACT) == Modifier.ABSTRACT) {
System.out.println("这是一个抽象方法");
}
if ((modifier & Modifier.SYNCHRONIZED) == Modifier.SYNCHRONIZED) {
System.out.println("这是一个同步方法");
}
Class declaringClass = method.getDeclaringClass();
System.out.println("方法声明在:"+declaringClass.getName()+"中");
Class[] exceptions = method.getExceptionTypes();
if (exceptions.length > 0) {
System.out.println("该方抛出的异常有:[");
for (int i = 0; i < exceptions.length; i++) {
if (i != 0) {
System.out.println(", ");
System.out.println(exceptions[i].getName());
}
System.out.println("]");
}
System.out.println("-------------------------------");
}
}
}
}
泛型获取
public class MethodTest {
//定义一个需要传入泛型参数的方法
public void test01(Map<String, Person> map, List<Person> list) {
System.out.println("test01");
}
//定义一个返回泛型的方法
public Map<String, SecurityProperties.User> test02() {
System.out.println("test02");
return null;
}
public static void ttt() throws NoSuchMethodException {
Method method = MethodTest.class.getMethod("test01", Map.class, List.class);
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println("泛型的样子是:" + genericParameterType);
}
}
}
result:
泛型的样子是:java.util.Map<java.lang.String, com.jasmine.reflect.Person>
泛型的样子是:java.util.List<com.jasmine.reflect.Person>
注解获取
public class Test10 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class c1 = Class.forName("com.jdsydwr.reflection.Student2");
//通过反射获得注解
Annotation[] annotations = c1.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
//获取注解的value
TableName tableName = (TableName)c1.getAnnotation(TableName.class);
String value = tableName.value();
System.out.println(value);
//获取类指定的注解
Field f = c1.getDeclaredField("Name");
FieldName annotation = f.getAnnotation(FieldName.class);
System.out.println(annotation.columnName());
System.out.println(annotation.type());
System.out.println(annotation.length());
}
}
@TableName("db_student")
class Student2{
@FieldName(columnName = "db_id",type = "int",length = 10)
private int id;
@FieldName(columnName = "db_age",type = "int",length = 10)
private int age;
@FieldName(columnName = "db_name",type = "String",length = 3)
private String Name;
public Student2() {
}
public Student2(int id, int age, String name) {
this.id = id;
this.age = age;
Name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
@Override
public String toString() {
return "Student2{" +
"id=" + id +
", age=" + age +
", Name='" + Name + '\'' +
'}';
}
}
//类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TableName{
String value();
}
//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FieldName{
String columnName();
String type();
int length();
}
new实例
public class InstanceTest {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchFieldException {
Class clz = Class.forName("entity.Person");
Constructor cl = clz.getDeclaredConstructor();
Object obj = cl.newInstance();
Constructor c3 = clz.getDeclaredConstructor(String.class,String.class,String.class);
c3.setAccessible(true);
obj = c3.newInstance("new Person", "beijing", "Hello");
System.out.println(obj);
Object person = clz.newInstance();
Field name = clz.getDeclaredField("name");
name.setAccessible(true);
name.set(person,"张三");
System.out.println("赋值后的 name:" +name.get(person));
}
}
获取final属性值
public class Person extends Animal implements Fly {
private final String food="cookie";
public String getFood() {
return food;
}
}
public class FieldTest {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
System.out.println("=============================获取final属性");
Field food = c1.getDeclaredField("food");
System.out.println("111" + food);
com.jasmine.reflect.dto.Person person2 = (com.jasmine.reflect.dto.Person) c1.newInstance();
food.setAccessible(true);
food.set(person2, "面包");
System.out.println("222" + person2.getFood());///222cookie
System.out.println("333" + food.get(person2));///333面包
}
}