JAVA反射机制介绍和动态操作

反射机制介绍

反射机制是java的动态性之一
动态性:在程序运行时,可以改变程序的结构和变量的类型。

典型的动态语言“Python、ruby、javaScript”

C,C++,Java不是动态语言,但具有一定的动态性,可以成为“准动态语言”,具备类似动态语言的特性。传一块代码来动态的执行,动态的处理,java也能做,可以利用反射来实现类似的功能。java的动态性让编程变得更加灵活,功能就更加的强大。

反射机制
程序在运行的过程中加载一些“只知道相关名字”的类,以下代码在程序运行时加载User类:Class c = Class.forName(“com.weini.User”);
一个类被加载后,JVM会创建一个对应类的Class对象,类的整个结构信息会被放到Class对象中。这个Class对象就像镜子一样,通过这面镜子,可以得到对应类的全部信息。

反射机制的常见作用

  1. 动态的加载类、动态的获取类的信息(属性,方法,构造器)
  2. 动态构造对象
  3. 动态调用类和对象的任意方法、构造器
  4. 动态调用和处理属性
  5. 获取泛型信息
  6. 处理注解

获取Class对象的方式

  1. 通过字节码文件
  2. 对象的getClass()方法
  3. Class类的静态方法forName(…)
import come.weini.User;

