1. 反射获取字节码(Class对象)
class="java" name="code">
Java 反射机制是在运行状态中,对于任意一个类,都能够获得这个类的所有属性和方法,对于任意一个对象都能够调用它的任意一个属性和方法。
这种在运行时动态的获取信息以及动态调用对象的方法的功能称为 Java 的反射机制。
1. 要想使用反射,首先需要获得待处理类或对象所对应的Class对象。获取某个类或某个对象所对应的Class对象的常用的3种方式:
a) 使用Class类的静态方法forName
Class.forName("java.lang.String");
b) 使用类的.class语法
String.class;
c) 使用对象的getClass()方法
String str = "abc";
Class<?> strClass = str.getClass();
import java.lang.reflect.Method;
public class DumpMethods {
public static void main(String[] args) throws Exception {
// 方式一
// Class<?> classType = Class.forName("java.lang.String");
// 方式二
// Class<?> classType = String.class;
// 方式三
String str = "abc";
Class<?> classType = str.getClass();
Method[] methods = classType.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
}
}
运行结果:
...
public java.lang.String java.lang.String.toUpperCase(java.util.Locale)
public java.lang.String java.lang.String.trim()
2. 反射获取类信息
1. 通过反射机制获取类的构造函数,通过构造函数创建类的实例。
1) 若想通过类的不带参数的构造方法来生成对象,我们有两种方式:
a) 先获得Class对象,然后通过该Class对象的newInstance()方法直接生成即可:
Class<?> classType = String.class;
Object obj = classType.newInstance();
b) 先获得Class对象,然后通过该对象获得对应的Constructor对象,再通过该Constructor对象的newInstance()方法生成:
Class<?> classType = Customer.class;
Constructor cons = classType.getConstructor(newClass[]{});
Object obj = cons.newInstance(newObject[]{});
2) 若想通过类的带参数的构造方法生成对象,只能使用下面这一种方式:
Class<?> classType = Customer.class;
Constructor cons = classType.getConstructor(newClass[]{String.class,int.class});
Object obj = cons.newInstance(newObject[]{"hello", 3});
import java.lang.reflect.Constructor;
public class ReflectTest {
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("reflex.Person");
Constructor<Person> constructor1 = clazz.getConstructor();
Constructor<Person> constructor2 = clazz.getConstructor(String.class);
// 无参方式一
Person person11 = (Person) clazz.newInstance();
// 无参方式二
Person person12 = constructor1.newInstance();
// 有参方式
Person person2 = constructor2.newInstance("andrew");
}
}
class Person {
public Person() {
System.out.println("我是路人");
}
public Person(String name) {
System.out.println("我是:" + name);
}
}
运行结果:
我是路人
我是路人
我是:andrew
2. 通过反射机制获取类的属性。
1) 获取class类: Class<?> classType = InvokeTester.class;
2) 实例化: Object invokeTester = classType.newInstance();
3) 获取field
public字段: Field publicField = clazz.getField("age");
private字段: Field privateField = clazz.getDeclaredField("name");
4) 赋值:
public字段: publicField.set(person, 20);
private字段: privateField.setAccessible(true); // 对私有字段的访问取消检查
privateField.set(person, "tony");
5) 取值: privateField.get(person)
import java.lang.reflect.Field;
public class ReflectTest {
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("reflex.Person");
Person person = (Person) clazz.newInstance();
// public字段
Field publicField = clazz.getField("age");
publicField.set(person, 20);
System.out.println(publicField.get(person));
// private字段
// Field privateField = clazz.getField("name"); //java.lang.NoSuchFieldException
Field privateField = clazz.getDeclaredField("name");
privateField.setAccessible(true); // 对私有字段的访问取消检查
privateField.set(person, "tony");
System.out.println(privateField.get(person));
}
}
class Person {
public int age;
private String name;
public Person() {
System.out.println("我是路人");
}
public Person(String name) {
System.out.println("我是:" + name);
}
}
运行结果:
我是路人
20
tony
3. 通过反射机制获取类的方法,并调用方法。
1) 获取class类: Class<?> classType = InvokeTester.class;
2) 实例化: Object invokeTester = classType.newInstance();
3) 获取方法: Method addMethod = classType.getMethod("add", new Class[]{int.class, int.class});
4) 调用方法: Object addResult = addMethod.invoke(invokeTester, new Object[]{1, 2});
import java.lang.reflect.Method;
public class InvokeTester{
public int add(int param1, int param2){
return param1 + param2;
}
public String echo(String message){
return "hello: " + message;
}
public static void main(String[] args) throws Exception{
// InvokeTester test = new InvokeTester();
// System.out.println(test.add(1, 2));
// System.out.println(test.echo("tom"));
Class<?> classType = InvokeTester.class;
Object invokeTester = classType.newInstance();
// System.out.println(invokeTester instanceof InvokeTester);
Method addMethod = classType.getMethod("add", new Class[]{int.class, int.class});
Object addResult = addMethod.invoke(invokeTester, new Object[]{1, 2});
System.out.println((Integer)addResult);
Method echoMethod = classType.getMethod("echo", new Class[]{String.class});
Object echoResult = echoMethod.invoke(invokeTester, new Object[]{"tom"});
System.out.println((String)echoResult);
}
}
运行结果:
3
hello: tom
3. 使用反射拷贝对象
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectTester {
// 该方法实现对Customer对象的拷贝操作
public Object copy(Object object) throws Exception{
Class<?> classType = object.getClass();
Object objectCopy = classType.getConstructor(new Class[]{}).newInstance(new Object[]{});
Field[] fields = classType.getDeclaredFields();
for (Field field : fields) {
String name = field.getName();
String firstLetter = name.substring(0, 1).toUpperCase(); // 将属性的首字母转换为大写
String getMethodName = "get" + firstLetter + name.substring(1);
String setMethodName = "set" + firstLetter + name.substring(1);
Method getMethod = classType.getMethod(getMethodName, new Class[]{});
Method setMethod = classType.getMethod(setMethodName, new Class[]{ field.getType() });
Object value = getMethod.invoke(object, new Object[]{});
setMethod.invoke(objectCopy, new Object[]{ value });
}
return objectCopy;
}
public static void main(String[] args) throws Exception{
Customer customer = new Customer("anderw", 20);
customer.setId(1L);
ReflectTester test = new ReflectTester();
Customer customer2 = (Customer) test.copy(customer);
System.out.println(customer2.getId() + "," + customer2.getName() + ","+ customer2.getAge());
}
}
class Customer{
private Long id;
private String name;
private int age;
public Customer() {
}
public Customer(String name, int age) {
this.name = name;
this.age = age;
}
public Long getId() {return id;}
public void setId(Long id) {this.id = id;}
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;}
}
运行结果:
1,anderw,20
4. 使用反射
数组与反射
import java.lang.reflect.Array;
public class ArrayTester1 {
public static void main(String[] args) throws Exception{
Class<?> classType = Class.forName("java.lang.String");
Object array = Array.newInstance(classType, 10);
Array.set(array, 5, "hello");
String str = (String)Array.get(array, 5);
System.out.println(str);
}
}
运行结果:
hello
Class对象的getComponentType()方法返回一个数组类型的对象
import java.lang.reflect.Array;
public class ArrayTester2{
public static void main(String[] args){
int[] dims = new int[] { 5, 10, 15 };
Object array = Array.newInstance(Integer.TYPE, dims);
System.out.println(array instanceof int[][][]);
Object arrayObj = Array.get(array, 3);
Class<?> classType = arrayObj.getClass().getComponentType();
System.out.println(classType);
arrayObj = Array.get(arrayObj, 5);
Array.setInt(arrayObj, 10, 37);
int[][][] arrayCast = (int[][][]) array;
System.out.println(arrayCast[3][5][10]);
System.out.println(Integer.TYPE);
System.out.println(Integer.class);
}
}
运行结果:
true
class [I
37
int
class java.lang.Integer
反射调用对象的私有方法
public class Private{
private String sayHello(String name){
return "hello: " + name;
}
}
import java.lang.reflect.Method;
public class TestPrivate{
public static void main(String[] args) throws Exception{
Private p = new Private();
Class<?> classType = p.getClass();
Method method = classType.getDeclaredMethod("sayHello",
new Class[] { String.class });
method.setAccessible(true);//压制Java的访问控制检查
String str = (String)method.invoke(p, new Object[]{"zhangsan"});
System.out.println(str);
}
}
运行结果:
hello:zhangsan
反射调用对象的get方法
public class Private2{
private String name = "zhangsan";
public String getName(){
return name;
}
}
import java.lang.reflect.Field;
public class TestPrivate2{
public static void main(String[] args) throws Exception{
Private2 p = new Private2();
Class<?> classType = p.getClass();
Field field = classType.getDeclaredField("name");
field.setAccessible(true);//压制Java对访问修饰符的检查
field.set(p, "lisi");
System.out.println(p.getName());
}
}
运行结果:
lisi
获取已知class的父类
public class ClassTest {
public static void main(String[] args) {
Class<?> classType = Child.class;
System.out.println(classType);
classType = classType.getSuperclass();
System.out.println(classType);
classType = classType.getSuperclass();
System.out.println(classType);
classType = classType.getSuperclass();
System.out.println(classType);
}
}
class Parent{}
class Child extends Parent{}
运行结果:
class org09.Child
class org09.Parent
class java.lang.Object
null
推荐博客:
https://blog.csdn.net/sinat_38259539/article/details/71799078