Java教程

java开发框架基础-反射

本文主要是介绍java开发框架基础-反射,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

什么是反射

在这里插入图片描述
通过Java反射可以实现以下功能
在这里插入图片描述

就像照镜子可以看请自己,反射使程序可以看清一个类的情况并加以使用,Java反射机制能够探知类的基本结构,这种对Java类结构探知的能力,称为Java类的“自审”,并且,反射机制使构建框架的基础所在。

java反射常用API
在这里插入图片描述

获取类的信息

一个类或者接口被加载后,从系统中都能获得一个代表该类或接口的Class实例,通过该实例就可以访问到Java虚拟机中这个类会接口。

获取Class实例
Java程序中获取Class实例通常有如下三种方式,根据实际情况选择。
在这里插入图片描述

从Class实例中获取信息
在获得了某个类型对应的Class实例后,就可以调用Class实例的方法来获得该类型的信息。Class提供了大量实例方法来获取对应类型的详细信息。

获取类型的基本信息
在这里插入图片描述

示例1:
创建一个User类用于测试:

package pm;

public class User{
	private String name;
	private int age;
	private String address;
	private char sex;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@Override
	public String toString() {
		return "User [name=" + name + ", age=" + age + ", address=" + address
				+ ", sex=" + sex + "]";
	}
	public int getAge() { 
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public char getSex() {
		return sex;
	}
	public void setSex(char sex) {
		this.sex = sex;
	}
	public User() {
		super();
	}
	public User(String name, int age, String address, char sex) {
		super();
		this.name = name;
		this.age = age;
		this.address = address;
		this.sex = sex;
	}
}

示例2:通过反射方式获取User类的基本信息

package pm;

public class 获得Class实例 {

	/**
	 * @param args
	 * @throws ClassNotFoundException 
	 */
	public static void main(String[] args) throws ClassNotFoundException {
		// TODO Auto-generated method stub
		//第一种获取Class实例这种方式需要在编译期就知道类或接口的名称
		Class c1 = User.class;
		System.out.println(c1.getName());
		System.out.println(c1.getSimpleName());
		
		Package package1 = c1.getPackage();
		System.out.println(package1.getName());
		
		Class[] faces  = c1.getInterfaces();
		if(faces.length==0){
			System.out.println("该类没有实现接口");
		}else{
			for(Class c : faces){
				System.out.println(c.getName());
			}
		}
		
		Class superClass = c1.getSuperclass();
		System.out.println(superClass.getName());
		//第二种获取Class实例
		//getClass()方法是Object类的方法,所有类和接口都可以调用该方法
		User user = new User();
		Class c2 = user.getClass();
		System.out.println(c2.getName());
		
		//第三种获取Class实例
		/*若编码时无法确定类型,需要程序在运行中根据情况灵活加载,
		可以使用Class类的forName()方法。该方法时静态方法,需传入字符串参数,
		该字符串参数的值是某个类的完全限定类名,即包含包名的完整类名。*/
		Class c3 = Class.forName("pm.User");
		System.out.println(c3.getName());
	}

}

获得对应类型所包含的构造方法
在这里插入图片描述
示例3:通过反射获取User类的构造方法信息

	public static void main(String[] args) throws NoSuchMethodException, SecurityException {
		// TODO Auto-generated method stub
		Class<User> c1 = User.class;
		/*//获取单个参数构造方法
		Constructor c = c1.getDeclaredConstructor(String.class,int.class,String.class,char.class);
		//获取访问修饰符
		int mod = c.getModifiers();
		String modStr = Modifier.toString(mod);
		//获得方法名
		String name = c.getName();
		//获得参数列表
		Class[] params=c.getParameterTypes();
		String paramsStr="";
		for (int i = 0; i < params.length; i++) {
			if(i!=0){
				paramsStr+=",";
			}
			paramsStr+=params[i].getSimpleName()+" p"+i;
		}
		String str=modStr+" "+name+"("+paramsStr+"){\n\n}";
		System.out.println(str);
		*/
		//获取全部构造方法
		Constructor[] constructors = c1.getDeclaredConstructors();
		for (Constructor c : constructors) {
			//获取访问修饰符
			int mod = c.getModifiers();
			String modStr = Modifier.toString(mod);
			//获得方法名
			String name = c.getName();
			//获得参数列表
			Class[] params=c.getParameterTypes();
			String paramsStr="";
			for (int i = 0; i < params.length; i++) {
				if(i!=0){
					paramsStr+=",";
				}
				paramsStr+=params[i].getSimpleName()+" p"+i;
			}
			String str=modStr+" "+name+"("+paramsStr+"){\n\n}";
			System.out.println(str);
		}
	}

获取对应类型所包含的属性
在这里插入图片描述
示例4:通过反射方式获取User类的属性信息

