Day43 Java反射(二)

Day43 Java反射(二)

文章目录

一、利用反射操作方法

1、基本步骤

  1. 获取Class对象:要操作一个类,首先需要获取对应的Class对象。可以通过类名.class语法或者Class.forName("类名")方法来获取。
  2. 获取类的构造函数:通过Class对象可以获取类的构造函数,从而实例化对象。
  3. 获取类的字段(属性):可以通过Class对象的getFields()、getDeclaredFields()等方法获取类的字段信息,从而访问和修改这些字段的值。
  4. 获取类的方法:可以通过Class对象的getMethods()、getDeclaredMethods()等方法获取类的方法信息,从而调用这些方法。
  5. 调用方法:通过Method类的invoke()方法可以调用类的方法。
  6. 访问和修改字段:通过Field类的get()和set()方法可以访问和修改类的字段的值。
  7. 处理异常:在使用反射时,需要处理可能抛出的IllegalAccessException、IllegalArgumentException、InvocationTargetException等异常

2、示例代码:

java 复制代码
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Properties;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

import com.qf.utils.ReflexUtil;

public class Test01 {
	/**
	 * 知识点:利用反射操作方法
	 */
	public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, SecurityException {
		
		Properties p = new Properties();
		p.load(Test01.class.getClassLoader().getResourceAsStream("classPath.properties"));
		String path = p.getProperty("path");

		Class<?> clazz = Class.forName(path);
		
		//获取本类及其父类公有的方法对象
		Method[] methods = clazz.getMethods();
		for (Method method : methods) {
			System.out.println(method);
		}
		
		//获取本类所有的方法对象
		Method[] methods1 = clazz.getDeclaredMethods();
		for (Method method : methods1) {
			System.out.println(method);
		}
		
		//获取本类及其父类所有的方法对象
		for (Class<?> c = clazz; c != null; c = c.getSuperclass()) {
			Method[] methods2 = c.getDeclaredMethods();
			for (Method method : methods2) {
				System.out.println(method);
			}
		}
		
		//获取本类公有的指定名字的方法对象
		Method method = clazz.getMethod("setClassId", String.class);
		System.out.println(method);
		
		//获取本类所有的指定名字的方法对象
		Method method1 = clazz.getDeclaredMethod("method");
		System.out.println(method1);
		
		//利用反射工具类获取子类及其父类指定名字的方法对象
		Method method2 = ReflexUtil.getMethod(clazz, "method");
		System.out.println(method2);
		//获取方法参数值
		int modifiers = method.getModifiers();
		System.out.println("是否使用public修饰:" + Modifier.isPublic(modifiers));
		System.out.println("是否使用private修饰:" + Modifier.isPrivate(modifiers));
		System.out.println("是否使用protected修饰:" + Modifier.isProtected(modifiers));
		System.out.println("是否使用static修饰:" + Modifier.isStatic(modifiers));
		System.out.println("是否使用final修饰:" + Modifier.isFinal(modifiers));
		System.out.println("是否使用abstract修饰:" + Modifier.isAbstract(modifiers));
		System.out.println("是否使用synchronized修饰:" + Modifier.isSynchronized(modifiers));
		
	}
}

public class ReflexUtil {

	/**
	 * 获取当前类及其父类的属性对象
	 * @param clazz class对象
	 * @param name 属性名
	 * @return 属性对象
	 */
	public static Field getField(Class<?> clazz,String name){
		
		for(Class<?> c = clazz;c != null;c = c.getSuperclass()){
			try {
				Field field = c.getDeclaredField(name);
				return field;
			} catch (NoSuchFieldException e) {
			} catch (SecurityException e) {
			}
		}
		return null;
	}
	
