关闭

反射机制的详细代码理解

47人阅读 评论(0) 收藏 举报
分类:

1.类的加载器以及如何获取Class的实例

public class TestReflection {
	
	//关于类的加载器:ClassLoader
	@Test
	public void test5() throws Exception{
		ClassLoader loader1 = ClassLoader.getSystemClassLoader();//获取系统类加载器
		System.out.println(loader1);
		
		ClassLoader loader2 = loader1.getParent();//获取扩展类加载器
		System.out.println(loader2);
		
		ClassLoader loader3 = loader2.getParent();//引导类加载器无法被获取
		System.out.println(loader3);
		
		Class class1 = Person.class;
		ClassLoader loader4 = class1.getClassLoader();
		System.out.println(loader4);
		
		String className = "java.lang.Object";
		Class class2 = Class.forName(className);
		ClassLoader loader5 = class2.getClassLoader();//引导类加载器无法被获取
		System.out.println(loader5);
		
		ClassLoader loader = this.getClass().getClassLoader();
		InputStream is = loader.getResourceAsStream("com\\panda\\java\\jdbc.properties");
		Properties pros = new Properties();
		pros.load(is);
		String name = pros.getProperty("user");
		System.out.println(name);
		
		String password = pros.getProperty("password");
		System.out.println(password);
	}
	
	//如何获取Class的实例(3种)
	@Test
	public void test4() throws ClassNotFoundException{
		//1.调用运行时类本身的.class属性
		Class class1 = Person.class;
		System.out.println(class1.getName());
		
		Class class2 = String.class;
		System.out.println(class2.getName());
		
		//2.通过运行时类的对象获取
		Person person = new Person();
		Class class3 = person.getClass();
		System.out.println(class3.getName());
		
		//3.通过Class的静态方法获取
		String className = "com.panda.java.Person";
		Class class4 = Class.forName(className);
		System.out.println(class4.getName());
		
		//4.通过类的加载器
		ClassLoader classLoader = this.getClass().getClassLoader();
		Class class5 = classLoader.loadClass(className);
		System.out.println(class5.getName());
		
	}
	
	/*
	 * java.lang.class:是反射的源头
	 * 我们创建了一个类,通过编译(javac.exe),生成对应的.class文件。之后我们使用java.exe加载(JVM的类加载器完成的)
	 * 此.class文件,此.class文件加载到内存以后,就是一个运行时类,存在在缓存区。那么这个运行时类本身就是一个Class的实例!
	 * 1.每一个运行时类只加载一次!
	 * 2.有了Class的实例以后,我们才可以进行如下的操作:
	 *     1)*创建对应的运行时类的对象
	 *     2)获取对应的运行时类的完整结构(属性、方法、构造器、内部类、父类、所在的包、异常、注解、...)
	 *     3)*调用对应的运行时类的指定的结构(属性、方法、构造器)
	 *     4)反射的应用:动态代理
	 */
	@Test
	public void test3(){
		Person person = new Person();
		Class class1 = person.getClass();//通过运行时类的对象,调用其getClass(),返回其运行时类
		System.out.println(class1);
	}
	
	//有了反射,可以通过反射创建一个类的对象,并调用其中的结构
	@Test
	public void test2() throws Exception{
		Class class1 = Person.class;
		
		//1.创建class1对应的运行时类Person类的对象
		Person person = (Person) class1.newInstance();
		//2.通过反射调用运行时类的指定的属性
		Field f1 = class1.getField("name");
		f1.set(person, "liuDeHua");
		System.out.println(person);
		
		Field f2 = class1.getDeclaredField("age");
		f2.setAccessible(true);
		f2.set(person, 20);
		System.out.println(person);
		
		//3.通过反射调用运行时类的指定的方法
		Method m1 = class1.getMethod("show");
		m1.invoke(person);
		
		Method m2 = class1.getMethod("display", String.class);
		m2.invoke(person, "CHN");
	}
	//在有反射以前,如何创建一个类的对象,并调用其中的方法、属性
	@Test
	public void test1(){
		Person person = new Person();
		person.setAge(10);
		person.setName("liming");
		System.out.println(person);
		person.show();
		//person.display("中国");
	}
}
2.通过反射获取对应的运行时类的属性

