一、反射是什么?

Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。

二、反射的优缺点

1、优点:在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。
2、缺点:
(1)反射会消耗一定的系统资源,因此如果不需要动态地创建一个对象,那么就不需要用反射;
(2)反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。

三、反射的api

3.1、反射类

  • Class类: 代表类的实体,在运行的Java应用程序中表示类和接口
  • Field类: 代表类的成员变量(成员变量也称为类的属性)
  • Method类: 代表类的方法
  • Constructor 类: 代表类的构造方法

3.2、反射方法

  • getField : 获取指定字段
  • getMethod : 获取指定方法
  • getCostructor :获取指定构造器
  • getFields :获得类中的所有 public 字段(包括父类)
  • getMethods :获得类中的所有 public 方法 (包括父类)
  • getCostructors :获得类中的所有 public 构造器数 (包括父类)
  • getDeclatedFields : 获得类中的所有字段 (包括 private 不包括父类)
  • getDeclatedMethods : 获得类中的所有方法 (包括 private 不包括父类)
  • getDeclaredConstructors : 获得类中的所有构造器 (包括 private 不包括父类)
  • getName() : 获取方法名 / 字段名(作用于 Method / Field)
  • getReturnType() : 获取方法返回值 (作用于 Method)
  • getParameterTypes() : 获取传入参数 (作用于 Method)
  • setAccessible(true) : 允许访问私有成员(设置在 Field 字段上)

四、反射的 3种创建反射

//  第一种方式(类的全路径):  
	Class c1 = Class.forName("Employee");  
		
	// 第二种方式(.calss):  
	// java中每个类型都有class 属性.  
	Class c2 = Employee.class;  
		   
	// 第三种方式( 类.getCalss()):  
	// java语言中任何一个java对象都有getClass 方法 ,c3是运行时类 (e的运行时类是Employee) 
     Employee e = new Employee();  
	Class<?>  c3 = e.getClass();

五、使用示例

5.1、反射给实体类赋值

Class<?> forName = Class.forName("class_demo.User");
		// 创建此Class 对象所表示的类的一个新实例 调用了User的.
		Object newInstance = forName.newInstance();
		User user1 = (User) newInstance;
		user1.setUsername("阿英");
		user1.setAge(1);
		System.out.println(user1.toString()+"----反射--无参数构造创建user实列");

5.2、反射调用有参构造方法

Class<?> forName2 = Class.forName("class_demo.User");
		// 调用了User的有参数构造方法.  参数对应有参构造器的参数的数据类型.class ,必须按顺序
		Constructor<?> constructor2 = forName2.getConstructor(String.class, Integer.class);
		Object newInstance2 = constructor2.newInstance("阿瑶",1);
		User user2 = (User) newInstance2;
		System.out.println(user2.toString()+"----反射--有参数构造创建user实列");

5.3、反射给私有属性赋值

// 获取当前类class地址
	 Class<?> forName3 = Class.forName("class_demo.User");
	// 使用反射实例化对象 无参数构造函数
	Object newInstance3 = forName3.newInstance();
	// 获取当前类的 username,age字段
	Field username = forName3.getDeclaredField("username");
	Field age = forName3.getDeclaredField("age");
	// 允许操作私有成员
	username.setAccessible(true);
	age.setAccessible(true);
	// 设置值
	username.set(newInstance3, "ws_兮");
	age.set(newInstance3, 19);
	User user3 = (User) newInstance3;
	System.out.println(user3.toString()+"----反射给私有属性赋值");

5.4、反射获取该类的所有方法

// 获取当前类class地址
	Class<?> forName4 = Class.forName("class_demo.User");
	//本类所有方法
	Method[] declaredMethods = forName4.getDeclaredMethods();
	//遍历
	for(Method de : declaredMethods) {
	     //打印方法名及返回值类型
		 System.out.println(de.getName()+"--"+de.getReturnType());
	}

5.5、反射获取该类的所有属性

Class<?> forName6 = Class.forName("class_demo.User");
	 Field[] declaredFields = forName6.getDeclaredFields();
	 for(Field de : declaredFields) {
		  System.out.println(de.getName());
	 }