学习JAVA反射之Class类

关于java. Lang. Class类的理解
1.类的加载过程:
程序经过javac. exe命令以后,会生成-一个或多个字 节码文件(. class结尾)。接着我们使用java. exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中。此过程就称为类的加载。加载到内存中的类,我们就称为运行时类,此运行时类,就作为Class的一个实例。
2.换句话说,Class的实例就对应着一个运行时类。
3.加载到内存中的运行时类,会缓存一定的时间。 在此时间之内,我们可以通过不同的方式来获取此运行时类。

哪些类型可以有Class对象?
(1) class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
(2) interface: 接口
(3) []: 数组
(4) enum: 枚举
(5) annotation: 注解@interface
(6) primitive type:基本数据类型
(7) void 可以看做一个类型

public void test(){
Class c1 = 0bject.class; .
Class c2 = Comparable.class;
Class c3 = String[].class;
Class c4 = int[][].class ;
Class c5 = ElementType. class ;
Class c6 = Override. class;
Class c7 = int.class;
Class c8 = void. class;
Class c9 = Class.class;
int[] a = new int[10] ;
int[] b = new int[100];
Class c10 = a.getClass();
Class c11 = b. getClass();
只要数组的元素类型与维度一样,就是同一个Class
System. out.println(c10 == c11);
}

使用newInstance方法 创建运行时类的对象(Person可以看作一个运行时类),内部运用了运行时类的空参构造器
使用此方法时候能正常运行时的对象,要求:
1.运行时类b必须提供空参构造器
2.空参构造器的访问权限要有,如public

使用反射获取类的名字、方法、构造器、属性

package com.lrq.Reflection;

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

public class ClassTest {

	public static void main(String[] args) throws Exception, SecurityException {
		String path = new String("com.lrq.Reflection.Person");
		
		try {
			Class clazz = Class.forName(path);
			
			//获取类的名字
			String name1 = clazz.getName();//获得包名加类名 com.lrq.Reflection.Person
			String name2 = clazz.getSimpleName();//获得类名 Person
			System.out.println(name1);
			System.out.println(name2);
			//获取类的方法
			Method[] m1 = clazz.getMethods();//获得所有public的方法
			Method[] m2 = clazz.getDeclaredMethods();//获得所有方法包括private声明的
			/*
			 * 如果方法有参,必须传入参数类型对应的class对象
			 * 这样做是因为方法会有重载,这样的话就避免了重载,指定了一个
			 */
			Method m3 = clazz.getDeclaredMethod("setName",String.class);
			Method m4 = clazz.getDeclaredMethod("getName",null);
			System.out.println(m1);
			for(Method m: m2) {
				System.out.println("方法"+m);
			}
		
			//获取类的构造器
			Constructor[] c1 = clazz.getConstructors();//获得所有构造器,但是private的不可以
			Constructor[] c2 = clazz.getDeclaredConstructors();//获得所有构造器,包括private
			Constructor c3 = clazz.getDeclaredConstructor(String.class);//获得指定构造器,
			
			System.out.println(c1);
			System.out.println(c3);
			for(Constructor c: c2) {
				System.out.println("构造器"+c);
			}
			//获取类的属性
			Field[] f1 = clazz.getFields();//获得所有public的属性
			Field[] f2 = clazz.getDeclaredFields();//获得包括有private的属性
			clazz.getDeclaredField("name");//获得指定属性
			System.out.println(f1.length);
			for(Field f : f2) {
				System.out.println("属性"+f);
			}
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	
	
	}
}

使用反射API操作属性和普通方法


package com.lrq.Reflection;

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

import org.junit.Test;

	@SuppressWarnings("deprecation")
	@Test
	public void Test2() {
		
		String path = new String("com.lrq.Reflection.Person");
		
		try {
			Class<Person> clazz = (Class<Person>)Class.forName(path);
			Person P1 = clazz.newInstance();//其实是调用了Person的无参方法
			System.out.println(P1);
			
			Constructor<Person> c = clazz.getDeclaredConstructor(String.class,int.class);
			Person P2 = c.newInstance("刘睿卿",22);
			System.out.println(P2.getName());
			
			//通过反射API调用普通方法
			Person P3 = clazz.newInstance();
			Method M1 = clazz.getDeclaredMethod("Show", null);
			M1.invoke(P3, null);//相当于 P3.Show();
			System.out.println(P3);
			
			//通过反射API操作属性
			Person P4 = clazz.newInstance();
			Field F = clazz.getDeclaredField("name");
			F.setAccessible(true);//这样设置就可以调用private 不要经过安全检查
			F.set(P4,"刘睿卿");//通过反射直接写属性
			
			System.out.println(P4.getName());//通过反射直接读属性的值
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	
	}
	
	
}

发布了29 篇原创文章 · 获赞 3 · 访问量 862

猜你喜欢

转载自blog.csdn.net/My_name_PeterLiu/article/details/104761960