01-反射

反射

Class类

java.lang.Class类的理解:

1、类的加载过程
程序经过javac.exe命令以后 会生成一个或多个字节码文件 (.class)接着我们使用java.exe命令对某个字节码文件进行解释运行 相当于将某个字节码文件加载到内存中 此过程称为类的加载。加载到内存中的类 我们就称为运行时类 此运行时类就作为Class的一个实例

获取Class类实例的4种方式

方式一 调用运行时类的属性

Class clazz1 = Person.class;

方式二 通过运行时类的对象

Person p1 = new Person();
Class clazz2 = p1.getClass();

方式三 调用Class静态方法 forName(String classPath)

Class clazz3 = Class.forName(“com.lili.Person”);

方式四 使用类的加载器

ClassLoader classLoader = ReflectionTest.class.getClassLoader();
Class clazz4 = classLoader.loadClass(“com.lili.Person”);

System.out.println(clazz1==clazz2);//true
加载到内存中的运行时类 会缓存一段时间 在此时间段内 可以通过不同的方式来获取此运行时类

哪些类可以获取Class对象

1、class:

内部类 成员(成员内部类 静态内部类) 局部内部类 匿名内部类

2、interface
3、[]数组
4、enum 枚举
5、annotation 注解
6、primitive type 基本数据类型
7、void

Class c1=Object.calss;
Class c2 = Comparable.class;
Class c3 = String[].class;
Class c4 = Override.class;
Class c5 = int.class;
Class c6 = void.class;

int[] a = new int[10];
int[] b = new int[100];
Class c10 = a.getClass();
Class c11 = b.getClass();
System.out.println(c10==c11);//true
只要数组的元素类型与纬度相同 就是同一个Class

读取properties文件

1、新建jdbc.properties文件 文件内容为:

user=lili
password=mysql

方式一 文件默认在当前module下

Properties pros = new Properties();
FileInputStream fis = new FileInputStream(“jdbc.properties”);
pros.Load(fis);

**方式二 使用ClassLoader 默认位置在src下
ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream(“jdbc.properties”);
pros.load(is);

String user = pros.getProperties(“user”);

创建运行时类的对象

	Class<Person> clazz = Person.class;
	//内部调用的是无参构造器
	//要求:
	//1、运行时类必须提供空参构造器
	//2、空参构造器访问权限得够 通常设置为public
	Person obj = clazz.newInstance();
	//在javabean 中要提供一个public 空参构造器原因:
	//1、便于通过反射 创建运行时类对象
	//2、便于子类继承此类 默认调用super()保证父类由有此构造器

获取运行时类的属性和方法

	Class clazz = Person.class;
	//getFields() 获取当前运行时类及其父类中声明为public访问权限的属性
	Field[] fields = clazz.getFields();
	//getDeclaredFields() 获取当前运行时类中声明的所有属性 不包括父类中的属性
	Field[] dfields = clazz.getDeclaredFields();
	
	//getMethods() 获取当前运行时类及其父类中声明为public访问权限的方法
	Method[] methods = clazz.getMethods();
	//getDeclaredFields() 获取当前运行时类中声明的所有方法 不包括父类中的方法
	Method[] dmethods = clazz.getDeclaredMethodss();

	//getConstructors() 获取当前运行时类及其父类中声明为public访问权限的构造器
	Constructor[] constructors = clazz.getConstructors();
	//getDeclaredConstructors() 获取当前运行时类中声明的所有构造器 不包括父类中的构造器
	Constructor[] dconstructors = clazz.getDeclaredConstructors();
	
	//获取运行时类的父类
	Class superClass=clazz.getSuperclass();
	//获取运行时类带泛型的父类
	Type genericSuperClass=clazz.getGenericSuperclass();

	//获取运行时类实现的接口
	Class[] interfaces =clazz.getInterfaces();

	//获取运行时类所在包
	Package pack=clazz.getPackage();

	//获取运行时类声明的注解
	Annotation[] annotations=clazz.getAnnotations();

	//以下了解即可
	for(Field f:dfields){
		//1 权限修饰符
		int modifier =f.getModifiers();
		System.out.println(Modifier.toString(modifier)+"\t");
		//2、数据类型
		Class type = f.getType();
		System.out.println(type.getName());
		//3、变量名
		String fname=f.getName();
	}
	for(Method m:dmethods){
		//1 权限修饰符
		int modifier =m.getModifiers();
		System.out.println(Modifier.toString(modifier)+"\t");
		//2、返回值类型
		Class type = m.getReturnType();
		System.out.println(type.getName());
		//3、获取方法声明的注解
		Annotation[] annos=m.getAnnotations();
		for (Annotation a :annos){
			System.out.println(a);
		}
		//4、获取方法名
		System.out.println(m.getName());
		//5、获取形参列表
		Class[] parameterTypes=m.getParameterTypes();
		if(!(parameterTypes==null && parameterTypes.length==0)){
			for(Class p :parameterTypes){
				System.out.println(p.getName());
			}
		}
	}

获取指定属性、方法和构造器

	Pserson p =(Person) clazz.newInstance();
	//要求属性声明为public
	Field id = clazz.getField("id");
	//不要求属性声明为public
	Field id2 = clazz.getDeclaredField("id");
	id.set(p,1001);
	int pid = id.get(p);
	
	//不要求属性声明为public
	Field name = clazz.getDeclaredField("name");
	name.setAccessible(true);//设置为true才能修改
	name.set(p,"lili");

	//参数1 指明获取方法的名称 参数2 指明获取的方法的形参列表
	Method show = calzz.getDeclaredMethod("show",String.class);
	show.setAccessible(true);//保证当前方法可访问
	//参数1 方法的调用者 参数2 给方法形参赋值的实参
	Object returnValue=show.invoke(p,"CHN");
	***************************
	//调用静态方法 调用静态属性也类似
	Method showDesc = clazz.getDeclaredMethod("showDesc");//无参方法
	showDesc.setAccessible(true);
	//如果运行时类的方法无返回值 则invoke返回null
	Obejct returnValue = showDesc.invoke(Person.class);
	***************************
	//调用治党构造器
	Constructor constructor = clazz.getDeclaredConstructor(String.class);
	//保证构造器是可访问的
	constructor.setAccessible(true);
	//调用此类创建对象
	Person per =(Person) constrructor.newInstance("Tom");
上一篇:Java 反射机制


下一篇:dubbo spi