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
其余的操作和方法操作差不多,这里就不过的赘述了.
如果有不对的地方欢迎在留言区批评指正。如果觉得对请点个赞那是对我最大的支持~~