java 反射详解

目录

反射定义
反射实现
通过反射获取对应类的Class对象
根据对应类的Class对象得到全限定名、类名、包名
获取类的所有实现接口
获取类的属性(Filed 类)
通过Class对象构造对应的实例对象(不通过new)
修改或获取指定对象的属性
获取类的方法 (Method 类)
构造方法相关操作

反射定义

反射式在java程序运行时,我还能动态的得到某个对象的所有属性和方法信息。并且可以动态执行某个对象的指定方法,或修改指定属性。这就是反射。

java反射实现

首先定义我们的操作类,Person

public class Person  implements Serializable{
	/**
	 * 序列化  序列化编号
	 */
	private static final long serialVersionUID = -5293639382415756109L;
	public int pid;
	private String pname;
	
	public Person() {
		
	}
	public Person(String name) {
		this.pname = name;
	}
	
	public Person(int pid, String pname) {
		this.pid = pid;
		this.pname = pname;
	}
	public String getPname() {
		return pname;
	}
	
	//getPid是一个私有的方法
	public int getPid() {
		return pid;
	}
	
	public void setPid(int pid) {
		this.pid = pid;
	}
	
	public void setPname(String pname) {
		this.pname = pname;
	}
	
	//add是一个私有的方法
	private String add(Integer i, Integer j) {
		return i + j + "";
	}
}

通过反射获取对应类的Class对象

class对象在类加载时会由虚拟机内部产生,并且一个类有且只有一个对应的class对象。还有 基础数据类型、数组、包括关键字 void (void.class)都有对应的class对象.下面我们看看如何获取class对象

		//(1)类.class
		 Class c = Person.class;
		 
		// (2)对象名.getClass()
		 Person person = new Person();
		 Class c2 = person.getClass();
	
		// (3)Class.forName("全限定名")
		// 全限定名 一定是包含包名的 包名.类名
		 Class c3 = Class.forName("com.cpc.temp.Person");
	
		// (4)类.getClassLoader().loadClass("全限定名")
		 Class c4 = Person.class.getClassLoader().loadClass("com.cpc.temp.Person");

		// (5)子类.class.getSuperClass()
		// 这是等到父类class对象  (这返回的是Object的Class对象)
		Class c5 = Person.class.getSuperclass();
		
		// (6)包装类.class
		Class c6 = Integer.class;

根据对应类的Class对象得到全限定名、类名、包名

		 Class c1 = Class.forName("com.cpc.temp.Person");
		 System.out.println("全限定名" + c1.getName());
		 System.out.println("类名" + c1.getSimpleName());
		 System.out.println("包名" + c1.getPackage());

执行结果

全限定名com.cpc.temp.Person
类名Person
报名package com.cpc.temp

获取类的所有实现接口

		 Class c1 =  Person.class;
		 //这是所有接口对应的Class对象数组
		 Class[] classin = c1.getInterfaces();
		 //遍历
		 for(int i = 0; i < classin.length; i ++) {
			 System.out.println(classin[i].getName());
		 }

执行结果

java.io.Serializable

获取类的属性(Filed 类)

获取Class对象的属性返回的就是Filed类实例

		// 4获取类的属性(Filed 类)
		Class c1 = Person.class;
		// getField("属性名") 获取公有属性
		System.out.println("---------获取公有属性--------");
		Field pid = c1.getField("pid");
		// getName() 获取属性名
		System.out.println("pid的属性名" + pid.getName());
		// getModifiers() 获取访问修改符
		System.out.println("pid的访问修饰符" + pid.getModifiers());
		// 上面的getModifiers输出结果是数字,对应的修饰符就是下面几个常量值
		System.out.println("----属性访问修饰符------");
		System.out.println("public:" + Modifier.PUBLIC);
		System.out.println("private:" + Modifier.PRIVATE);
		System.out.println("protected:" + Modifier.PROTECTED);
		
		// getType() 获取属性的类型对应的Class对象
		System.out.println("----获取属性的类型对应的Class对象------");
		Class cla = pid.getType();
		System.out.println(cla.getName());
		
		// getDeclaredField("属性名") 获取私有属性值
		Field pname = c1.getDeclaredField("pname");
		System.out.println("-----获取私有属性----");
		//输出属性名
		System.out.println(pname.getName());
		//输出属性的访问修饰符
		System.out.println(pname.getModifiers());
		//setAccessible(true) 设置私有属性可访问
		pname.setAccessible(true);
		pname.set(person, "zs");
		System.out.println(person.getPname());
		
		// getDeclaredFields() 获取所有的属性(公有私有都能获取到)
		Field[] fileds = c1.getDeclaredFields();
		System.out.println("------遍历所有属性,并输出属性名-----");
		for (Field field : fileds) {
			System.out.println(field.getName());
		}

