反射:将类的各个组成部分封装为其他对象,这就是反射机制。
反射好处:(1)可以在程序运行过程中,操作这些对象。(2)可以解耦,提高程序的可扩展性。
获取Class对象的方式:
- Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象。(多用于配置文件,将类名定义在配置文件中。读取文件,加载类)
- 类名.class:通过类名的属性class获取。(多用于参数的传递)
- 对象.getClass():getClass()方法在Object类中定义着。(多用于对象的获取字节码的方式)
package com.calvin.reflect;
/**
* @Title ReflectDemo01
* @Description
* @author calvin
* @date: 2020/2/9 9:24 PM
*/
public class ReflectDemo01 {
public static void main(String[] args) throws Exception {
// 1.Class.forName("全类名")
Class class1 = Class.forName("com.calvin.reflect.Person");
System.out.println("class1:" + class1);
// 2.类名.class
Class class2 = Person.class;
System.out.println("class2:" + class2);
// 3.对象.getClass()
Person p = new Person();
Class class3 = p.getClass();
System.out.println("class3:" + class3);
System.out.println(class1 == class2);
System.out.println(class2 == class3);
}
}
其中Person类的代码如下:
package com.calvin.reflect;
import lombok.Data;
import lombok.ToString;
/**
* @Title Person
* @Description
* @author calvin
* @date: 2020/2/9 9:23 PM
*/
@Data
@ToString // 使用lombok来自动生成get,set,toString方法
public class Person {
private String name;
private int age;
public String a;
protected String b;
String c;
private String d;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
}
private Person(String name, String c) {
this.name = name;
this.c = c;
}
public void eat() {
System.out.println("eat...");
}
public void eat(String food) {
System.out.println("eat..." + food);
}
private void run(String miles) {
System.out.println("run..." + miles);
}
}
控制台输出结果:
class1:class com.calvin.reflect.Person
class2:class com.calvin.reflect.Person
class3:class com.calvin.reflect.Person
true
true
结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
接着我们去使用class对象的功能
(1)获取成员变量
package com.calvin.reflect;
import java.lang.reflect.Field;
/**
* @Title ReflectDemo02
* @Description
* @author calvin
* @date: 2020/2/9 9:50 PM
*/
public class ReflectDemo02 {
public static void main(String[] args) throws Exception {
// 0.获取Person的Class对象
Class personClass = Person.class;
// 1.Field[] getFields() 获取所有public修饰的成员变量
Field[] fields = personClass.getFields();
for (Field field : fields) {
System.out.println("field:" + field);
}
// 2.Field getField(String name) 获取指定名称的public修饰的成员变量
Field a = personClass.getField("a");
System.out.println("a:" + a);
// 获取成员变量a的值
Person p = new Person();
Object value = a.get(p);
System.out.println("value:" + value);
// 设置a的值
a.set(p, "张三");
System.out.println("p:" + p);
Object value2 = a.get(p);
System.out.println("value2:" + value2);
// 3.Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符
Field[] declaredFields = personClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("declaredField:" + declaredField);
}
// 4.Field getDeclaredField(String name) 获取指定名称的成员变量,不考虑修饰符
Field d = personClass.getDeclaredField("d");
System.out.println("d:" + d);
// 忽略访问权限修饰符的安全检查(暴力反射)
d.setAccessible(true);
Object value3 = d.get(p);
System.out.println("value3:" + value3);
d.set(p, "222");
System.out.println("p:" + p);
Object value4 = d.get(p);
System.out.println("value4:" + value4);
}
}
控制台输出:
field:public java.lang.String com.calvin.reflect.Person.a
a:public java.lang.String com.calvin.reflect.Person.a
value:null
p:Person(name=null, age=0, a=张三, b=null, c=null, d=null)
value2:张三
declaredField:private java.lang.String com.calvin.reflect.Person.name
declaredField:private int com.calvin.reflect.Person.age
declaredField:public java.lang.String com.calvin.reflect.Person.a
declaredField:protected java.lang.String com.calvin.reflect.Person.b
declaredField:java.lang.String com.calvin.reflect.Person.c
declaredField:private java.lang.String com.calvin.reflect.Person.d
d:private java.lang.String com.calvin.reflect.Person.d
value3:null
p:Person(name=null, age=0, a=张三, b=null, c=null, d=222)
value4:222
(2)获取构造方法
package com.calvin.reflect;
import java.lang.reflect.Constructor;
/**
* @Title ReflectDemo03
* @Description
* @author calvin
* @date: 2020/2/9 10:13 PM
*/
public class ReflectDemo03 {
public static void main(String[] args) throws Exception {
// 0.获取Person的Class对象
Class personClass = Person.class;
// 1.Constructor<?>[] getConstructors() 获取所有的public构造方法
Constructor[] constructors = personClass.getConstructors();
for (Constructor cs : constructors) {
System.out.println("cs:" + cs);
}
// 2.Constructor<T> getConstructor(类<?>... parameterTypes) 获取指定的构造方法
Constructor constructor = personClass.getConstructor(String.class, int.class);
System.out.println("constructor:" + constructor);
// 创建对象(有参)
Object person = constructor.newInstance("张三", 23);
System.out.println("person:" + person);
// 创建对象(无参)
Object person1 = personClass.newInstance();
System.out.println("person1:" + person1);
// 3.Constructor<?>[] getDeclaredConstructors() 获取所有的构造方法,不考虑修饰符
Constructor[] declaredConstructors = personClass.getDeclaredConstructors();
for (Constructor cs1 : declaredConstructors) {
System.out.println("cs1:" + cs1);
}
// 4.Constructor<T> getDeclaredConstructor(类<?>... parameterTypes) 获取所有的构造方法,不考虑修饰符
Constructor constructor2 = personClass.getDeclaredConstructor(String.class, String.class);
System.out.println("constructor2:" + constructor2);
constructor2.setAccessible(true);
Object person2 = constructor2.newInstance("张三", "222");
System.out.println("person2:" + person2);
}
}
控制台输出:
cs:public com.calvin.reflect.Person()
cs:public com.calvin.reflect.Person(java.lang.String,int)
constructor:public com.calvin.reflect.Person(java.lang.String,int)
person:Person(name=张三, age=23, a=null, b=null, c=null, d=null)
person1:Person(name=null, age=0, a=null, b=null, c=null, d=null)
cs1:private com.calvin.reflect.Person(java.lang.String,java.lang.String)
cs1:public com.calvin.reflect.Person()
cs1:public com.calvin.reflect.Person(java.lang.String,int)
constructor2:private com.calvin.reflect.Person(java.lang.String,java.lang.String)
person2:Person(name=张三, age=0, a=null, b=null, c=222, d=null)
(3)获取成员方法
package com.calvin.reflect;
import java.lang.reflect.Method;
/**
* @Title ReflectDemo04
* @Description
* @author calvin
* @date: 2020/2/9 10:44 PM
*/
public class ReflectDemo04 {
public static void main(String[] args) throws Exception {
// 0.获取Person的Class对象
Class personClass = Person.class;
// 1.Method[] getMethods() 获取所有的public成员方法
Method[] classMethods = personClass.getMethods();
for (Method method : classMethods) {
System.out.println("method:" + method);
}
// 2.Method getMethod(String name, 类<?>... parameterTypes) 获取指定的成员方法
Method eatMethod1 = personClass.getMethod("eat");
Person p = new Person();
// 执行方法
eatMethod1.invoke(p);
// 方法重载
Method eatMethod2 = personClass.getMethod("eat", String.class);
// 执行方法
eatMethod2.invoke(p, "饭");
// 3.Method[] getDeclaredMethods() 获取所有的成员方法,不考虑修饰符
Method[] classMethods2 = personClass.getMethods();
for (Method method2 : classMethods2) {
System.out.println("method2:" + method2);
}
// 4.Method getDeclaredMethod(String name, 类 < ? >...parameterTypes) 获取指定的成员方法,不考虑修饰符
Method runMethod = personClass.getDeclaredMethod("run", String.class);
runMethod.setAccessible(true);
Person p1 = new Person();
// 执行方法
runMethod.invoke(p1, "1000米");
}
}
控制台输出:
method:public boolean com.calvin.reflect.Person.equals(java.lang.Object)method:public java.lang.String com.calvin.reflect.Person.toString()
method:public int com.calvin.reflect.Person.hashCode()
method:public java.lang.String com.calvin.reflect.Person.getName()
method:public void com.calvin.reflect.Person.setName(java.lang.String)
method:public int com.calvin.reflect.Person.getAge()
method:public java.lang.String com.calvin.reflect.Person.getA()
method:public java.lang.String com.calvin.reflect.Person.getB()
method:public java.lang.String com.calvin.reflect.Person.getC()
method:public java.lang.String com.calvin.reflect.Person.getD()
method:public void com.calvin.reflect.Person.setAge(int)
method:public void com.calvin.reflect.Person.setA(java.lang.String)
method:public void com.calvin.reflect.Person.setB(java.lang.String)
method:public void com.calvin.reflect.Person.setC(java.lang.String)
method:public void com.calvin.reflect.Person.setD(java.lang.String)
method:public void com.calvin.reflect.Person.eat(java.lang.String)
method:public void com.calvin.reflect.Person.eat()
method:public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
method:public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
method:public final void java.lang.Object.wait() throws java.lang.InterruptedException
method:public final native java.lang.Class java.lang.Object.getClass()
method:public final native void java.lang.Object.notify()
method:public final native void java.lang.Object.notifyAll()
eat…
eat…饭
method2:public boolean com.calvin.reflect.Person.equals(java.lang.Object)
method2:public java.lang.String com.calvin.reflect.Person.toString()
method2:public int com.calvin.reflect.Person.hashCode()
method2:public java.lang.String com.calvin.reflect.Person.getName()
method2:public void com.calvin.reflect.Person.setName(java.lang.String)
method2:public int com.calvin.reflect.Person.getAge()
method2:public java.lang.String com.calvin.reflect.Person.getA()
method2:public java.lang.String com.calvin.reflect.Person.getB()
method2:public java.lang.String com.calvin.reflect.Person.getC()
method2:public java.lang.String com.calvin.reflect.Person.getD()
method2:public void com.calvin.reflect.Person.setAge(int)
method2:public void com.calvin.reflect.Person.setA(java.lang.String)
method2:public void com.calvin.reflect.Person.setB(java.lang.String)
method2:public void com.calvin.reflect.Person.setC(java.lang.String)
method2:public void com.calvin.reflect.Person.setD(java.lang.String)
method2:public void com.calvin.reflect.Person.eat(java.lang.String)
method2:public void com.calvin.reflect.Person.eat()
method2:public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
method2:public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
method2:public final void java.lang.Object.wait() throws java.lang.InterruptedException
method2:public final native java.lang.Class java.lang.Object.getClass()
method2:public final native void java.lang.Object.notify()
method2:public final native void java.lang.Object.notifyAll()
run…1000米