public class TestField {
	//获取对应的运行时类的属性
	@Test
	public void test1(){
		Class class1 = Person.class;
		
		//1.getFields(),只能获取到运行时类中极其父类中声明为public的属性
		Field[] fields = class1.getFields();
		for (int i = 0; i < fields.length; i++) {
			System.out.println(fields[i]);
		}
		System.out.println();
		//2.getDeclaredFields(),获取运行时类本身声明的所有的属性
		Field[] fields2 = class1.getDeclaredFields();
		for(Field f : fields2){
			System.out.println(f.getName());
		}
	}
	/*
	 * 权限修饰符 变量类型 变量名
	 * 获取属性的各个部分的内容
	 */
	@Test
	public void test2(){
		Class class1 = Person.class;
		Field[] fields2 = class1.getDeclaredFields();
		for(Field f : fields2){
			//1.获取每个属性的权限修饰符
			int i = f.getModifiers();
			String str = Modifier.toString(i);
			System.out.print(str + " ");
			
			//2.获取属性的变量类型
			Class type = f.getType();
			System.out.print(type.getName() + " ");
			
			//3.获取属性名
			System.out.print(f.getName());
	
			System.out.println();
		}
	}
	
	//调用运行时类指定的属性
	@Test
	public void test3() throws Exception, SecurityException{
		Class class1 = Person.class;
		//1.获取指定的属性
		//getField(String fieldName):获取运行时类中声明为public的指定属性名为fieldName的属性
		Field name = class1.getField("name");
		//2.创建运行时类的对象
		Person person = (Person) class1.newInstance();
		//3.将运行时类的指定的属性赋值
		name.set(person, "Jack");
		System.out.println(person);
		
		System.out.println();
		//getDeclaredField(String fieldName):获取运行时类中指定属性名为fieldName的属性
		Field age = class1.getDeclaredField("age");
		//由于属性权限修饰的限制,为了保证可以给属性赋值,需要在操作前使得此属性可被操作
		age.setAccessible(true);
		age.set(person, 22);
		System.out.println(person);
	}
}

3.通过反射获取运行时类的方法

public class TestMethod {
	//1.获取运行时类的方法
	@Test
	public void test1(){
		Class class1 = Person.class;
		//1.getMethods(),获取运行时类及其父类中所有的声明为public的方法
		Method[] methods = class1.getMethods();
		for(Method m : methods){
			System.out.println(m);
		}
		System.out.println();
		
		//2.getDeclaredMethods(),获取运行时类本身声明的所有的方法
		Method[] methods2 = class1.getDeclaredMethods();
		for(Method m : methods2){
			System.out.println(m);
		}
	}
	
	
	//注解 权限修饰符 返回值类型 方法名 形参列表 异常
	@Test
	public void test2(){
		Class class1 = Person.class;
		
		Method[] methods2 = class1.getDeclaredMethods();
		for(Method m : methods2){
			//1.注解
			Annotation[] ann = m.getAnnotations();
			for(Annotation a : ann){
				System.out.println(a);
			}
			
			//2.权限修饰符
			String str = Modifier.toString(m.getModifiers());
			System.out.print(str + " ");
			
			//3.返回值类型
			Class returnType = m.getReturnType();
			System.out.print(returnType.getName() + " ");
			
			//4.方法名
			System.out.print(m.getName() + " ");
			
			//5.形参列表
			System.out.print("(");
			Class[] params = m.getParameterTypes();
			for(Class p : params){
				System.out.print(p.getName() + " ");
			}
			System.out.print(")");
			
			//6.异常类型
			Class[] exps = m.getExceptionTypes();
			for (int i = 0; i < exps.length; i++) {
				System.out.println(exps[i].getName());
			}
			System.out.println();
		}
	}
	//调用运行时类中的指定的方法
	@Test
	public void test3() throws Exception{
		Class class1 = Person.class;
		//getMethod(String methodName,Class ... params):获取运行时类中声明为public的指定的方法
		Method m1 = class1.getMethod("show");
		Person person = (Person) class1.newInstance();
		//调用指定的方法:Object invoke(Object obj,Object ... obj)
		Object returnVal = m1.invoke(person);//我是一个人
		System.out.println(returnVal);//null
		
		Method m2 = class1.getMethod("toString");
		Object returnVal1 = m2.invoke(person);
		System.out.println(returnVal1);//Person [name=null,age=0]
		
		//对于运行时类中静态方法的调用
		Method m3 = class1.getMethod("info");
		m3.invoke(Person.class);//中国人
		
		//getDeclaredMethod(String methodName,Class ... params):获取运行时类中声明了的指定的方法
		Method m4 = class1.getDeclaredMethod("display",String.class);
		m4.setAccessible(true);
		Object value = m4.invoke(person,"CHN");//我的国籍是:CHN
		
	}
}
4.通过反射调用指定的构造器

