Java进阶学习第十九节——反射的使用

反射

反射是什么,能干什么

反射是:指程序可以访问、检测和修改它本身状态或行为的一种能力
反射是一种能力,所以给的定义就是说明了它能干嘛。

我们平时用反射主要做:

获取类型的相关信息
动态调用方法
动态构造对象
从程序集中获得类型。

一、Class类

  • 在面对对象编程中,万事万物皆对象,但是类本身又是谁的对象呢?
    他是java.lang.Class的对象
  • 获取类类型的3种方法
  1. 通过对象类的对象获取
Foo foo = new Foo();
Class class1 = foo.getClass();
  1. 通过类名获取
Class class2 = Foo.class;
  1. 还是通过类名获取,但是要try catch, 并且要转换类型
try {
	Class class3 = (Class) Class.forName("Foo");
} catch (ClassNotFoundException e) {
	// TODO Auto-generated catch block
	e.printStackTrace();
}

二、获取类的方法信息

  • 一个成员方法就是Method类的对象
  • getMethods()是获得该类的所有public方法,包括从父类继承来的方法
Method[] methods1 = class1.getMethods();
  • getDeclaredMethods()是获取当前类自己声明的成员方法,不包含父类继承来的,但是不问访问权限
Method[] methods2 = class1.getDeclaredMethods();
  • 得到返回值类型,先得到返回值类型的类类型,再获得名字
Class returnType = methods1[i].getReturnType();
String returnTypeName = returnType.getName();

  • 得到方法名
for (int i = 0; i < methods1.length; i++) {
	System.out.println(methods1[i].getName());
}
  • 得到参数类型,因为参数可能有多个,所以先得到参数列表,再遍历它得到参数类型的名字
Class[] paramTypes = methods1[i].getParameterTypes();
	for (Class paramType : paramTypes) {
		String paramTypeName = paramType.getName();
}

三、获取成员变量的信息

  • 成员变量是java.lang.reflect.Field类的对象
  • getFields()获得的是所有public的成员变量
Field[] fields1 = class1.getFields();
  • getDeclaredFields()获得的是自己声明的所有的成员变量
Field[] fields2 = class1.getDeclaredFields();
  • 获得成员变量类型的名称
for (Field field : fields2) {
	Class fieldType = field.getType();
	String fieldTypeName = fieldType.getName();
}
  • 获得成员变量名称
String fieldName = field.getName();

四、获取构造函数的信息

  • 构造函数是java.lang.reflect.Constructor的对象
  • 获得构造函数,方法基本同上
Constructor[] constructors1 = class1.getConstructors();
Constructor[] constructors2 = class1.getDeclaredConstructors();
  • 获得构造参数类型
for (Constructor constructor : constructors2) {
	Class[] paramTypes = constructor.getParameterTypes();
	for (Class paramType : paramTypes) {
		String paramTypeName = paramType.getName();
	}
}
  • 获得构造方法名称
String csName = constructor.getName();

五、 反射调用方法

public class A {
	public void print(int a, int b) {
		System.out.println(a + b);
	}
	
	public void print(String a, String b) {
		System.out.println(a.toUpperCase() + b.toLowerCase());
	}
}
  • 获取方法对象,先获得类类型,再操作
A a1 = new A();
Class clazz = a1.getClass();
// 这里第一个参数表示方法名,后面的是参数的类类型,如果没参数,就不传
// 要唯一确定一个方法,就得确定他的方法名和参数类型
Method m = clazz.getMethod("print", int.class, int.class);
  • 反射调用方法
// 这里是方法对象调用invoke方法,第一个参数是对象,后面的是参数,没参数就不写
//普通调用方法为:a1.print(10,20);
m.invoke(a1, 10, 20);

下面直接上代码

首先建立一个对象

Stu.java

package com.hqyj.pojo;

public class Stu {
	public String name;
	private int id;
	private String sex;
	
	private void sleep(String name) {
		System.out.println("我和"+name+"睡觉,你别管");
	}
	
	/**
	 * 
	 * <p>
	 * 1、为什么这个方法过时了
	 * 2、推荐我使用哪个类来使用
	 * </p>
	 * @author HC
	 * @Date 2018年12月14日
	 */
	@Deprecated
	public void eat() {
		System.out.println("吃饭");
	}
	