	/**
	 * 设置对象中的属性
	 * @param obj 对象
	 * @param name 属性名
	 * @param value 属性值
	 */
	public static void setField(Object obj,String name,Object value){
		
		Field field = getField(obj.getClass(), name);
		if(field != null){
			field.setAccessible(true);
			try {
				field.set(obj, value);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 创建对象
	 * @param clazz class对象
	 * @param paremeterType 构造方法中的参数类型数组
	 * @param paremeters 构造方法中的参数数据
	 * @return 对象
	 */
	public static <T> T newInstance(Class<T> clazz,Class<?>[] parameterTypes,Object[] paremeters){
		
		try {
			Constructor<T> constructor = clazz.getDeclaredConstructor(parameterTypes);
			constructor.setAccessible(true);
			T obj = constructor.newInstance(paremeters);
			return obj;
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取方法对象
	 * @param clazz class对象
	 * @param name 方法名
	 * @param parameterTypes 参数列表数组
	 * @return 方法对象
	 */
	public static Method getMethod(Class<?> clazz,String name,Class<?>... parameterTypes){
		
		for(Class<?> c = clazz; c != null; c = c.getSuperclass()) {
			try {
				Method method = c.getDeclaredMethod(name, parameterTypes);
				return method;
			} catch (NoSuchMethodException e) {
			} catch (SecurityException e) {
			}
		}
		
		return null;
	}

	/**
	 * 调用成员方法
	 * @param obj 对象
	 * @param name 方法名
	 * @param parameterTypes 参数列表数组
	 * @param paremeters 参数数据数组
	 * @return 方法返回值
	 */
	public static Object invoke(Object obj,String name,Class<?>[] parameterTypes,Object[] paremeters){
		
		Class<? extends Object> clazz = obj.getClass();
		
		Method method = getMethod(clazz, name, parameterTypes);
		method.setAccessible(true);
		
		try {
			Object invoke = method.invoke(obj, paremeters);
			return invoke;
		} catch (IllegalAccessException e) {
		} catch (IllegalArgumentException e) {
		} catch (InvocationTargetException e) {
		}
		return null;
	}
	
	/**
	 * 调用静态方法
	 * @param clazz class对象
	 * @param name 方法名
	 * @param parameterTypes 参数列表数组
	 * @param paremeters 参数数据数组
	 * @return 方法返回值
	 */
	public static Object invoke(Class<?> clazz,String name,Class<?>[] parameterTypes,Object[] paremeters){
		
		Method method = getMethod(clazz, name, parameterTypes);
		method.setAccessible(true);
		
		try {
			Object invoke = method.invoke(null, paremeters);
			return invoke;
		} catch (IllegalAccessException e) {
		} catch (IllegalArgumentException e) {
		} catch (InvocationTargetException e) {
		}
		return null;
	}
}

二、利用反射操作方法里的参数和返回值

在利用反射操作方法时,可以通过反射机制获取方法的参数信息和返回值类型。

1、常用方法:

  1. 获取方法参数信息
    • 使用Method类的getParameterTypes()方法可以获取方法的参数类型,返回一个Class数组,每个元素代表一个参数的类型。
    • 使用Method类的getParameters()方法可以获取方法的参数信息,返回一个Parameter数组,每个元素包含参数的名称、修饰符等信息。
  2. 调用方法
    • 使用Method类的invoke()方法可以调用方法,并传入对应的参数值。需要注意参数的类型要与方法定义的参数类型一致,否则会抛出IllegalArgumentException异常。
  3. 获取返回值类型
    • 使用Method类的getReturnType()方法可以获取方法的返回值类型,返回一个Class对象,表示返回值的类型。
  4. 处理返回值
    • 调用Method类的invoke()方法后会返回方法的执行结果,需要根据返回值类型进行相应的处理,可以使用instanceof关键字进行类型检查,然后进行强制类型转换

总的来说,通过反射机制可以动态地获取和操作方法的参数和返回值信息,这为编写通用的、灵活的代码提供了便利。但是在处理参数和返回值时,需要注意类型匹配和异常处理,以确保程序的正确性和稳定性。

2、示例代码:

java 复制代码
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.util.Properties;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

import com.qf.utils.ReflexUtil;

public class Test03 {
	/**
	 * 知识点:利用反射操作 方法里的参数和返回值
	 */
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		
		Properties p = new Properties();
		p.load(Test03.class.getClassLoader().getResourceAsStream("classPath.properties"));
		String path = p.getProperty("path");

		Class<?> clazz = Class.forName(path);
		
		//利用反射工具类获取方法对象
		Method method = ReflexUtil.getMethod(clazz, "method04", String.class,int.class);
		
		//获取方法的参数个数
		int parameterCount = method.getParameterCount();
		System.out.println("获取方法的参数个数:" + parameterCount);
		
		System.out.println("-----------------------------");
		
		//获取方法参数的class对象数组
		Class<?>[] parameterTypes = method.getParameterTypes();
		for (Class<?> c : parameterTypes) {
			System.out.println(c);
		}
		
		System.out.println("-----------------------------");
		
		//获取方法参数的Type对象数组
		//一个参数类型就是一个Type对象
		Type[] genericParameterTypes = method.getGenericParameterTypes();
		for (Type type : genericParameterTypes) {
			System.out.println(type);
		}
		
		System.out.println("-----------------------------");
		
		//获取方法参数对象数组
		//一个参数就是一个参数对象
		Parameter[] parameters = method.getParameters();
		for (Parameter parameter : parameters) {
			
			System.out.println("获取方法的参数类型:" + parameter.getType());
			
			/**
			 * 注意:
			 * 		参数名不会随着编译而编译到class文件,
			 * 		class文件描述该方法的参数名使用的是:arg0,arg1,arg2,.....
			 */
			System.out.println("获取方法的参数名:" + parameter.getName());
		}
		
		System.out.println("-----------------------------");
		
		//获取返回值的class对象
		Class<?> returnType = method.getReturnType();
		System.out.println("获取返回值的class对象:" + returnType);
		
		//获取返回值的Type对象
		Type genericReturnType = method.getGenericReturnType();
		System.out.println("获取返回值的Type对象:" + genericReturnType);
	}
}

public class ReflexUtil {

	/**
	 * 获取当前类及其父类的属性对象
	 * @param clazz class对象
	 * @param name 属性名
	 * @return 属性对象
	 */
	public static Field getField(Class<?> clazz,String name){
		
		for(Class<?> c = clazz;c != null;c = c.getSuperclass()){
			try {
				Field field = c.getDeclaredField(name);
				return field;
			} catch (NoSuchFieldException e) {
			} catch (SecurityException e) {
			}
		}
		return null;
	}
	
	/**
	 * 设置对象中的属性
	 * @param obj 对象
	 * @param name 属性名
	 * @param value 属性值
	 */
	public static void setField(Object obj,String name,Object value){
		
		Field field = getField(obj.getClass(), name);
		if(field != null){
			field.setAccessible(true);
			try {
				field.set(obj, value);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 创建对象
	 * @param clazz class对象
	 * @param paremeterType 构造方法中的参数类型数组
	 * @param paremeters 构造方法中的参数数据
	 * @return 对象
	 */
	public static <T> T newInstance(Class<T> clazz,Class<?>[] parameterTypes,Object[] paremeters){
		
		try {
			Constructor<T> constructor = clazz.getDeclaredConstructor(parameterTypes);
			constructor.setAccessible(true);
			T obj = constructor.newInstance(paremeters);
			return obj;
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取方法对象
	 * @param clazz class对象
	 * @param name 方法名
	 * @param parameterTypes 参数列表数组
	 * @return 方法对象
	 */
	public static Method getMethod(Class<?> clazz,String name,Class<?>... parameterTypes){
		
		for(Class<?> c = clazz; c != null; c = c.getSuperclass()) {
			try {
				Method method = c.getDeclaredMethod(name, parameterTypes);
				return method;
			} catch (NoSuchMethodException e) {
			} catch (SecurityException e) {
			}
		}
		
		return null;
	}

	/**
	 * 调用成员方法
	 * @param obj 对象
	 * @param name 方法名
	 * @param parameterTypes 参数列表数组
	 * @param paremeters 参数数据数组
	 * @return 方法返回值
	 */
	public static Object invoke(Object obj,String name,Class<?>[] parameterTypes,Object[] paremeters){
		
		Class<? extends Object> clazz = obj.getClass();
		
		Method method = getMethod(clazz, name, parameterTypes);
		method.setAccessible(true);
		
		try {
			Object invoke = method.invoke(obj, paremeters);
			return invoke;
		} catch (IllegalAccessException e) {
		} catch (IllegalArgumentException e) {
		} catch (InvocationTargetException e) {
		}
		return null;
	}
	
	/**
	 * 调用静态方法
	 * @param clazz class对象
	 * @param name 方法名
	 * @param parameterTypes 参数列表数组
	 * @param paremeters 参数数据数组
	 * @return 方法返回值
	 */
	public static Object invoke(Class<?> clazz,String name,Class<?>[] parameterTypes,Object[] paremeters){
		
		Method method = getMethod(clazz, name, parameterTypes);
		method.setAccessible(true);
		
		try {
			Object invoke = method.invoke(null, paremeters);
			return invoke;
		} catch (IllegalAccessException e) {
		} catch (IllegalArgumentException e) {
		} catch (InvocationTargetException e) {
		}
		return null;
	}
}

三、利用反射操作泛型

在Java中,由于泛型的类型擦除特性,直接使用反射来操作泛型可能会遇到一些限制和困难。然而,仍然可以通过一些技巧和方法来处理泛型类型。

注意

类上的泛型是获取不到的,因为不固定!!!

class A{}

1、常用方法:

  1. 获取泛型类型信息
    • 可以通过反射获取包含泛型信息的类、方法或字段的Type对象,例如ParameterizedType、TypeVariable等。
    • 使用Type类的getTypeName()方法可以获取泛型类型的名称,进而分析泛型参数的具体类型。
  2. 操作泛型类
    • 可以通过Class类的getGenericSuperclass()方法获取泛型父类的Type信息,从而获取泛型参数的具体类型。
    • 使用Class类的getTypeParameters()方法可以获取类声明的泛型参数信息。
  3. 操作泛型方法
    • 可以通过Method类的getGenericReturnType()、getGenericParameterTypes()等方法获取方法的泛型返回类型和参数类型信息。
  4. 操作泛型字段
    • 可以通过Field类的getGenericType()方法获取字段的泛型类型信息。
  5. 创建泛型实例
    • 可以通过ParameterizedTypeImpl类等来创建泛型实例,从而实现对泛型类型的操作和实例化。

2、示例代码:

java 复制代码
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Properties;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import com.qf.utils.ReflexUtil;

public class Test04 {
	/**
	 * 知识点:利用反射操作泛型
	 */
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		
		Properties p = new Properties();
		p.load(Test04.class.getClassLoader().getResourceAsStream("classPath.properties"));
		String path = p.getProperty("path");

		Class<?> clazz = Class.forName(path);
		
		
		//获取属性上的泛型类型
		Field field = ReflexUtil.getField(clazz, "map");
		Type fieldType = field.getGenericType();
		ParameterizedType fieldTypepPT = (ParameterizedType) fieldType;
		Type[] actualTypeArguments = fieldTypepPT.getActualTypeArguments();//获取泛型类型
		for (Type type : actualTypeArguments) {
			System.out.println(type);
		}
		
		System.out.println("---------------------------------------");
		
		Method method = ReflexUtil.getMethod(clazz, "method05", ArrayList.class,HashMap.class);
		
		//获取方法上参数的泛型类型
		Parameter[] parameters = method.getParameters();
		for (Parameter parameter : parameters) {
			Type parameterizedType = parameter.getParameterizedType();
			ParameterizedType parameterTypepPT = (ParameterizedType) parameterizedType;
			Type[] actualTypeArguments2 = parameterTypepPT.getActualTypeArguments();
			for (Type type : actualTypeArguments2) {
				System.out.println(type);
			}
		}
		
		System.out.println("---------------------------------------");
		
		//获取方法上返回值的泛型类型
		Type genericReturnType = method.getGenericReturnType();
		ParameterizedType returnPT = (ParameterizedType) genericReturnType;
		Type[] actualTypeArguments2 = returnPT.getActualTypeArguments();
		for (Type type : actualTypeArguments2) {
			System.out.println(type);
		}
	}
}


public class ReflexUtil {

	/**
	 * 获取当前类及其父类的属性对象
	 * @param clazz class对象
	 * @param name 属性名
	 * @return 属性对象
	 */
	public static Field getField(Class<?> clazz,String name){
		
		for(Class<?> c = clazz;c != null;c = c.getSuperclass()){
			try {
				Field field = c.getDeclaredField(name);
				return field;
			} catch (NoSuchFieldException e) {
			} catch (SecurityException e) {
			}
		}
		return null;
	}
	
	/**
	 * 设置对象中的属性
	 * @param obj 对象
	 * @param name 属性名
	 * @param value 属性值
	 */
	public static void setField(Object obj,String name,Object value){
		
		Field field = getField(obj.getClass(), name);
		if(field != null){
			field.setAccessible(true);
			try {
				field.set(obj, value);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 创建对象
	 * @param clazz class对象
	 * @param paremeterType 构造方法中的参数类型数组
	 * @param paremeters 构造方法中的参数数据
	 * @return 对象
	 */
	public static <T> T newInstance(Class<T> clazz,Class<?>[] parameterTypes,Object[] paremeters){
		
		try {
			Constructor<T> constructor = clazz.getDeclaredConstructor(parameterTypes);
			constructor.setAccessible(true);
			T obj = constructor.newInstance(paremeters);
			return obj;
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取方法对象
	 * @param clazz class对象
	 * @param name 方法名
	 * @param parameterTypes 参数列表数组
	 * @return 方法对象
	 */
	public static Method getMethod(Class<?> clazz,String name,Class<?>... parameterTypes){
		
		for(Class<?> c = clazz; c != null; c = c.getSuperclass()) {
			try {
				Method method = c.getDeclaredMethod(name, parameterTypes);
				return method;
			} catch (NoSuchMethodException e) {
			} catch (SecurityException e) {
			}
		}
		
		return null;
	}

	/**
	 * 调用成员方法
	 * @param obj 对象
	 * @param name 方法名
	 * @param parameterTypes 参数列表数组
	 * @param paremeters 参数数据数组
	 * @return 方法返回值
	 */
	public static Object invoke(Object obj,String name,Class<?>[] parameterTypes,Object[] paremeters){
		
		Class<? extends Object> clazz = obj.getClass();
		
		Method method = getMethod(clazz, name, parameterTypes);
		method.setAccessible(true);
		
		try {
			Object invoke = method.invoke(obj, paremeters);
			return invoke;
		} catch (IllegalAccessException e) {
		} catch (IllegalArgumentException e) {
		} catch (InvocationTargetException e) {
		}
		return null;
	}
	
	/**
	 * 调用静态方法
	 * @param clazz class对象
	 * @param name 方法名
	 * @param parameterTypes 参数列表数组
	 * @param paremeters 参数数据数组
	 * @return 方法返回值
	 */
	public static Object invoke(Class<?> clazz,String name,Class<?>[] parameterTypes,Object[] paremeters){
		
		Method method = getMethod(clazz, name, parameterTypes);
		method.setAccessible(true);
		
		try {
			Object invoke = method.invoke(null, paremeters);
			return invoke;
		} catch (IllegalAccessException e) {
		} catch (IllegalArgumentException e) {
		} catch (InvocationTargetException e) {
		}
		return null;
	}
}

四、利用反射操作注解

在Java中,可以利用反射机制来操作注解,包括获取类、方法、字段等上的注解信息,判断注解的存在与内容,以及根据注解信息进行相应的处理。

1、常用方法:

  1. 获取类、方法、字段上的注解
    • 使用Class类的getAnnotation()方法可以获取类上的指定注解。
    • 使用Method类的getAnnotation()方法可以获取方法上的指定注解。
    • 使用Field类的getAnnotation()方法可以获取字段上的指定注解。
  2. 判断注解的存在
    • 使用isAnnotationPresent()方法可以判断类、方法、字段上是否存在指定的注解。
  3. 获取注解的属性值
    • 获取到注解对象后,可以通过注解对象的方法来获取注解的属性值,例如@Retention、@Target等元注解的属性值。
  4. 根据注解信息进行处理
    • 根据注解的存在与内容,可以编写相应的逻辑来处理。例如,根据注解标记的方法执行特定的操作,或者根据注解的属性值进行不同的处理。
  5. 动态生成带有注解的类、方法、字段
    • 可以通过反射机制动态生成带有注解的类、方法、字段,并在运行时进行相应的处理。

2、示例代码:

java 复制代码
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Properties;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import com.qf.utils.ReflexUtil;

public class Test05 {

	/**
	 * 知识点:利用反射操作注解
	 */
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		
		Properties p = new Properties();
		p.load(Test05.class.getClassLoader().getResourceAsStream("classPath.properties"));
		String path = p.getProperty("path");

		Class<?> clazz = Class.forName(path);
		
		//获取类上的注解信息
		MyAnnotaction classAnnotation = clazz.getAnnotation(MyAnnotaction.class);
		System.out.println(classAnnotation.str());
	
		System.out.println("------------------------------------------------");
		
		//获取属性上的注解信息
		Field field = ReflexUtil.getField(clazz, "map");
		MyAnnotaction fieldAnnotation = field.getAnnotation(MyAnnotaction.class);
		System.out.println(fieldAnnotation.str());
		
		System.out.println("------------------------------------------------");
		
		//获取方法上的注解信息
		Method method = ReflexUtil.getMethod(clazz, "method05", ArrayList.class,HashMap.class);
		MyAnnotaction methodAnnotation = method.getAnnotation(MyAnnotaction.class);
		System.out.println(methodAnnotation.str());
		
		System.out.println("------------------------------------------------");
		
		//获取参数上的注解信息
		Parameter[] parameters = method.getParameters();
		for (Parameter parameter : parameters) {
			MyAnnotaction parameterAnnotation = parameter.getAnnotation(MyAnnotaction.class);
			if(parameterAnnotation != null){//说明该参数上有MyAnnotaction的注解
				System.out.println(parameterAnnotation.str());
			}
		}
		
		
	}
}


public class ReflexUtil {

	/**
	 * 获取当前类及其父类的属性对象
	 * @param clazz class对象
	 * @param name 属性名
	 * @return 属性对象
	 */
	public static Field getField(Class<?> clazz,String name){
		
		for(Class<?> c = clazz;c != null;c = c.getSuperclass()){
			try {
				Field field = c.getDeclaredField(name);
				return field;
			} catch (NoSuchFieldException e) {
			} catch (SecurityException e) {
			}
		}
		return null;
	}
	
	/**
	 * 设置对象中的属性
	 * @param obj 对象
	 * @param name 属性名
	 * @param value 属性值
	 */
	public static void setField(Object obj,String name,Object value){
		
		Field field = getField(obj.getClass(), name);
		if(field != null){
			field.setAccessible(true);
			try {
				field.set(obj, value);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 创建对象
	 * @param clazz class对象
	 * @param paremeterType 构造方法中的参数类型数组
	 * @param paremeters 构造方法中的参数数据
	 * @return 对象
	 */
	public static <T> T newInstance(Class<T> clazz,Class<?>[] parameterTypes,Object[] paremeters){
		
		try {
			Constructor<T> constructor = clazz.getDeclaredConstructor(parameterTypes);
			constructor.setAccessible(true);
			T obj = constructor.newInstance(paremeters);
			return obj;
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取方法对象
	 * @param clazz class对象
	 * @param name 方法名
	 * @param parameterTypes 参数列表数组
	 * @return 方法对象
	 */
	public static Method getMethod(Class<?> clazz,String name,Class<?>... parameterTypes){
		
		for(Class<?> c = clazz; c != null; c = c.getSuperclass()) {
			try {
				Method method = c.getDeclaredMethod(name, parameterTypes);
				return method;
			} catch (NoSuchMethodException e) {
			} catch (SecurityException e) {
			}
		}
		
		return null;
	}

	/**
	 * 调用成员方法
	 * @param obj 对象
	 * @param name 方法名
	 * @param parameterTypes 参数列表数组
	 * @param paremeters 参数数据数组
	 * @return 方法返回值
	 */
	public static Object invoke(Object obj,String name,Class<?>[] parameterTypes,Object[] paremeters){
		
		Class<? extends Object> clazz = obj.getClass();
		
		Method method = getMethod(clazz, name, parameterTypes);
		method.setAccessible(true);
		
		try {
			Object invoke = method.invoke(obj, paremeters);
			return invoke;
		} catch (IllegalAccessException e) {
		} catch (IllegalArgumentException e) {
		} catch (InvocationTargetException e) {
		}
		return null;
	}
	
	/**
	 * 调用静态方法
	 * @param clazz class对象
	 * @param name 方法名
	 * @param parameterTypes 参数列表数组
	 * @param paremeters 参数数据数组
	 * @return 方法返回值
	 */
	public static Object invoke(Class<?> clazz,String name,Class<?>[] parameterTypes,Object[] paremeters){
		
		Method method = getMethod(clazz, name, parameterTypes);
		method.setAccessible(true);
		
		try {
			Object invoke = method.invoke(null, paremeters);
			return invoke;
		} catch (IllegalAccessException e) {
		} catch (IllegalArgumentException e) {
		} catch (InvocationTargetException e) {
		}
		return null;
	}
}

五、利用反射操作数组

在Java中,可以利用反射机制来操作数组,包括创建数组实例、获取数组的长度、访问和修改数组元素等操作。

注意:Array -- 该类是Java给我们提供专门利用反射去操作数组的类

1、常用方法:

  1. 创建数组实例
    • 使用Array类的newInstance()方法可以动态创建数组实例,指定数组的类型和长度。
  2. 获取数组的长度
    • 使用Array类的getLength()方法可以获取数组的长度。
  3. 访问和修改数组元素
    • 使用Array类的get()方法可以访问数组指定位置的元素。
    • 使用Array类的set()方法可以修改数组指定位置的元素。
  4. 处理多维数组
    • 对于多维数组,可以使用Array类的newInstance()方法创建多维数组实例,通过多次调用get()和set()方法来访问和修改多维数组的元素。
  5. 数组类型检查
    • 在使用反射操作数组时,需要注意数组元素的类型,确保类型匹配,避免出现ClassCastException等异常。

2、示例代码:

java 复制代码
import java.lang.reflect.Array;

public class Test06 {
	/**
	 * 知识点:利用反射操作数组
	 * 
	 */
	public static void main(String[] args) {
		
		//创建数组
		int[] arr = (int[]) Array.newInstance(int.class, 10);
		
		//获取数组长度
		int length = Array.getLength(arr);
		System.out.println("获取数组长度:" + length);
		
		//循环设置每个下标上的元素
		for (int i = 0; i < Array.getLength(arr); i++) {
			//设置当前下标上的元素
			Array.set(arr, i, i+1);
		}
		
		//循环获取每个下标上的元素
		for (int i = 0; i < Array.getLength(arr); i++) {
			//获取当前下标上的元素
			Object element = Array.get(arr, i);
			System.out.println(element);
		}
	}
}

态创建数组实例,指定数组的类型和长度。

  1. 获取数组的长度
  • 使用Array类的getLength()方法可以获取数组的长度。
  1. 访问和修改数组元素
    • 使用Array类的get()方法可以访问数组指定位置的元素。
    • 使用Array类的set()方法可以修改数组指定位置的元素。
  2. 处理多维数组
    • 对于多维数组,可以使用Array类的newInstance()方法创建多维数组实例,通过多次调用get()和set()方法来访问和修改多维数组的元素。
  3. 数组类型检查
    • 在使用反射操作数组时,需要注意数组元素的类型,确保类型匹配,避免出现ClassCastException等异常。

2、示例代码:

java 复制代码
import java.lang.reflect.Array;

public class Test06 {
	/**
	 * 知识点:利用反射操作数组
	 * 
	 */
	public static void main(String[] args) {
		
		//创建数组
		int[] arr = (int[]) Array.newInstance(int.class, 10);
		
		//获取数组长度
		int length = Array.getLength(arr);
		System.out.println("获取数组长度:" + length);
		
		//循环设置每个下标上的元素
		for (int i = 0; i < Array.getLength(arr); i++) {
			//设置当前下标上的元素
			Array.set(arr, i, i+1);
		}
		
		//循环获取每个下标上的元素
		for (int i = 0; i < Array.getLength(arr); i++) {
			//获取当前下标上的元素
			Object element = Array.get(arr, i);
			System.out.println(element);
		}
	}
}
相关推荐
天天扭码几秒前
五天SpringCloud计划——DAY2之单体架构和微服务架构的选择和转换原则
java·spring cloud·微服务·架构
程序猿进阶1 分钟前
堆外内存泄露排查经历
java·jvm·后端·面试·性能优化·oom·内存泄露
FIN技术铺5 分钟前
Spring Boot框架Starter组件整理
java·spring boot·后端
zwjapple11 分钟前
typescript里面正则的使用
开发语言·javascript·正则表达式
小五Five13 分钟前
TypeScript项目中Axios的封装
开发语言·前端·javascript
小曲程序13 分钟前
vue3 封装request请求
java·前端·typescript·vue
前端每日三省15 分钟前
面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们?
开发语言·前端·javascript
好看资源平台24 分钟前
网络爬虫——综合实战项目:多平台房源信息采集与分析系统
爬虫·python
凡人的AI工具箱28 分钟前
15分钟学 Go 第 60 天 :综合项目展示 - 构建微服务电商平台(完整示例25000字)
开发语言·后端·微服务·架构·golang
陈王卜30 分钟前
django+boostrap实现发布博客权限控制
java·前端·django