反射的几种应用和具体代码解释

反射

一.反射的定义
1.反射是指程序运行中动态的获取类的信息,并访问,类的信息包含:属性和方法,构造方法
2.反射是通过JDK给我们提供一套API来获取类的属性,方法,构造方法并且可以使用
3.类的对象是Class
方法也是对象,属于Method类
构造方法也是对象,属于Constructor类
字段属性也是对象,Filed类
这些类都位于java.lang.reflect反射包中
二.反射调用类代码:

public class Test {
	public static void main(String[] args) {

		try {
			Class<?> dateClass = Class.forName("java.util.Date");
			System.out.println(dateClass);
			Object newInstance = dateClass.newInstance();
			System.out.println(newInstance);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

代码解释:
通过Class.forName方法获得的类名字和属于的包,传入Class修饰的对象中,可以直接输出,然后得到其包和类,然后通过其定义的对象dateClass调用newInstance方法可以得到一个对象,也可以直接输出,在此处直接输出代表输出Data类的对象,即直接输出未定义格式的时间。
三.通过反射获取类的无参构造方法

1.无参构造方法
public class Test1 {
	public static void main(String[] args) {
//		Person p1 = new Person();
		try {
			Class<?> personClass = Class.forName("com.qfedu.test6.Person");
			Constructor<?> constructor = personClass.getConstructor();
			Object newInstance = constructor.newInstance();
			System.out.println(newInstance);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} 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();
		}
	}
}
class Person {
	private String name;
	private String address;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Person() {
		System.out.println("Person无参构造方法");
	}
	public Person(String name, String address, int age) {
		this.name = name;
		this.address = address;
		this.age = age;
	}
	@Override
	public String toString() {
		System.out.println("Person toString方法");
		return "Person [name=" + name + ", address=" + address + ", age=" + age + "]";
	}
}

代码解释:
先用Class.forName获取类的信息,然后用Class定义的对象调用getConstructor()获取所有的构造方法赋值给constructor,然后用constructor调用newInstance方法获得类的对象,直接输出可以得到方法
2.有参构造方法

package com.qfedu.test6;

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

public class Test2 {
	public static void main(String[] args) {
		try {
			Class<?> stuClass = Class.forName("com.qfedu.test6.Student");
			Constructor<?> constructor = stuClass.getConstructor(String.class,String.class,int.class);
			Object newInstance = constructor.newInstance("赵四","象牙山",20);
			System.out.println(newInstance);
			
			Constructor<?>[] constructors = stuClass.getConstructors();
			for(Constructor<?> con : constructors) {
				System.out.println(con.getParameterCount());
				Parameter[] parameters = con.getParameters();
				for(Parameter p : parameters) {
					System.out.print("构造方法中参数的名称" + p.getName() + "\t");
					System.out.println("构造方法中参数的名称" + p.getType());
				}
			}
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} 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();
		}
	}
}
class Student {
	private String name;
	private String address;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Student() {
		System.out.println("Student无参构造方法");
	}
	public Student(String name, String address, int age) {
		this.name = name;
		this.address = address;
		this.age = age;
	}
	public Student(int age ,String name, String address) {
		this.name = name;
		this.address = address;
		this.age = age;
	}
	@Override
	public String toString() {
		System.out.println("Student toString方法");
		return "Student [name=" + name + ", address=" + address + ", age=" + age + "]";
	}
}

代码解释:
forName先获取对应类的信息,然后getConstructor(String.class,String.class,int.class)获取所有构造方法的信息,当不传参数类型时为无参构造,然后用newInstance方法获得对象,并进行传值constructor.newInstance(“赵四”,“象牙山”,20),直接输出对象即可得到传入的参数
调用getConstructors()方法获得构造方法有几个参数,用增强for循环进行输出,getParameters()方法获取参数的具体信息,然后在增强for循环里使用对象调方法得到我们想要的属性用增强for循环进行循环,输出的时候用增强for定义的对象可以调出我们想要的参数信息,比如p.getName()得到参数的参数的名称,p.getType()获得参数的类型
3.使用反射调用方法

package com.qfedu.test6;

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

public class Test3 {
	public static void main(String[] args) {
		try {
			Class<?> gradeClass = Class.forName("com.qfedu.test6.Grade");
			Object newInstance = gradeClass.newInstance();
			Method[] methods = gradeClass.getMethods();
			Method setNameMethod = null;
			Method setStuCountMethod = null;
			for(Method m : methods) {
				System.out.println(m.getName());
				if(m.getName().equals("setName")) {
					setNameMethod = m;
				}
				
				if(m.getName().equals("setStuCount")) {
					setStuCountMethod= m;
				}
			}
			// newInstance.setName("三年二班")
			setNameMethod.invoke(newInstance, "三年二班");
			setStuCountMethod.invoke(newInstance, 30);
			System.out.println(gradeClass.getMethod("getName").invoke(newInstance));
			System.out.println(gradeClass.getMethod("getStuCount").invoke(newInstance));
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} 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();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

class Grade{
	private String name;
	private int stuCount;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getStuCount() {
		return stuCount;
	}
	public void setStuCount(int stuCount) {
		this.stuCount = stuCount;
	}
	public Grade() {
	}
	public Grade(String name, int stuCount) {
		this.name = name;
		this.stuCount = stuCount;
	}
	@Override
	public String toString() {
		return "Grade [name=" + name + ", stuCount=" + stuCount + "]";
	}
}

先用forName获得类信息,用newInstance获得对象,再用getMethods获取所有方法,然后定义两个空白的方法setNameMethod和setStuCountMethod,然后用增强for循环遍历所有的方法,m.getName()可以获取所有方法,包括继承父类的,然后用if语句进行判断,遍历的方法中有没有我们想要的方法,有的话传值给我们之前定义的空白方法,然后通过invoke进行方法调用对象,格式为方法名.invoke(对象名,"传入的信息"),然后再输出时,通过我们获取到的类调用方法,再通过方法调用对象进行输出,格式为类.getMethod("我们要调用的方法").invoke(我们获得的对象)
四.通过反射调用对象
package com.qfedu.test6;

import java.lang.reflect.Field;

/**
 * 	调属性
 * @author WHD
 *
 */
public class Test4 {
	public static void main(String[] args) {
		try {
			Class<?> schoolClass = Class.forName("com.qfedu.test6.School");
			Object newInstance = schoolClass.newInstance();
			Field[] fields = schoolClass.getFields();
			Field nameField = null;
			Field ageField = null;
			for(Field f : fields) {
				System.out.println(f.getName() + "\t" + f.getType());
				if(f.getName().equals("name")) {
					nameField = f;
				}
				if(f.getName().equals("age")) {
					ageField = f;
				}
			}
			
			// newInstance.name  
			nameField.set(newInstance, "赵四");
			ageField.set(newInstance, 20);
			
			System.out.println(schoolClass.getField("name").get(newInstance));
			
			System.out.println(schoolClass.getField("age").get(newInstance));
			
			
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

class School{
	public String name;
	public int age;
}

代码解释:
和调用方法一样,先forName获得类信息,newInstance获得对象,getFields获得所有字段信息,定义两个空白的字段,然后进行增强for循环遍历,在进行判断遍历里是否有我们想要的字段,有的话赋给我们定义的空白字段,通过字段使用set添加我们要添加的对象信息,格式为,字段.set(我们获得的对象,“需要传入的值”),输出的时候用我们获取的类信息调用getField调用字段,然后用get调用对像,具体格式为,类信息.getField(“我们要输出的字段名”).get(我们获得的对象)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值