JAVA反射学习

1 反射的主体类

public class User {
	private int id;
	private int age;
	private String name;
	/**
	 * @return the id
	 */
	public int getId() {
		return id;
	}
	/**
	 * @param id the id to set
	 */
	public void setId(int id) {
		this.id = id;
	}
	/**
	 * @return the age
	 */
	public int getAge() {
		return age;
	}
	/**
	 * @param age the age to set
	 */
	public void setAge(int age) {
		this.age = age;
	}
	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}
	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}
	public User(int id, int age, String name) {
		super();
		this.id = id;
		this.age = age;
		this.name = name;
	}
	public User() {
		super();
	}

2 测试各种(class,interface,enum,annotation,private type,void 等等)类型对应的java.lang.class对象的获取方式

public class Demo01 {
	public static void main(String[] args) {
		String path="com.shiwen.reflectiontest.User";
	     try {
			Class clazz = Class.forName(path);
			// 对象是表示或者拼装一些数据的,一个类被加载后,JVM会创建一个对应的Class对象,类的整个信息会放到对应的Class对象
			// Class 对象就像一面镜子一样,通过这面镜子可以看到对应类的全部信息
			System.out.println(clazz);
			System.out.println(clazz.hashCode());
			Class clazz2 = Class.forName(path); // 一个类只对应一个Class对象
			System.out.println(clazz2.hashCode());
			
			Class strClazz=String.class;
			Class strclazz2=path.getClass();
			System.out.println(strClazz==strclazz2); // 同一个反射类是同一个对象,拥有想通过的hash值,在内存中只会有一个反射类对象被创建
			
			Class intClazz=int.class;
			int[] arr01=new int[10];
			int[] arr02=new int[30];
			int[][] arr03=new int[10][2];
			double[] arr04=new double[10];
			
			// 同一个数组类型的反射类的hash值是一样的
			System.out.println(intClazz.hashCode());
			System.out.println(arr01.getClass().hashCode());
			System.out.println(arr02.getClass().hashCode());
			System.out.println(arr03.getClass().hashCode());
			System.out.println(arr04.getClass().hashCode());
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}    
}
class com.shiwen.reflectiontest.User
366712642
366712642
true
1829164700
2018699554
2018699554
1311053135
118352462

3 应用反射的APT获取类的信息(类的名字,属性,方法,构造器等)

public class Demo02 {
	public static void main(String[] args) throws NoSuchFieldException, SecurityException, NoSuchMethodException {
		String path = "com.shiwen.reflectiontest.User";
		try {
			Class clazz = Class.forName(path);
            // 获取类的名字
			System.out.println(clazz.getName()); // 包名+类名
			System.out.println(clazz.getSimpleName()); // 类名
			
			// 获取属性信息
			Field[] fields = clazz.getFields(); // 只能获得public 的field
			System.out.println(fields.length);
			Field[] declaredFields = clazz.getDeclaredFields(); // 获取所有的field
			System.out.println(declaredFields.length);
			// 获取指定的field
			Field declaredField = clazz.getDeclaredField("name");
			System.out.println(declaredField);
			
			for(Field temp: declaredFields) {
				System.out.println("属性:"+temp);
			}
			
			// 获取方法信息
			Method[] declaredMethods = clazz.getDeclaredMethods(); // 获取所有的方法
			Method m01=clazz.getDeclaredMethod("getName", null); // 获取指定的方法参数类型为空
			Method m02=clazz.getDeclaredMethod("setName", String.class); // 获取指定的方法。参数类型为String
			for(Method m:declaredMethods) {
				System.out.println("方法:"+m);
			}
			
			// 获取构造器信息
			Constructor[] declaredConstructors = clazz.getDeclaredConstructors();// 获取所有的构造器
			Constructor declaredConstructor = clazz.getDeclaredConstructor(null); // 获取指定无参构造器
			Constructor declaredConstructor2 = clazz.getDeclaredConstructor(int.class,int.class,String.class); // 获取指定参数的构造器
			for(Constructor temp:declaredConstructors) {
				System.out.println("构造器"+temp);
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
}

4 通过反射API动态的操作:构造器,方法,属性

public class Demo03 {
	public static void main(String[] args) {
		String path = "com.shiwen.reflectiontest.User";
		try {
			Class<User> clazz = (Class<User>) Class.forName(path);

			// 通过反射API调用构造方法,构造对象
			User u = clazz.newInstance(); // 其实是调用了user的无参构造方法

			Constructor<User> declaredConstructor = clazz.getDeclaredConstructor(int.class, int.class, String.class);
			User newInstance = declaredConstructor.newInstance(1, 18, "史文");
			System.out.println(u);
			System.out.println(newInstance.getName());

			// 通过反射API调用普通方法
			User newInstance2 = clazz.newInstance();
			Method declaredMethod = clazz.getDeclaredMethod("setName", String.class);
			declaredMethod.invoke(newInstance2, "史文2"); // 相当于newInstance2.setName("史文2");
			System.out.println(newInstance2.getName());

			// 通过反射API操作属性
			User newInstance3 = clazz.newInstance();
			Field f = clazz.getDeclaredField("name");
			f.setAccessible(true); // 这个属性不用做安全检查了,可以直接访问
			f.set(newInstance3, "史文3"); // 通过反射直接写属性
			System.out.println(newInstance3.getName());
			System.out.println(f.get(newInstance3)); // 通过属性直接读属性的值
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		}
	}

}
com.shiwen.reflectiontest.User@15db9742
史文
史文2
史文3
史文3

5 通过反射获取泛型信息

public class Demo04 {
	
	public void test01(Map<String,User> map,List<User> list){
		System.out.println("Demo04.test01()");
	}
	
	public Map<Integer,User> test02(){
		System.out.println("Demo04.test02()");
		return null;
	}
	
	public static void main(String[] args) {

		try {
			
			//获得指定方法参数泛型信息
			Method m = Demo04.class.getMethod("test01", Map.class,List.class);
			Type[] t = m.getGenericParameterTypes();
			for (Type paramType : t) {
				System.out.println("#"+paramType);
				if(paramType instanceof ParameterizedType){
					Type[] genericTypes = ((ParameterizedType) paramType).getActualTypeArguments();
					for (Type genericType : genericTypes) {
						System.out.println("泛型类型:"+genericType);
					}
				}
			}
			
			//获得指定方法返回值泛型信息
			Method m2 = Demo04.class.getMethod("test02", null);
			Type returnType = m2.getGenericReturnType();
			if(returnType instanceof ParameterizedType){
					Type[] genericTypes = ((ParameterizedType) returnType).getActualTypeArguments();

					for (Type genericType : genericTypes) {
						System.out.println("返回值,泛型类型:"+genericType);
					}
					
			}
			
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	
		
	
	}
}

6 通过反射获取注解信息

@SxtTable("tb_student")
public class SxtStudent {
	
	@SxtField(columnName="id",type="int",length=10)
	private int id;
	@SxtField(columnName="sname",type="varchar",length=10)
	private String studentName;
	@SxtField(columnName="age",type="int",length=3)
	private int age;
	
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getStudentName() {
		return studentName;
	}
	public void setStudentName(String studentName) {
		this.studentName = studentName;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	
}
public class Demo05 {
	public static void main(String[] args) {

		try {
			Class clazz = Class.forName("demo.shiwen.test.annotation.SxtStudent");
			
			//获得类的所有有效注解
			Annotation[] annotations=clazz.getAnnotations();
			for (Annotation a : annotations) {
				System.out.println(a);
			}
			//获得类的指定的注解
			SxtTable st = (SxtTable) clazz.getAnnotation(SxtTable.class);
			System.out.println(st.value());
			
			//获得类的属性的注解
			Field f = clazz.getDeclaredField("studentName");
			SxtField sxtField = f.getAnnotation(SxtField.class);
			System.out.println(sxtField.columnName()+"--"+sxtField.type()+"--"+sxtField.length());
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	
	}
}

7 通过跳过安全检查,提高反射效率(三种执行方法的效率差异比较)

public class Demo06 {
	
	public static void test01(){
		User u = new User();
		
		long startTime = System.currentTimeMillis();
		
		for (int i = 0; i < 1000000000L; i++) {
			u.getName();
		}
		
		long endTime = System.currentTimeMillis();
		System.out.println("普通方法调用,执行10亿次,耗时:"+(endTime-startTime)+"ms"); 
	}
	
	public static void test02() throws Exception{
		User u = new User();
		Class clazz = u.getClass();
		Method m = clazz.getDeclaredMethod("getName", null);
//		m.setAccessible(true);
		
		long startTime = System.currentTimeMillis();
		
		for (int i = 0; i < 1000000000L; i++) {
			m.invoke(u, null);
		}
		
		long endTime = System.currentTimeMillis();
		System.out.println("反射动态方法调用,执行10亿次,耗时:"+(endTime-startTime)+"ms");
	}
	
	public static void test03() throws Exception{
		User u = new User();
		Class clazz = u.getClass();
		Method m = clazz.getDeclaredMethod("getName", null);
		m.setAccessible(true);	//不需要执行访问安全检查
		
		long startTime = System.currentTimeMillis();
		
		for (int i = 0; i < 1000000000L; i++) {
			m.invoke(u, null);
		}
		
		long endTime = System.currentTimeMillis();
		System.out.println("反射动态方法调用,跳过安全检查,执行10亿次,耗时:"+(endTime-startTime)+"ms");
	}
	
	
	public static void main(String[] args) throws Exception {
		test01();
		test02();
		test03();
	}
}
普通方法调用,执行10亿次,耗时:339ms
反射动态方法调用,执行10亿次,耗时:1309ms
反射动态方法调用,跳过安全检查,执行10亿次,耗时:932ms
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值