执行结果

---------获取公有属性--------
pid的属性名pid
pid的访问修饰符1
----属性访问修饰符------
public:1
private:2
protected:4
----获取属性的类型对应的Class对象------
int
-----获取私有属性----
pname
2
zs
------遍历所有属性,并输出属性名-----
serialVersionUID
pid
pname

通过Class对象构造对应的实例对象(不通过new)

		Class c1 = Person.class;
		Person p = (Person)c1.newInstance();

修改或获取指定对象的属性

		Class c1 = Person.class;
		Field pid = c1.getField("pid");
		Person p = (Person) c1.newInstance();
		// 修改person的
		pid.set(person, 1);
		//// get(对象名)=对象名.get属性名 获取属性值
		System.out.println(pid.get(person));

执行结果

1

获取类的方法 (Method 类)

		Class c1 = Person.class;
		Object object = c1.newInstance();
		// getMethod(方法名,参数数据类型(无参数传Null)) 获取公共方法
		Method setPid = c1.getMethod("setPid", int.class);
		// invok (对象名, 参数列表)=对象名.方法名 执行方法
		setPid.invoke(object, 1);
		Method getPid = c1.getMethod("getPid", null);
		System.out.println("执行公共getPid返回结果:" + getPid.invoke(object, null));

		// getDeclaredMethod(方法名,参数数据类型(无参数传null)) 获取私有方法
		Method add = c1.getDeclaredMethod("add", Integer.class, Integer.class);
		add.setAccessible(true);
		System.out.println("执行私有add返回结果:" + add.invoke(object, 1, 2));
		// getReturnType() 得到返回值方法的数据类型的Class对象
		Class re = add.getReturnType();
		System.out.println("add方法的返回类型"+re.getName());

		// getParameterTypes() 得到方法参数列表()
		Class[] cal = add.getParameterTypes();
		System.out.println("----遍历add的参数列表------开始");
		for (Class cc : cal) {
			System.out.println(cc.getName());
		}
		System.out.println("----遍历add的参数列表------结束");
		// getDeclaredMethods() 得到类的所有方法
		Method[] methods = c1.getDeclaredMethods();
		System.out.println("-----遍历所有方法----开始");
		for (Method method : methods) {
			System.out.println(method.getName());
		}
		System.out.println("-----遍历所有方法-----结束");

执行结果

执行公共getPid返回结果:1
执行私有add方法:3
add方法的返回类型java.lang.String
----遍历add的参数列表------开始
java.lang.Integer
java.lang.Integer
----遍历add的参数列表------结束
-----遍历所有方法----开始
add
setPid
getPname
getPid
setPname
-----遍历所有方法-----结束

构造方法相关操作

		Class c1 = Person.class;
		// getConstructor 得到构造方法
		Constructor con = c1.getConstructor(int.class, String.class);
		// 通过指定构造方法构造对象
		Person p1 = (Person) con.newInstance(1, "张三");
		System.out.println("获取通过指定构造方法构造出来的p1对象的属性");
		System.out.println(p1.getPid());
		System.out.println(p1.getPname());
		// gitConstructors 获取所有构造方法 并输出构造方法的参数个数
		Constructor[] constructors = c1.getConstructors();
		System.out.println("------遍历构造方法-----");
		for (Constructor constructor : constructors) {
			System.out.println(constructor.getParameterCount());
		}

执行结果

获取通过指定构造方法构造出来的p1对象的属性
1
张三
------遍历构造方法-----
2
1
0

其余的操作和方法操作差不多,这里就不过的赘述了.

如果有不对的地方欢迎在留言区批评指正。如果觉得对请点个赞那是对我最大的支持~~

posted @ 2019-05-31 20:02  小cai一碟  阅读(811)  评论(1编辑  收藏  举报