public class Test {
	public static void main(String[] args) throws ClassNotFoundException {
		System.out.println(int.class);
		System.out.println(void.class);
		int []arrA=new int[10];
		int[] arrB=new int[30];
		/**维数相同和类型相同的数组共享同一个Class对象*/
		System.out.println(arrA.getClass()==arrB.getClass());
		
		/**同一个类的N多对象,共享同一个Class对象*/
		User u1=new User();
		User u2=new User();
		System.out.println(u1.getClass()==u2.getClass());
		
		
		/**获取Class对象的三种方式*/
		//(1)通过对象的getClass()方法获取
		Class c1=u1.getClass();
		//(2)通过字节码文件获取
		Class c2=User.class;
		//(3)通过Class类的静态方法获取
		Class c3=Class.forName("com.weini.User");
		System.out.println((c1==c2)+"\t"+(c1==c3));
		
		
	}
}
public class User {
	//类的属性
	private int userId;
	private String userName;
	private String password;
	//公有的取值,赋值方法
	public int getUserId() {
		return userId;
	}
	public void setUserId(int userId) {
		this.userId = userId;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	//构造方法
	public User() {
		// TODO Auto-generated constructor stub
	}
	public User(int userId, String userName, String password) {
		super();
		this.userId = userId;
		this.userName = userName;
		this.password = password;
	}
	
	
}
反射机制动态操作

获取类的名字

序号 方法 描述
1 String getName() 获取包名+类名
2 String getSimpleName() 获取类的名字

获取类的属性

序号 方法 描述
1 Field getField(String fieldName) 得到公共的属性对象
2 Field getDeclareField(String fieldName) 得到指定名称的属性对象
3 Field [] c.getDeclaredFields() 得到所有的属性对象

获取类的方法

序号 方法 描述
1 Method[] getDeclareMethods() 得到公共的方法对象
2 Method[] c.getMethods() 得到父类及本类中的公共方法对象
3 Method getDeclaredMethod(String methodName,Class…type) 得到指定名称的本类中公共的方法
4 Method getMethod(String methodName,Class type) 得到本类或父类中的公共的方法对象

获取构造方法

序号 方法 描述
1 Constructor[] getDeclaredConstructors() 得到公共的构造方法的对象
2 Constructor[] getConstructors() 得到公共的构造方法对象
3 Constructor getDeclaredConstructor(Class…type) 得到指定参数的公共的构造方法对象
package com.weini.entity;

public class User {
	//类的属性
	//public int userId;
	private int userId;
	private String userName;
	private String password;
	//公有的取值,赋值方法
	public int getUserId() {
		return userId;
	}
	public void setUserId(int userId) {
		this.userId = userId;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	//构造方法
	public User() {
		// TODO Auto-generated constructor stub
	}
	public User(int userId, String userName, String password) {
		super();
		this.userId = userId;
		this.userName = userName;
		this.password = password;
	}
	
	
}

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Test {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, NoSuchMethodException {
		String path="com.weini.entity.User";
		//(1)获取类的名称
		Class c=Class.forName(path);
		System.out.println("类的全名称:"+c.getName());
		System.out.println("类的名称:"+c.getSimpleName());
		
		//获取父类的Class对象
		Class cSuper=c.getSuperclass();
		System.out.println(cSuper.getName());
		System.out.println(cSuper.getSimpleName());
		
		//(2)获取类的属性信息
		//Field f=c.getField("userId"); //只能获取公共的属性
		//System.out.println(f);
		Field [] fields=c.getFields(); //只能获取公共的属性
		System.out.println(fields.length);
		
		Field [] fields2=c.getDeclaredFields();
		//System.out.println(fields2.length);
		for (Field field : fields2) {
			//System.out.println(field);//调用了toString()方法
			System.out.println(field.getModifiers()+"\t"+field.getType()+"\t"+field.getName());
		}
		
		
		//(3)获取类的方法信息
		Method[] methods=c.getDeclaredMethods(); //本类中的公共的方法对象
		System.out.println(methods.length);
		for (Method method : methods) {
			//System.out.println(method);
			System.out.println("访问权限"+method.getModifiers());
			System.out.println("返回值类型:"+method.getReturnType());
			System.out.println("方法的名称:"+method.getName());
			//获取方法的参数
			Class [] cPara=method.getParameterTypes();
			for (Class c1 : cPara) {
				System.out.println(c1.getTypeName()+"\t");
			}
			System.out.println("\n--------------------------");
			
		}
		System.out.println("\n=============================\n");
		
		//(4)获取类的构造器
		Constructor [] cons=c.getConstructors();
		for (Constructor constructor : cons) {
			System.out.println(constructor);
		}
		System.out.println("\n=====================");
		//获取指定的构造方法
		Constructor con=c.getConstructor(null);
		System.out.println(con);
		System.out.println("\n=====================");
		Constructor con2=c.getConstructor(int.class,String.class,String.class);
		System.out.println(con2);
	}
}

动态的操作属性、方法、构造方法

package com.weini.test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import com.bjsxt.entity.User;

public class Test2 {
	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException {
		//获到Class类的对象
		Class c=Class.forName("com.bjsxt.entity.User");
		
		//(1)得到无参构造方法的对象
		Constructor cons=c.getConstructor(null);
		//通过无参构造方法的对象,创建User类的对象
		User user=(User) cons.newInstance();
		
		//(2)动态操作属性
		Field field=c.getDeclaredField("userId");
		field.setAccessible(true);//这个属性不需要做安全检查了,可以直接访问
		field.set(user, 1001);  //通过反射直接赋值
		System.out.println("取出userId这个属性的值:"+field.get(user));//通过反射直接取值
		
		//(3)动态操作方法
		Method m=c.getDeclaredMethod("setUserName", String.class);
		//执行setUserName这个方法
		m.invoke(user, "张三");
		Method m2=c.getDeclaredMethod("getUserName", null);
		System.out.println(m2.invoke(user));
	}
}

提高反射效率

反射机制对程序的运行在性能上有一定的影响,速度慢
提高反射性能
setAccessible启用和禁用访问安全检查的开关,值为true则指示反射的对象在使用时应该取消java语言访问检查。禁止安全检查可以提高反射的运行速度。

反射操作泛型

泛型
java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换的麻烦,但是一旦编译完成,所有与泛型有关的类型全部擦除。
使用泛型直接读取泛型,是读取不到的,因为反射时操作以后加载的类。
java新增的数据类型
为了通过反射操作这些类型 以迎合实际开发的需要
在这里插入图片描述

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

import com.weini.entity.User;

public class TestGeneric {
	public void test01(Map<String,User> map,List<User> list,String s){
		System.out.println("TestGeneric.test01()");
	}
	public Map<Integer,User> test02(){
		System.out.println("TestGeneric.test02()");
		return null;
	}
	public String test03(){
		System.out.println("TestGeneric.test03()");
		return null;
	}
	public static void main(String[] args) throws NoSuchMethodException, SecurityException {
		//获取test01方法的泛型参数信息
		Class c=TestGeneric.class;
		Method test01=c.getMethod("test01", Map.class,List.class,String.class);
		
		//获取带泛型参数的类型
		Type [] tytes=test01.getGenericParameterTypes();
		System.out.println(tytes.length);
		for (Type type : tytes) {
			//System.out.println("#"+type);
			if (type instanceof ParameterizedType) {
				Type[] genericType= ((ParameterizedType) type).getActualTypeArguments();
				//遍历每一个泛型参数中泛型的类型  
				for (Type genType : genericType) {
					System.out.println("泛型类型:"+genType);
				}
				System.out.println("\n--------------------------");
			}
		}
		
		System.out.println("\n----------------------------\n");
		//获取test02方法返回值的泛型信息
		Method m2=c.getMethod("test02", null);
		Type returnType=m2.getGenericReturnType();
		//判断是否带有泛型
		if(returnType instanceof ParameterizedType){
			Type [] types=((ParameterizedType) returnType).getActualTypeArguments();
			for (Type type : types) {
				System.out.println("返回值的泛型类型:"+type);
			}
		}
		
		System.out.println("\n------------------------------\n");
		Method m3=c.getMethod("test03", null);
		Type returnType3=m3.getGenericReturnType();
		//System.out.println(returnType3);
		System.out.println(returnType3 instanceof ParameterizedType);
	}
	
}

猜你喜欢

转载自blog.csdn.net/weixin_45684562/article/details/107907746