反射机制简介
反射其实就是动态的加载类,我们在写JDBC的时候加载驱动Class.forName("xxx")时就涉及到了反射。
反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射机制功能
- 在运行时判断任意一个对象的所属的类Class。
- 在运行时判断构造任意一个类的对象Constructor。
- 在运行时判断任意一个类所具有的成员变量Field和方法Method。
- 在运行时调用任意一个对象的方法,例如:method.invoke(object,args)
反射相关 API
主要API有以下几个:
- java.lang.Class:代表一个类
- java.lang.reflect.Method:代表类的方法
- java.lang.reflect.Field:代表类的成员变量
- java.lang.reflect.Constructor:代表类的构造方法
其他API有:
- java.lang.reflect.getName():获得类的完整名字。
- java.lang.reflect.getDeclaredFields():获得类的所有属性。包括private 声明的和继承类
- java.lang.reflect.getDeclaredMethods():获得类的所有方法。包括private 声明的和继承类
- java.lang.reflect.newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
获得完整的包名和类名
Student.java
package com.reflect.test;
public class Student {
private int id;
private String name;
public Student() {}
public Student(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + "]";
}
}
Test.java
package com.reflect.test;
public class Test {
Student stu = new Student();
public static void main(String[] args) {
Test test = new Test();
test.getClassName();
}
//获得完整的包名和类名
public void getClassName() {
System.out.println(stu.getClass().getName());
}
}
运行结果:
com.reflect.test.Student
获取Class的三种方法
public static void main(String[] args) {
Test test = new Test();
test.getStudentClass();
}
//获取Class对象的三种犯法
public void getStudentClass() {
//第一种方法,forName
Class<?> class1;
try {
class1 = Class.forName("com.reflect.test.Student");
System.out.println("class1:"+class1);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//第二种方法,class
Class<?> class2 = Student.class;
System.out.println("class2:"+class2);
//第三种方法,getClass()
Student stu1 = new Student();
Class<?> class3 = stu1.getClass();
System.out.println("class3:"+class3);
}
运行结果
class1:class com.reflect.test.Student
class2:class com.reflect.test.Student
class3:class com.reflect.test.Student
完整调用案例示例
用户类:
package com;
public class UserEntity {
private String userName;
private int userAge;
private final int money = 10000;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getUserAge() {
return userAge;
}
public void setUserAge(int userAge) {
this.userAge = userAge;
}
//借钱方法
public int getMoney(){
System.out.println("你借了 " + money + "元!");
return money;
}
//还钱方法,单个参数
public void repay(int money){
System.out.println("你还了 " + money + "元!");
}
//还钱方法,多个参数
public void repay(String userName,int money){
System.out.println(userName+ " 还了 " + money + "元!");
}
}
测试类:
package com;
import java.lang.reflect.Method;
public class Reflection {
//反射调用方法获取返回值
//第一种方法,获取对象,直接通过对象调用方法
//第二种方法,通过方法名获取方法,执行方法
public static void main(String[] args) throws Exception {
Class<?> userClass = Class.forName("com.UserEntity");
UserEntity userEntity = (UserEntity) userClass.newInstance();
//第一种方法
System.out.println("第一次借钱:");
int money = userEntity.getMoney();
System.out.println("实际拿到钱为: " + money);
System.out.println("------------------------分割线------------------------");
//第二种方法,(无参的示例:借钱)
System.out.println("第二次借钱:");
Method getMoney = userClass.getMethod("getMoney");//得到方法对象
Object money2 = getMoney.invoke(userEntity);//调用借钱方法,得到返回值
System.out.println("实际拿到钱为:" + money2);
System.out.println("------------------------分割线------------------------");
//第二种方法,(单个参数的示例:还钱)
System.out.println("第一次还钱:");
Method repay1 = userClass.getMethod("repay",int.class);//得到方法对象,有参的方法需要指定参数类型
repay1.invoke(userEntity,3000);//执行还钱方法,有参传参
System.out.println("------------------------分割线------------------------");
//第二种方法,(单个参数的示例:还钱)
System.out.println("第二次还钱:");
Method repay2 = userClass.getMethod("repay", String.class,int.class);//得到方法对象,有参的方法需要指定参数类型
repay2.invoke(userEntity,"小飞",5000);//执行还钱方法,有参传参
}
}