public class TestConstructor {
	@Test
	public void test1() throws Exception{
		String className = "com.panda.java.Person";
		Class class1 = Class.forName(className);
		
		//创建对应的运行时类的对象.使用newInstan(),实际上就是调用了运行时类的空参的构造器
		//要想能创建成功:1.要求对应的运行时类要有空参的构造器。2.构造器的权限修饰符的权限要足够
		Object object = class1.newInstance();
		Person person = (Person) object;
		System.out.println(person);
	}
	
	@Test
	public void test2() throws ClassNotFoundException{
		String className = "com.panda.java.Person";
		Class class1 = Class.forName(className);
		
		Constructor[] cons = class1.getDeclaredConstructors();
		
		for(Constructor constructor : cons){
			System.out.println(constructor);
		}
	}
	//调用指定的构造器,创建运行时类的对象
	@Test
	public void test3() throws Exception{
		String className = "com.panda.java.Person";
		Class class1 = Class.forName(className);
		Constructor constructor = class1.getDeclaredConstructor(String.class,int.class);
		constructor.setAccessible(true);
		Person person = (Person) constructor.newInstance("李明",21);
		System.out.println(person);
	}
} 
5.通过反射获取其他
public class TestOthers {
	//1.获取运行时类的父类
	@Test
	public void test1(){
		Class class1 = Person.class;
		Class supercClass = class1.getSuperclass();
		
		System.out.println(supercClass);
	}
	//2.获取带泛型的父类
	@Test
	public void test2(){
		Class class1 = Person.class;
		Type type = class1.getGenericSuperclass();
		
		System.out.println(type);
	}
	
	//3.获取父类的泛型
	@Test
	public void test3(){
		Class class1 = Person.class;
		Type type = class1.getGenericSuperclass();
		
		ParameterizedType pType = (ParameterizedType) type;
		Type[] ars = pType.getActualTypeArguments();
		System.out.println(((Class)ars[0]).getName());
	}
	
	//4.获取实现的接口
	@Test
	public void test4(){
		Class class1 = Person.class;
		Class[] interfaces = class1.getInterfaces();
		
		for(Class c : interfaces){
			System.out.println(c);
		}
	}
	
	//5.获取所在的包
	@Test
	public void test5(){
		Class class1 = Person.class;
		Package package1 = class1.getPackage();
		
		System.out.println(package1);
	}
	
	//6.获取注解
	@Test
	public void test6(){
		Class class1 = Person.class;
		Annotation[] anns = class1.getAnnotations();
		
		for(Annotation annotation : anns){
			System.out.println(annotation);
		}
	}
}
附录:

1.父类Creature

public class Creature<T> {
	public double weight;
	
	public void breath(){
		System.out.println("呼吸!");
	}
}

2.Person类

@MyAnnotation(value = "panda")
public class Person extends Creature<String> implements Comparable,MyInterface{

	public String name;
	private int age;
	int id;
	
	public Person() {
		super();
	}

	public Person(String name) {
		super();
		this.name = name;
	}

	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	
	
	public String getName() {
		return name;
	}

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

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	
	public int getId() {
		return id;
	}

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

	@MyAnnotation(value = "abc123")
	public void show(){
		System.out.println("我是一个人");
	}
	private void display(String nation)throws Exception{
		System.out.println("我的国籍是:" + nation);
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}

	@Override
	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		return 0;
	}
	public static void info(){
		System.out.println("中国人!");
	}
	class Bird{
		
	}
}
3.注解类

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
	String value();
}
4.接口类
public interface MyInterface extends Serializable{

}
5.jdbc.properties文件
user=root
password=123456











0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:10795次
    • 积分:722
    • 等级:
    • 排名:千里之外
    • 原创:63篇
    • 转载:4篇
    • 译文:0篇
    • 评论:0条