什么是反射
反射是程序运行过程中,对于任意一个类,都可以获得这个类的属性和公有方法(公有私有属性方法都可以获得,只不过获得有区别);对于任意一个对象,都可以调用它的属性和方法.
反射的作用
- 在运行时获得一个对象所属的类(即可以根据这个对象获得这个类的名称,地址等信息,粗浅理解,帮助记忆)
- 在运行时实例化一个类的对象
- 在运行时获得和使用一个对象的方法和属性
- 动态代理
反射的使用
前提:先创建几个类和接口,后面使用:
People.java
public class People {
private int height;
private int weight;
public int test1;
int test2;
protected int test3;
public People() {
super();
}
public People(int height, int weight) {
super();
this.height = height;
this.weight = weight;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
Student.java
public class Student extends People implements StudentInterface1,StudentInterface2{
private String id="144520";
private String name="大明";
private String gender;
public Student() {
super();
}
public Student(String id, String name, String gender) {
super();
this.id = id;
this.name = name;
this.gender = gender;
}
public Student(String id,String name){
this.id=id;
this.name=name;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", gender=" + gender + "]";
}
public String getId() {
return id;
}
public void setId(String id,String name) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public void setPassword() {
}
@Override
public void getPassword() {
}
}
StudentInterface1.java
public interface StudentInterface1 {
public void setPassword();
}
StudentInterface2.java
public interface StudentInterface2 {
public void getPassword();
}
通过一个对象获得完整的包名和类名
- 方法一(常用)
Class c1=Class.forName("com.reflex.Student");
- 方法二
Class c1=Student.class;
- 方法三
Student student = new Student();
Class c1 = student.getClass();
System.out.println(c1);
实例化一个对象
Class c = Class.forName("com.reflex.Student");
// 创建一个Class的一个实例
Object o = c.newInstance();// 调用Student的一个无参构造方法
System.out.println(c.getName());
获得对象的父类和实现的接口
Class c = Class.forName("com.reflex.Student");
// 获得父类
Class parentClass = c.getSuperclass();
System.out.println(parentClass);
// 获得接口
Class intf[] = c.getInterfaces();
for (int i = 0; i < intf.length; i++) {
System.out.println(intf[i]);
}
获得构造方法
Class c = Class.forName("com.reflex.Student");
// 一、实例化一个无参构造方法,对对象set值
Student student = (Student) c.newInstance();
student.setId("144520", "");
student.setName("小明");
student.setGender("男");
// 取Student对象的值
System.out.println(student.toString());
// 二、获得全部的构造方法,通过对构造方法传参数来赋值对象的成员变量
Constructor cons[] = c.getConstructors();
// 遍历每个构造方法
for (int i = 0; i < cons.length; i++) {
System.out.println("第" + (i + 1) + "个构造方法");
// 获得每个构造方法的参数类型
Class para[] = cons[i].getParameterTypes();
for (int j = 0; j < para.length; j++) {
System.out.println("[" + j + "]" + para[j]);
}
}
// 对三个参数的构造方法进行传参数(此处没有详写,直接传参)
Student stu = (Student) cons[1].newInstance("1545245", "小花", "test");
System.out.println(stu.toString());
//另一种使用构造的方法是
//查看API有两个方法,分别是getConstructor(Class...)和newInstance(Class...)
//举例含有2个参数的构造方法
Student stu1 = c.getConstructor(String.class,String.class).newInstance("001","小明");
获得对象的所有成员变量
Class c = Class.forName("com.reflex.Student");
// 一、获得本对象的属性
System.out.println("获得本对象的属性");
Field field[] = c.getDeclaredFields();
for (int i = 0; i < field.length; i++) {
// 得到权限修饰符
int modify = field[i].getModifiers();
String modifyStr = Modifier.toString(modify);
// 得到属性的类型
Class type = field[i].getType();
// 输出这个变量
System.out.println(modifyStr + " " + type + " " + field[i].getName());
}
// 二、获得父类或者接口的公共属性,只有public修饰的才能获得
System.out.println("获得父类或者接口的公共属性");
Field paraentField[] = c.getFields();// 这个方法返回的是父类或者接口可以访问的公共属性,私有属性不会返回
for (int i = 0; i < paraentField.length; i++) {
// 获得权限修饰符
int paraentModify = paraentField[i].getModifiers();
String paraentModifyStr = Modifier.toString(paraentModify);
// 获得类型
Class paraentType = paraentField[i].getType();
System.out.println(paraentModifyStr + " " + paraentType + " " + paraentField[i].getName());
}
获得对象的所有公共方法
Class c = Class.forName("com.reflex.Student");
// 获得所有公共的方法
Method[] method = c.getMethods();
for (int i = 0; i < method.length; i++) {
// 获得方法的修饰符
int modify = method[i].getModifiers();
String modifyStr = Modifier.toString(modify);
// 获得方法的返回类型
Class returnType = method[i].getReturnType();
// 获得参数的类型
Class para[] = method[i].getParameterTypes();
System.out.print(modifyStr + " " + returnType + " " + method[i].getName() + "( ");
// 循环遍历参数类型
for (int j = 0; j < para.length; j++) {
System.out.print(para[j].getName() + " ");
}
System.out.println(")");
}
通过反射机制调用对象的方法
Class c = Class.forName("com.reflex.Student");
// 一、调用对象的方法一
Method method = c.getMethod("getId");
Object o = null;
method.invoke(o = c.newInstance());
// 测试
// 获取id的属性
Field idF = c.getDeclaredField("id");
// 打破封装
idF.setAccessible(true);
System.out.println(idF.get(o));
// 二、调用对象的方法二
method = c.getMethod("setId", String.class, String.class);
method.invoke(c.newInstance(), "123456789", "test");
打破封装,操作对象的属性
Class c = Class.forName("com.reflex.Student");
// 获得属性
Field nameF = c.getDeclaredField("name");
// 实例化
Object o = c.newInstance();
// 打破封装
nameF.setAccessible(true);
// 对属性name赋值
nameF.set(o, "test name");
System.out.println(nameF.get(o));// 这个地方的取值跟传统方法不同
未完待续,伸个懒腰,先睡一觉:)