	public void project(String project) {
		System.out.println("正在学习:"+project);
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	@Override
	public String toString() {
		return "Stu [name=" + name + ", id=" + id + ", sex=" + sex + "]";
	}

	public Stu() {
		super();
		// TODO Auto-generated constructor stub
	}
	
	
	
}

测试类,ReflectDemo.java

package com.hqyj.reflect;

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

import com.hqyj.pojo.Stu;

public class ReflectDemo {

	
	public static void main(String[] args) {
		Class<Stu> stuClazz = getStuClazz();
		
		Field field = getField(stuClazz);
		System.out.println("***************");
		
		Method method =getStuMethod(stuClazz);
		System.out.println("***************");
		
		//普通的调用方法
		Stu stu = new Stu();
		stu.project("springboot");
		System.out.println("***************");
		//反射调用方法
		try {
			//让私有的方法能被访问
			method.setAccessible(true);
			method.invoke(stuClazz.newInstance(),"李万杰");
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}


	private static Method getStuMethod(Class<Stu> stuClazz) {
		/**
		 * 获得方法
		 * 1、获得所有方法
		 * 2、获得指定方法
		 */
		
		//所有public的方法
		System.out.println("获取所有public方法");
		Method[] methods = stuClazz.getMethods();
		for (Method method : methods) {
			String returnType = method.getReturnType().getName();
			String methodName = method.getName();
			String str = returnType +":"+methodName+"(";
			/*Parameter[] parameters =  method.getParameters();
			for (Parameter parameter : parameters) {
				System.out.println(parameter);
			}*/
			
			Class<?>[] clazzes = method.getParameterTypes();
			for (Class clazz : clazzes) {
				str+=clazz.getName()+", ";
			}
			str +=")";
			System.out.println(str);
		}
		System.out.println("***************");
		//获得所有方法
		System.out.println("获取所有方法");
		Method[] methods2 = stuClazz.getDeclaredMethods();
		for (Method method : methods2) {
			String returnType = method.getReturnType().getName();
			String methodName = method.getName();
			String str = returnType +":"+methodName+"(";
			/*Parameter[] parameters =  method.getParameters();
			for (Parameter parameter : parameters) {
				System.out.println(parameter);
			}*/
			
			Class<?>[] clazzes = method.getParameterTypes();
			for (Class clazz : clazzes) {
				str+=clazz.getName()+", ";
			}
			str +=")";
			System.out.println(str);
		}
		System.out.println("***************");
		//获得指定方法
		System.out.println("获取指定方法");
		try {
			Method method = stuClazz.getDeclaredMethod("sleep",String.class);
			System.out.println(method);
			return method;
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}


	private static Field getField(Class<Stu> stuClazz) {
		/**
		 * 获得字段
		 * 1、获取所有字段
		 * 2、获取指定字段
		 */
		
		//获取所有的(包括从父类继承下来的)public字段
		Field[] fields = stuClazz.getFields();
		System.out.println("获取所有的(包括从父类继承下来的)public字段");
		for (Field field : fields) {
			System.out.println(field.getType()+":"+field.getName());
		}
		
		//获取所有的字段,不管访问权限
		Field[] fields2 = stuClazz.getDeclaredFields();
		System.out.println("获取所有的字段,不管访问权限");
		for (Field field : fields2) {
			System.out.println(field.getType()+":"+field.getName());
		}
		
		//获取指定字段
		try {
			Field field = stuClazz.getDeclaredField("name");
			System.out.println("获取指定字段");
			System.out.println(field.getType()+":"+field.getName());
			return field;
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	
	/**
	 * 
	 * <p>
	 * 获取类类型
	 * </p>
	 * @author HC
	 * @Date 2018年12月14日
	 * @return
	 */
	private static Class<Stu> getStuClazz(){
		Stu stu = new Stu();
		
		Class<? extends Stu> stuClazz = stu.getClass();
		
		Class<Stu> stuClazz2 = Stu.class;
		
		try {
			Class<?> stuClazz3 = Class.forName("com.hqyj.pojo.Stu");
		}catch( ClassNotFoundException e ) {
			e.printStackTrace();
		}
		return stuClazz2;
	}
	
	
	
}


结果:
获取所有的(包括从父类继承下来的)public字段
class java.lang.String:name
获取所有的字段,不管访问权限
class java.lang.String:name
int:id
class java.lang.String:sex
获取指定字段
class java.lang.String:name
***************
获取所有public方法
java.lang.String:toString()
java.lang.String:getName()
int:getId()
void:setName(java.lang.String, )
void:setId(int, )
void:setSex(java.lang.String, )
void:project(java.lang.String, )
void:eat()
java.lang.String:getSex()
void:wait()
void:wait(long, int, )
void:wait(long, )
boolean:equals(java.lang.Object, )
int:hashCode()
java.lang.Class:getClass()
void:notify()
void:notifyAll()
***************
获取所有方法
java.lang.String:toString()
java.lang.String:getName()
int:getId()
void:setName(java.lang.String, )
void:sleep(java.lang.String, )
void:setId(int, )
void:setSex(java.lang.String, )
void:project(java.lang.String, )
void:eat()
java.lang.String:getSex()
***************
获取指定方法
private void com.hqyj.pojo.Stu.sleep(java.lang.String)
***************
正在学习:springboot
***************
我和李万杰睡觉,你别管

List绕过编译添加元素

package com.hqyj.reflect;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

import com.hqyj.pojo.Stu;

public class ArrayListDemo {
	public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		ArrayList<Integer> intList= new ArrayList<>();
		ArrayList<String> stringList= new ArrayList<>();
		
		Class class1 = intList.getClass();
		Class class2 = stringList.getClass();
		//结果为true,说明泛型只是在编译时检查,在运行时是去掉泛型的
		System.out.println(class1 == class2);
		
		//获取指定方法
		Method add = class1.getDeclaredMethod("add",Object.class);
		//反射调用方法
		add.invoke(intList, "haha");
		add.invoke(intList, new Stu());
		System.out.println(intList);
		
		
	}
}


结果:
true
[haha, Stu [name=null, id=0, sex=null]]

总结

		//获得Class的方法
		//第一种
		MyClazz myClazz = new MyClazz();
		Class<? extends MyClazz> myClass2 = myClazz.getClass();
		
		//第二种
		Class myClass3 = MyClazz.class;
		
		//第三种 
		Class myClass4 = Class.forName("MyClazz");
		
		
		//获得所有public包括父类字段
		Field[] fields = myClass.getFields();
		//获得所有字段,不管访问权限
		Field[] fields2 = myClass.getDeclaredFields();
		//获得指定字段
		Field field3 = myClass.getDeclaredField("字段名");
		
		
		//获得所有public包括父类方法
		Method[] methods = myClass.getMethods();
		//获得所有方法,不管访问权限
		Method[] methods2 = myClass.getDeclaredMethods();
		//获得指定方法
		Method method3 = myClass.getDeclaredMethod("方法名");
		//调用方法(第一个参数,第二个参数类型)
		method3.invoke("参数", Object.class);

猜你喜欢

转载自blog.csdn.net/qq_38846837/article/details/85008526