Java反射的使用(2)

一、使用反射调用可变参数方法

要把可变参数都当做是其对应的数组类型参数;如 show(XX… is)作为 show(XX[] is)调用;
若可变参数元素类型是引用类型:
JDK 内部接收到参数之后,会自动拆包取出参数再分配给该底层方法,为此我们需要把这个数组实参先包装成一个 Object 对象或把实际参数作为一个Object 一维数组的元素再传递。
若可变参数元素类型是基本类型:
JDK 内部接收到参数之后,不会拆包,所以可以不必再封装。不过封装了也不会错,所以建议,不管基本类型还是引用类型都使用 Object[]封装一层,保证无误。
示例代码:
Java反射的使用(2)_第1张图片

import java.lang.reflect.Method;

class VaryMethod {
	public static void show(int... args) {
		System.out.println("基本数据类型传递过来了!");
	}

	/*public static void show(int[] args){//跟上面的写法一样
		System.out.println("基本数据类型传递过来了!");
	}*/
	 
	public static void show(String... args) {
		System.out.println("引用数据类型传递过来了!");
	}
}

public class InvokeVaryDemo {
	public static void main(String[] args) throws Exception {
		Class c = VaryMethod.class;
		Method m = c.getMethod("show", int[].class);
		m.invoke(null, new int[] { 1, 2, 3 });
		
		m = c.getMethod("show", String[].class);
		//m.invoke(null,new String[]{"A","B","C"});//ERROR:wrong number of arguments
		m.invoke(null, (Object) new String[] { "A", "B", "C" });// 强转为Object类型
		m.invoke(null, new Object[] { new String[] { "A", "B", "C" } });// 推荐写法
	}
}

结果截图:
在这里插入图片描述

二、使用反射操作字段

Field 提供两组方法操作字段:
xxx getXxx(Object obj):获取 obj 对象该 Field 的字段值,此处的 xxx 表示 8 个基本数据类型。
若该字段的类型是引用数据类型则使用,Object get(Object obj);
void setXxx(Object obj,xxx val):将 obj 对象的该 Field 字段设置成 val 值,此处的 xxx 表示 8
个基本数据类型。若该字段的类型是引用数据类型则使用,void set(Object obj, Object value);
获取字符,并且赋值,然后再取出来(对应的去查看api,比如这个是Field,别的比如Constructor,Method)。
步骤:
1.获取类
2.获取字段
3.赋值(set(c.newInstance(),””));{如果为私有的话设置可接受}
示例代码:
Java反射的使用(2)_第2张图片

import java.lang.reflect.Field;

class Cat {
	private String name;
	public int age;
	private String color;
}

public class FieldDemo {
	public static void main(String[] args) throws Exception {
		Class clz = Cat.class;
		Field[] f = clz.getDeclaredFields();
		for (Field field : f) {
			System.out.println(field);
		}
		
		Field fi = clz.getDeclaredField("name");
		System.out.println(fi);
		System.out.println(fi.getName());// name
		// 核心开始
		/**
		 * void set(Object obj, Object value) 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
		 */
		Cat c = clz.newInstance();
		fi.setAccessible(true);
		fi.set(c, "刘昭");// 赋值成功
		Object o = fi.get(c);
		System.out.println(o);// 取出成功
		
		fi = clz.getDeclaredField("age");
		fi.setAccessible(true);
		fi.set(c, 21);
		int i = fi.getInt(c);// 左边的接受类型已经写成了int,右边的返回类型就也必须是int
		System.out.println(i);// 获取成功
	}
}

结果截图:
Java反射的使用(2)_第3张图片

三、反射和泛型-反射来获取泛型信息

通过指定对应的 Class 对象,程序可以获得该类里面所有的 Field,不管该 Field 使用 private方法还是public。获得 Field 对象后都可以使用 getType()来获取其类型。
Class type = f.getType();//获得字段的类型
但此方法只对普通 Field 有效,若该 Field 有泛型修饰,则不能准确得到该 Field 的泛型参数,如
Map;
为了获得指定 Field 的泛型类型,我们采用:Type gType = f.getGenericType();得到泛型类型,
然后将 Type 对象强转为 ParameterizedType,其表示增加泛型后的类型
Type getRawType()//返回被泛型限制的类型;
Type[] getActualTypeArguments()//返回泛型参数类型;
利用反射来获取泛型的类型(泛型信息)
步骤:
1.获取当前类
2.获取目标字段
3.获取包含泛型类型的类型 getGenericType()
4.强转至子类 ParameterizedType 因为 Type 没有任何对应的方法
5.获得泛型真正的类型 getActualTypeArguments()
示例代码:
Java反射的使用(2)_第4张图片

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

public class GetGenericTypeDemo {
	Map map = new HashMap();
	public static void main(String[] args) throws Exception {
		Class c = GetGenericTypeDemo.class;
		Field f = c.getDeclaredField("map");
		System.out.println(f);
		System.out.println(f.getName());// map
		// Class getType() 返回一个 Class 对象,它标识了此 Field 对象 所表示字段的声明类型。
		Class cl = f.getType();
		System.out.println("获得其类型:" + cl);// 获得其类型:interface java.util.Map
		//Type getGenericType() 返回一个 Type 对象,它表示此 Field 对象 所表示字段的声明类型。Type是Class的接口;
		Type t = f.getGenericType();// 包含泛型的类型
		System.out.println(t);// java.util.Map
		//Type这个类里面没有任何的方法,所以需要调用子类的方法,那么大的类型 转到小的类型,需要强转!
		ParameterizedType pt = (ParameterizedType) t;// 强转到其子类
		//Type[] getActualTypeArguments() 返回表示此类型实际类型参数的 Type对象的数组。 
		//Type getOwnerType() 返回 Type 对象,表示此类型是其成员之一的类型。 
		//Type getRawType() 返回 Type 对象,表示声明此类型的类或接口。
		t = pt.getRawType();// 类型的类或接口
		System.out.println(t);
		Type[] ts = pt.getActualTypeArguments();
		for (Type type : ts) {
			System.out.println(type);//class java.lang.String //class java.lang.Integer
		}
	}
}

结果截图:
Java反射的使用(2)_第5张图片

你可能感兴趣的:(Java,Java基础知识点)