目录
2.getField(String name); 获取指定公共属性(public修饰的)
4.getDeclaredField(String name); 获取指定属性(不限制修饰符)
1.getMethods(); 返回所有公共成员方法(有参无参都可以)
2.getMethod(String name); 返回指定的公共无参成员方法
3.getDeclaredMethods(); 返回所有无参成员方法(不限制修饰符)
4.getDeclaredMethod(String name); 返回指定的无参成员方法(不限制修饰符)
1.getConstructors(); 返回公共无参构造方法数组
2.getConstructor()+newInstance(); 返回指定的公共构造方法+无参构造实例化
3.getConstructor(new Class[]{parameterTypes})+newInstance();
4.指定成员方法实例化:invoke(Object obj,Object... args);
一、反射的概念
Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象的称之为:反射。
二、获取全类名的三种方式
try {
Class c = Class.forName("com.atguigu.practices.reflection.Student");
System.out.println(c);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Student student = new Student();
Class c2 = student.getClass();
System.out.println(c2);
Class<Student> c3 = Student.class;
System.out.println(c3);
三、反射获取成员变量的方法
先创建一个Person类
package com.atguigu.practices.reflection;
public class Person {
private String name;
private Integer age;
public String gender;
public String address;
Integer score;
protected Boolean Chinese;
public Boolean getChinese() {
return Chinese;
}
public void setChinese(Boolean chinese) {
Chinese = chinese;
}
public void showInfo(){
System.out.println(this.getName()+","+this.getAge()+","+this.getGender());
}
public void showInfo2(){
System.out.println(this.getScore()+","+this.getAddress()+","+this.getChinese());
}
private void printSecr(){
System.out.println("私有方法");
}
public Person() {
}
public Person(Integer score, String address,Boolean Chinese) {
this.score = score;
this.address = address;
this.Chinese = Chinese;
}
public Person(String name, Integer age, String gender){
this.name = name;
this.age = age;
this.gender = gender;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
", score=" + score +
", address='" + address + '\'' +
'}';
}
public String getName() {
System.out.println("getName:"+name);
return name;
}
public void setName(String name) {
this.name = name;
}
private Integer getAge() {
return age;
}
public void setAge(Integer age) {
System.out.println("setAge:"+age);
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Integer getScore() {
return score;
}
public void setScore(Integer score) {
this.score = score;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public boolean isChinese() {
return Chinese;
}
public void setChinese(boolean chinese) {
Chinese = chinese;
}
}
- getFields(); 获取公共属性数组
- getField(String name); 获取指定公共属性(public修饰的)
- getDeclaredFields(); 获取所有属性
- getDeclaredField(String name); 获取指定属性(不限制修饰符)
1.getFields(); 获取公共属性数组
Field[] fields = c.getFields();
for (int i = 0; i < fields.length; i++) {// 遍历存放公共属性的数组
Field field = fields[i];
System.out.println(field.getName()+","+field.getType());
// getName():返回此field对象表示的字段的名称
// getType():返回该field对象表示的字段的声明类型
// gender,class java.lang.String
// 只遍历出了一个属性,说明getFields()只能访问到public修饰的属性及其对应的数据类型
}
/**
* 控制台输出:
* gender,class java.lang.String
* address,class java.lang.String
*/
2.getField(String name); 获取指定公共属性(public修饰的)
try {
Field age = c.getField("address");
System.out.println(age);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
/**
* 控制台输出:
* public java.lang.String com.atguigu.practices.reflection.Person.address
*/
3.getDeclaredFields(); 获取所有属性
fields = c.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
System.out.println(field.getName()+","+field.getType());
// 可以遍历出所有属性及其对应的数据类型
}
/**
* 控制台输出:
* name,class java.lang.String
* age,class java.lang.Integer
* gender,class java.lang.String
* score,class java.lang.Integer
* address,class java.lang.String
*/
4.getDeclaredField(String name); 获取指定属性(不限制修饰符)
try {
Field field = c.getDeclaredField("address");
System.out.println(field.getName()+","+field.getType());
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
/**
* 控制台输出:
* gender,class java.lang.String
*/
五、反射获取成员方法的方法
(一)获取Person类成员方法
- getMethods(); 返回所有公共成员方法
- getMethod(String name, Class<?>... parameterTypes)); 返回指定的公共成员方法
参数:name–方法的名称;parameterTypes–参数列表
- getDeclaredMethods(); 返回所有成员方法(不限制修饰符)
- getDeclaredMethod(String name); 返回指定的成员方法(不限制修饰符)
1.getMethods(); 返回所有公共成员方法(有参无参都可以)
Method[] methods = c.getMethods();
// foreach遍历成员方法数组
for (Method method :
methods) {
System.out.println(method.getName() + "," + method.isVarArgs());
}
/**
* method.getName()方法:
* 返回此method对象表示的方法的名称(字符串)。
* method.isVarArgs()方法:
* 如果此可执行文件声明为采用可变数量的参数,则返回true;否则返回false。
*/
// 控制台输出:
/**
* 返回Person类中所有public修饰的成员方法[数组]
* toString,false
* getAddress,false
* getName,false
* setName,false
* setAge,false
* setChinese,false
* setChinese,false
* showInfo2,false
* setGender,false
* getGender,false
* getScore,false
* setScore,false
* getChinese,false
* setAddress,false
* showInfo,false
* isChinese,false
* wait,false
* wait,false
* wait,false
* equals,false
* hashCode,false
* getClass,false
* notify,false
* notifyAll,false
*/
2.getMethod(String name); 返回指定的公共无参成员方法
try {
Method showInfoMethod = c.getMethod("showInfo");// 无参
Method setAgeMethod = c.getMethod("setAge",Integer.class);// 有参
System.out.println(showInfoMethod);
System.out.println(setAgeMethod);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
/**
* public void com.atguigu.practices.reflection.Person.showInfo()
* public void com.atguigu.practices.reflection.Person.setAge(java.lang.Integer)
*/
3.getDeclaredMethods(); 返回所有无参成员方法(不限制修饰符)
Method[] methods1 = c.getDeclaredMethods();
// for循环遍历
for (int i = 0; i < methods1.length; i++) {
Method m2 = methods1[i];
System.out.println(m2.getName() + "," + m2.isVarArgs());
}
/**
* 返回Person类中所有的成员方法[数组]
* toString,false
* getAddress,false
* getName,false
* setName,false
* setAge,false
* setChinese,false
* setChinese,false
* showInfo2,false
* printSecr,false
* getAge,false
* setGender,false
* getGender,false
* getScore,false
* setScore,false
* getChinese,false
* setAddress,false
* showInfo,false
* isChinese,false
*/
4.getDeclaredMethod(String name); 返回指定的无参成员方法(不限制修饰符)
try {
Method printSecrMethod = c.getDeclaredMethod("printSecr");
Method getNameMethod = c.getDeclaredMethod("setName",String.class);
System.out.println(printSecrMethod);
System.out.println(getNameMethod);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
// 控制台输出:
/**
* 返回任意无参成员方法,不限制修饰符
* private void com.atguigu.practices.reflection.Person.printSecr()
* private void com.atguigu.practices.reflection.Person.setName(java.lang.String)
*/
(二)获取Person类构造方法
- getConstructors(); 返回公共构造方法数组(不限制参数)
- getConstructor(new Class[]{parameterTypes}); 返回指定的公共构造方法
- getConstructor(); 返回公共无参构造
- newInstance(); 使用此构造函数对象表示的构造函数,使用指定的初始化参数创建和初始化构造函数声明类的新实例。单个参数会自动展开以匹配原始形式参数,并且原始参数和引用参数都会根据需要进行方法调用转换。
- invoke(Object obj,Object... args); 在具有指定参数的指定对象上调用此method对象表示的基础方法。单个参数会自动展开以匹配原始形式参数,并且原始参数和引用参数都会根据需要进行方法调用转换。
- obj–调用基础方法的对象;args–用于方法调用的参数
1.getConstructors(); 返回公共无参构造方法数组
Constructor[] constructors = c.getConstructors();
for (int i = 0; i < constructors.length; i++) {
Constructor constructor = constructors[i];
System.out.println(constructor.getName());
}
/**
* com.atguigu.practices.reflection.Person
* com.atguigu.practices.reflection.Person
* com.atguigu.practices.reflection.Person
*/
2.getConstructor()+newInstance(); 返回指定的公共构造方法+无参构造实例化
parameterTypes参数是一个Class对象数组,以声明的顺序标识构造函数的形式参数类型
try {
Constructor constructor = c.getConstructor();
System.out.println(constructor.getName());
//com.atguigu.practices.reflection.Person
// 无参构造方法初始化
Object obj = constructor.newInstance();
System.out.println(obj);
//Person{name='null', age=null, gender='null', score=null, address='null'}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
3.getConstructor(new Class[]{parameterTypes})+newInstance();
返回指定的公共有参构造方法+有参构造方法实例化
parameterTypes参数是一个Class对象数组,以声明的顺序标识构造函数的形式参数类型。
try {
Constructor constructor = c.getConstructor(new Class[]{String.class, Integer.class, String.class});
System.out.println(constructor.getName());
// com.atguigu.practices.reflection.Person
// 有参构造初始化
Object obj = constructor.newInstance("zhangsan", 45, "男");
System.out.println(obj);
// Person{name='zhangsan', age=45, gender='男', score=null, address='null'}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
4.指定成员方法实例化:invoke(Object obj,Object... args);
try {
Method method = c.getDeclaredMethod("showInfo2");
Object obj1 = c.getConstructor().newInstance();// 未传参
Constructor constructor = c.getConstructor(new Class[]{Integer.class, String.class, Boolean.class});
Object obj = constructor.newInstance(new Object[]{100,"上海路20号", true});// 传参
Object invoke = method.invoke(obj1,null);
// null,null,null
Object invoke2 = method.invoke(obj,null);
// 100,上海路20号,true
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
5.反射访问get方法
try {
// 找到方法后,即使传递很多参数也会自动匹配,前提是n个参数也能够自动匹配到类中的有参构造方法
Method getNameMethod = c.getDeclaredMethod("getName");
Constructor constructor = c.getConstructor(new Class[]{String.class,Integer.class,String.class});
Object obj = constructor.newInstance(new Object[]{"张三",20,"男"});
getNameMethod.invoke(obj,null);
// getName:张三
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
6.反射访问set方法
try {
// 基于字节码对象获取类的构造方法对象
Constructor con = c.getConstructor();
// 构建类的实例对象
Object obj = con.newInstance();
Method m=c.getDeclaredMethod("setName",String.class);
m.invoke(obj,"张三");
System.out.println(obj);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// Person{name='张三', age=null, gender='null', score=null, address='null'}