反射
一、目的
-获取字节码文件,绕过new,直接获取对象
-为什么要绕过new方法?使用反射有什么优点?
-获取字节码文件的3种方法
.class()
.forName()
.getClass()
二、过程
(1) 获取字节码文件对象
Class<?> class1= person.getClass();//方法1
Class<?> class1 = Person.class;//方法2
Class<?> class1 = Class.forName("cn.leoxry.Person");//方法3 常用 使用更加灵活
(2) 通过字节码文件对象获取相应的实例对象
(2.1)通过无参的构造方法创建实例对象
Object obj = class1.newInstance();//这里相当于在newInstance方法的内部调用了无参的构造方法
Person person = (Person)obj;//创建实例对象
person.setName("test01");
(2.2)通过有参的构造方法创建实例对象
Constructor constructor = class1.getConstructor(String.class, int.class);
Object obj = constructor.newInstance("test01", 20);//创建实例对象
Person person = (Person)obj;
(3) 给属性赋值(通过从属性中提取出来的类-Field)
Class<?> class1 = class.forName("cn.leoxry.Person");
Object obj = class1.newInstance();
//Field field1 = class1.getField("name");//只能获取public类型的属性
Field field1 = class1.getDeclaredField("name");
field1.setAccessible(true);//暂时忽略权限
field1.set(obj, "test01");
System.out.println(field1.get(obj));
getDeclaredFiled()方法public和private类型的都可以获取吗?
(4) 调用方法(通过从方法中提取出来的类-Method)
(4.1)非静态无参方法的调用
Object obj = class1.newInstance();
Method method = class1.getMethod("show");//通过反射得到方法
method.invoke(obj);//通过调用invoke方法实现对show方法的调用
(4.2)非静态有参方法的调用
Constructor<?> constructor = class1.getConstructor(String.class, int.class);
Object obj = constructor.newInstance("test01", 10);
Method method = class1.getMethod("callPhone", String.class);
method.invoke(obj, "123");
(4.3)静态有参方法的调用
Method method = class1.getMethod("run", int.class);
method.invoke(null, 11);
(4.4)静态有参有返回值方法的调用
Method method = class1.getMethod("eat", String.class);
String st = (String)method.invoke(null, 11);
三、代码
_Reflect_01类(测试类)
package _Reflect;
import java.util.*;
import java.lang.reflect.*;
/**
*
* 反射:动态获取类的字节码文件,并对其成员进行抽象
*
* 过程:
* 1. 获取字节码文件对象
* 2. 通过字节码文件对象获取对应的实例对象
* 3. 给属性赋值(通过从属性中提取出来的类--Field)
* 4. 调用方法(通过从方法中提取出来的类--Method)
*
*/
public class _Reflect_01 {
public static void main(String args[]) {
//test01();
//test02();
//test03();
test04();
}
//获取字节码文件对象的3种方式
public static void test01() {
//1. 通过Object提供的getClass()方法
Person person = new Person();
Class<?> class1 = person.getClass();
//2. 通过类名.class获取
Class<?> class2 = Person.class;
//3. Class类提供的一个静态方法forName(字符串) 字符串:包名+类名
try {
Class<?> class3 = Class.forName("_Reflect.Person");
//System.out.println(class3.getName());
}
catch(ClassNotFoundException e) {
e.printStackTrace();
}
}
//通过字节码文件对象获取对应的实例对象
public static void test02() {
//方法一:通过无参的构造方法创建实例对象
try {
Class<?> class1 = Class.forName("_Reflect.Person");
Object obj = class1.newInstance();
Person person = (Person)obj;
person.setName("name01");
System.out.println(person);
}
catch(Exception e) {
e.printStackTrace();
}
//方法二:通过有参的构造方法创建实例对象
try {
Class<?> class2 = Class.forName("_Reflect.Person");
Constructor constructor = class2.getConstructor(String.class, int.class);
Object obj = constructor.newInstance("name02", 19);
System.out.println(obj);
}
catch(Exception e) {
e.printStackTrace();
}
}
//给属性赋值
public static void test03() {
try {
//1. 获取字节码文件
Class<?> class1 = Class.forName("_Reflect.Person");
//2. 获取实例对象
Object obj = class1.newInstance();
//3. 给属性赋值
//public属性的变量可以使用class1.getField("name")
//Field field1 = class1.getField("name");
//private属性的变量可以按照以下方式,获取和忽略权限
Field field1 = class1.getDeclaredField("name");
field1.setAccessible(true);
//赋值 第一个参数:关联的具体对象,第二个参数:赋的值
field1.set(obj, "name03");
System.out.println(obj);
}
catch(Exception e) {
e.printStackTrace();
}
}
//调用方法(通过从方法中提取出来的类--Method)
public static void test04() {
//调用非静态无参
try {
//1. 获取字节码文件
Class<?> class1 = Class.forName("_Reflect.Person");
//2. 获取实例对象
Object obj = class1.newInstance();
//3. 通过反射得到方法
Method method = class1.getMethod("show");
//4. 通过invoke方法实现实例对象的方法的调用
method.invoke(obj);
}
catch(Exception e) {
e.printStackTrace();
}
//调用非静态有参
try {
//1. 获取字节码文件
Class<?> class1 = Class.forName("_Reflect.Person");
//2. 获取实例对象
Object obj = class1.newInstance();
//3. 通过反射得到方法
Method method = class1.getMethod("callPhone", String.class);
//4. 通过invoke方法实现实例对象的方法的调用
method.invoke(obj, "17853312964");
}
catch(Exception e) {
e.printStackTrace();
}
//调用静态有参
try {
//1. 获取字节码文件
Class<?> class1 = Class.forName("_Reflect.Person");
//2. 通过反射获得方法
Method method = class1.getMethod("run", int.class);
//3. 通过invoke方法实现实例对象的方法的调用
method.invoke(null, 11);
}
catch(Exception e) {
e.printStackTrace();
}
//调用静态有参有返回值
try {
//1. 获取字节码文件
Class<?> class1 = Class.forName("_Reflect.Person");
//2. 通过反射获得方法
Method method = class1.getMethod("eat", String.class);
//3. 通过invoke方法实现实例对象的方法的调用
String st = (String)method.invoke(null, "apple");
System.out.println(st);
}
catch(Exception e) {
e.printStackTrace();
}
}
}
Person类
package _Reflect;
public class Person {
private String name;
int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
// TODO Auto-generated constructor stub
}
//非静态的无参方法
public void show() {
System.out.println("show");
}
//非静态的有参方法
public void callPhone(String tel) {
System.out.println("打电话给"+tel);
}
//静态的有参方法
public static void run(int num) {
System.out.println("run:" + num);
}
//静态的有参有返回值方法
public static String eat(String food) {
return "eat:" + food;
}
}