	public static void main(String[] args) throws NoSuchFieldException, SecurityException {
		// TODO Auto-generated method stub
		//获得user实例对象
		Class<User> c1 = User.class;
		//获得单个name属性
		Field nameField = c1.getDeclaredField("name");
		//获得属性访问修饰符
		int mod = nameField.getModifiers();
		String m = Modifier.toString(mod);
		
		//获得属性类型
		Class type = nameField.getType();
		
		//获得属性名称
		String name = nameField.getName();
		
		String str = m+" "+type.getSimpleName()+" "+name;
		System.out.println(str);
		
		//获取全部User属性值
		Field[] fields = c1.getDeclaredFields();
		for (Field field : fields) {
			//获得属性访问修饰符
			int mod1 = field.getModifiers();
			String m1 = Modifier.toString(mod1);
			
			//获得属性类型
			Class type1 = field.getType();
			
			//获得属性名称
			String name1 = field.getName();
			
			String str1 = m1+" "+type1.getSimpleName()+" "+name1+";";
			System.out.println(str1);
		}
	}

访问对应类型所包含的方法
在这里插入图片描述
示例5:通过反射获取User类中方法信息

public class 获得方法 {
	public static void main(String[] args) throws NoSuchMethodException, SecurityException {
		Class<User> c1 = User.class;//获取实例对象
		/*//获得setName方法
		Method method = c1.getDeclaredMethod("setName", String.class);
		//获得方法访问修饰符
		int mod = method.getModifiers();
		String modStr  = Modifier.toString(mod);
		
		//获得返回值类型
		Class returntype = method.getReturnType();
		//获得方法名
		String name  = method.getName();
		
		//获得方法参数列表
		Class[] params = method.getParameterTypes();
		String paramsStr = "";
		for (int i = 0; i < params.length; i++) {
			if(i!=0){
				paramsStr+=",";
			}
			paramsStr+=params[i].getSimpleName()+" p"+i;
		}
		System.out.println(modStr+" "+returntype.getSimpleName()+" "+name+"("+paramsStr+")"+"{\n\n}");*/
		
		//获取全部方法
		Method[] methods = c1.getDeclaredMethods();
		for (Method method : methods) {
			//获得方法访问修饰符
			int mod = method.getModifiers();
			String modStr  = Modifier.toString(mod);
			
			//获得返回值类型
			Class returntype = method.getReturnType();
			//获得方法名
			String name  = method.getName();
			
			//获得方法参数列表
			Class[] params = method.getParameterTypes();
			String paramsStr = "";
			for (int i = 0; i < params.length; i++) {
				if(i!=0){
					paramsStr+=",";
				}
				paramsStr+=params[i].getSimpleName()+" p"+i;
			}
			System.out.println(modStr+" "+returntype.getSimpleName()+" "+name+"("+paramsStr+")"+"{\n\n}");
		}
	}
}

总结:
Class实例可以获得相关类型中的构造方法,属性,方法等成员信息。其中,构造方法由Constructor类型表示,属性由Field类型表示,方法由Method类型表示。Constructor,Field,Method这3个类都都定义了在java.lang.reflect包下,并且都实现了java.lang.reflect.Member接口。程序可以通过Constructor实例来调用相应的构造方法创建相关类型的实例,通过Field实例直接访问并修改相关类型实例的属性值,通过Method实例来执行相关类型实例的方法。

创建实例

通过反射来创建类型实例的方法有两种:
在这里插入图片描述
示例6:创建类型示例方式:

	public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
		// TODO Auto-generated method stub
		Class<User> c1 = User.class;
		//实例化对象
		User user1 = c1.newInstance();
		user1.setName("张三");
		System.out.println(user1);
		//利用构造方法创建对象
		//如果创建java实例时,需要使用指定构造方法,则可以使用该方式。
		Constructor c=c1.getDeclaredConstructor(String.class,int.class,String.class,char.class);
		User user2 = (User)c.newInstance("李四",20,"beijing",'男');
		System.out.println(user2);
		
	}

访问类的属性
在这里插入图片描述
调用类的方法
Method类中包含一个invoke()方法,通过invoke()方法,Method实例可以调用Java类的实例方法和静态方法,invoke()方法定义 如下:
在这里插入图片描述
若Method实例表示的是一个静态方法,则obj可以为null。
若该方法没有参数可以不填,或者填null

示例7:通过反射访问User类的属性,调用方法:

public class 操作方法和属性 {
	public static void main(String[] args) throws NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
		Class c1 = User.class;
		//获得实例化对象
		Object u = c1.newInstance();
		//操作对象属性
		//获得属性
		Field f= c1.getDeclaredField("name");//获取name属性
		f.setAccessible(true);//绕开访问权限
		f.set(u, "Tom");
		System.out.println(u);
		//操作对象方法
		//获得方法
		Method method = c1.getDeclaredMethod("setName",String.class);
		method.invoke(u,"tom");
		Method methodget = c1.getDeclaredMethod("getName");
		String nameString=(String)methodget.invoke(u);
		System.out.println(nameString);	
	}
}

注意:
受访问修饰符的限制,使用反射方式访问超出访问范围的构造方法,属性,方法时,会引发异常。若要禁止java语言访问检强行访问,需要设置相关实例即可访问,如下:

f.setAccessible(true);//绕开访问权限

扩展:

  1. 当直接输出对象时,系统会自动调用对象的toString()方法
  2. 系统默认的toString()方法打印内容为:类全名@16进制哈希值
  3. toString()方法属于Object类,所有类都能继承该方法

反射技术优点:
在这里插入图片描述

反射技术缺点:
在这里插入图片描述
总结
在这里插入图片描述

这篇关于java开发框架基础-反射的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!