目录
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。实际上,我们创建的每一个类也都是对象,即类本身是java.lang.Class类的实例对象。这个实例对象称之为类对象,也就是Class对象。那么,Class对象又是什么对象呢?
一、Class对象
1.1 类描述
1.2 类方法
1.3 特点
Class类的实例对象表示正在运行的Java应用程序中的类和接口
。也就是JVM中有很多类的实例对象,每个类都有唯一的Class对象。Class类没有公共构造方法
。Class对象是加载类时由Java虚拟机自动构造的。也就是说由JVM类加载器自动创建。- Class对象用于提供类本身的信息,比如有几种构造方法, 有多少属性,有哪些普通方法。
二、类对象
2.1 获取类对象
Class.forName("package.T")
(常用)T.class
new T().getClass()
在一个JVM中,一种类只会有一个类对象存在。所以,以上三种方式获取的都是都是同一个类对象。准确地说,是在ClassLoader下只有一个类对象。
示例
public static void main(String[] args) {
String className = "package.T";
try {
Class forNameClass = Class.forName(className);
Class directClass = T.class;
Class objectClass = new T().getClass();
System.out.println(forNameClass == directClass); // print true
System.out.println(forNameClass == objectClass); // print true
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
2.2 获取类构造器
获取类构造方法
-
批量方法
public Constructor[] getConstructors()
:获取所有"公有的"构造器方法
public Constructor[] getDeclaredConstructors()
:获取所有构造方法(包括私有、受保护、默认、公有) -
获取单个方法
public Constructor getConstructor(Class... parameterTypes)
:获取单个"公有的"构造器方法
public Constructor getDeclaredConstructor(Class... parameterTypes)
:获取单个"公有的"构造器方法(包括私有的、受保护、默认或公有的)
示例
package pojo;
public class User {
/** 姓名 */
public String userName;
/** 年龄 */
private Integer age;
/** 住所 */
private String address;
/** 无参构造器 **/
public User() {
}
/** public修饰符, 带参构造器 **/
public User(String userName, Integer age) {
this(userName, age, null);
}
/** private修饰符, 带参构造器 **/
private User(String userName, Integer age, String address) {
this.userName = userName;
this.age = age;
this.address = address;
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
//1. 加载Class对象
Class<?> forNameClass = Class.forName("pojo.User");
//2. 获取所有公有构造方法
System.out.println("**********************所有公有构造方法*********************************");
Constructor<?>[] constructors = forNameClass.getConstructors();
// 打印信息
// public pojo.User(java.lang.String,java.lang.Integer)
// public pojo.User()
Stream.of(constructors).forEach(e -> System.out.printf(" %s\n", e.toString()));
System.out.println("************所有的构造方法(包括:私有、受保护、默认、公有)***************");
// 打印信息
// private pojo.User(java.lang.String,java.lang.Integer,java.lang.String)
// public pojo.User(java.lang.String,java.lang.Integer)
// public pojo.User()
Constructor<?>[] declaredConstructors = forNameClass.getDeclaredConstructors();
Stream.of(declaredConstructors).forEach(e -> System.out.printf(" %s\n", e.toString()));
System.out.println("*****************获取公有、无参的构造方法*******************************");
// 打印信息
// public pojo.User()
Constructor<?> publicNoArgConstructor = forNameClass.getConstructor();
System.out.printf(" %s\n", publicNoArgConstructor.toString());
System.out.println("******************获取公有构造方法*******************************");
// 打印信息
// public pojo.User(java.lang.String,java.lang.Integer)
Constructor<?> publicArgConstructor = forNameClass.getDeclaredConstructor(String.class, Integer.class);
System.out.printf(" %s\n", publicArgConstructor.toString());
System.out.println("******************获取私有构造方法*******************************");
// 打印信息
//private pojo.User(java.lang.String,java.lang.Integer,java.lang.String)
Constructor<?> privateArgConstructor = forNameClass.getDeclaredConstructor(String.class, Integer.class, String.class);
System.out.printf(" %s\n", privateArgConstructor.toString());
}
}
2.3 创建类对象
调用Constructor
对象的newInstance(Object... initArgs)
创建类对象实例。
示例
public static void main(String[] args)
throws ClassNotFoundException, NoSuchMethodException,
IllegalAccessException, InvocationTargetException, InstantiationException {
Class<?> forNameClass = Class.forName("pojo.User");
System.out.println("*****************获取公有、无参的构造方法*******************************");
// 打印信息
// User(userName=null, age=null, address=null)
Constructor<?> publicNoArgConstructor = forNameClass.getConstructor();
Object publicNoArgObject = publicNoArgConstructor.newInstance();
System.out.println(publicNoArgObject);
System.out.println("******************获取公有构造方法*******************************");
// 打印信息
// User(userName=ioteye, age=18, address=null)
Constructor<?> publicArgConstructor = forNameClass.getDeclaredConstructor(String.class, Integer.class);
Object publicArgObject = publicArgConstructor.newInstance("ioteye", 18);
System.out.println(publicArgObject);
System.out.println("******************获取私有构造方法*******************************");
// 打印信息
// User(userName=ioteye, age=18, address=sz)
Constructor<?> privateArgConstructor = forNameClass.getDeclaredConstructor(String.class, Integer.class, String.class);
// 设置对象访问标志设置为公有
privateArgConstructor.setAccessible(true);
Object privateArgObject = privateArgConstructor.newInstance("ioteye", 18, "sz");
System.out.println(privateArgObject);
}
三、类成员变量
3.1 获取成员变量
获取方式
- 批量方法
clazz.getFields()
:获取所有公有的成员变量(包括从父类继承的成员变量)
clazz.getDeclaredFields()
:获取所有成员变量(包括私有、默认、受保护或公有,不包括从父类继承的成员变量) - 获取单个方法
clazz.getField(String name)
:获取单个公有的成员变量(包括从父类继承的成员变量)
clazz.getDeclaredField(String name)
:获取单个成员变量(包括私有、默认、受保护或公有,不包括从父类继承的成员变量)
示例
package pojo;
import java.lang.reflect.Field;
import java.util.stream.Stream;
public class User {
/** 静态ID **/
private static final String ENV = "TEST";
/** 姓名 */
public String userName;
/** 年龄 */
private Integer age;
/** 住所 */
private String address;
public static void main(String[] args)
throws ClassNotFoundException, NoSuchFieldException {
Class<?> forNameClass = Class.forName("pojo.User");
System.out.println("*****获取所有公有的成员变量(包括从父类继承的成员变量)******");
// 打印信息
// public java.lang.String pojo.User.userName
Field[] fields = forNameClass.getFields();
Stream.of(fields).forEach(System.out::println);
System.out.println("******获取所有成员变量(包括私有、默认、受保护或公有,不包括从父类继承的成员变量)******");
// 打印信息
// public java.lang.String pojo.User.userName
// private java.lang.Integer pojo.User.age
// private java.lang.String pojo.User.address
Field[] declaredFields = forNameClass.getDeclaredFields();
Stream.of(declaredFields).forEach(System.out::println);
System.out.println("******************获取单个公有的成员变量*******************************");
// 打印信息
// public java.lang.String pojo.User.userName
Field userNameField = forNameClass.getField("userName");
System.out.println(userNameField);
System.out.println("******************获取单个私有成员变量*******************************");
// 打印信息
// private java.lang.Integer pojo.User.age
Field ageField = forNameClass.getDeclaredField("age");
System.out.println(ageField);
}
}
3.2 Field类介绍
3.3 Field类方法摘要
3.4 成员变量赋值
public class User {
/** 静态ID **/
private static final String ENV = "TEST";
/** 姓名 */
public String userName;
/** 年龄 */
private Integer age;
/** 住所 */
private String address;
public static void main(String[] args)
throws ClassNotFoundException, NoSuchMethodException,
InstantiationException, IllegalAccessException, InvocationTargetException,
NoSuchFieldException {
Class<?> forNameClass = Class.forName("pojo.User");
System.out.println("******获取公有、无参的构造方法******");
Constructor<?> constructor = forNameClass.getConstructor();
Object instance = constructor.newInstance();
System.out.println("******************获取单个公有的成员变量*******************************");
Field userNameField = forNameClass.getField("userName");
userNameField.set(instance, "ioteye");
System.out.println("******************获取单个私有成员变量*******************************");
Field ageField = forNameClass.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(instance, 18);
// 打印信息
// User(userName=ioteye, age=18, address=null)
System.out.println(instance);
System.out.println("******************获取静态字段*******************************");
// 打印信息
// TEST
Field envField = forNameClass.getDeclaredField("ENV");
envField.setAccessible(true);
Object value = envField.get(instance);
System.out.println(value);
}
}
四、类方法
4.1 获取方法
获取方式
- 批量方法
clazz.getMethods()
:获取所有公有的方法(包括父类继承的)
clazz.getDeclaredMethods()
:获取所有方法(包括私有、默认、受保护和公有的,以及类方法,但是不包括父类继承的方法) - 获取单个方法
clazz.getField(String name)
:获取单个公有的方法(包括父类继承的)
clazz.getDeclaredField(String name)
:获取单个方法(包括私有、默认、受保护和公有的,以及类方法,但是不包括父类继承的方法)
注意
:获取的方法中不包括构造器方法
示例
package pojo;
import java.lang.reflect.Method;
import java.util.stream.Stream;
public class User {
/** 静态ID **/
private static final String ENV = "TEST";
/** 姓名 */
public String userName;
/** 年龄 */
private Integer age;
/** 住所 */
private String address;
/** 无参构造器 **/
public User() {
}
/** private修饰符, 带参构造器 **/
private User(String userName, Integer age) {
this(userName, age, null);
}
/** private修饰符, 带参构造器 **/
private User(String userName, Integer age, String address) {
this.userName = userName;
this.age = age;
this.address = address;
}
/** public修饰符, 无参方法 */
public void printInfo() {
System.out.printf("%s is %d years old, and his hometown is %s\n", userName, age, address);
}
/** private修饰符, 无参方法 */
private void gotoAddress(String gotoAddress) {
System.out.printf("%s is %d years old, went to work in %s\n", userName, age, gotoAddress);
}
/** private和static修饰符, 带参方法 */
private static User newInstance(String userName, Integer age, String address) {
return new User(userName, age, address);
}
public static void main(String[] args)
throws ClassNotFoundException, NoSuchMethodException{
Class<?> forNameClass = Class.forName("pojo.User");
System.out.println("****获取所有公有的方法(包括父类继承的)****");
// 打印信息
// public static void pojo.User.main(java.lang.String[])
// throws java.lang.ClassNotFoundException,java.lang.NoSuchMethodException
// public void pojo.User.printInfo()
// public final void java.lang.Object.wait() throws java.lang.InterruptedException
// public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
// public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
// public boolean java.lang.Object.equals(java.lang.Object)
// public java.lang.String java.lang.Object.toString()
// public native int java.lang.Object.hashCode()
// public final native java.lang.Class java.lang.Object.getClass()
// public final native void java.lang.Object.notify()
// public final native void java.lang.Object.notifyAll()
Method[] methods = forNameClass.getMethods();
Stream.of(methods).forEach(System.out::println);
System.out.println("****获取所有方法(包括私有、默认、受保护和公有的,以及类方法,但是不包括父类继承的方法)****");
// 打印信息
// public static void pojo.User.main(java.lang.String[])
// throws java.lang.ClassNotFoundException,java.lang.NoSuchMethodException
// private static pojo.User pojo.User.newInstance(java.lang.String,java.lang.Integer,java.lang.String)
// public void pojo.User.printInfo()
// private void pojo.User.gotoAddress(java.lang.String)
Method[] declaredMethods = forNameClass.getDeclaredMethods();
Stream.of(declaredMethods).forEach(System.out::println);
System.out.println("**********获取单个公有、无参方法**********");
// 打印信息
// public void pojo.User.printInfo()
Method printInfoMethod = forNameClass.getMethod("printInfo");
Stream.of(printInfoMethod).forEach(System.out::println);
System.out.println("****获取单个私有、带参方法****");
// 打印信息
// private void pojo.User.gotoAddress(java.lang.String)
Method gotoAddressMethod = forNameClass.getDeclaredMethod("gotoAddress", String.class);
Stream.of(gotoAddressMethod).forEach(System.out::println);
System.out.println("****获取单个有返回值、私有类方法****");
// 打印信息
// private static pojo.User pojo.User.newInstance(java.lang.String,java.lang.Integer,java.lang.String)
Method newInstanceMethod = forNameClass.getDeclaredMethod("newInstance", String.class, Integer.class, String.class);
Stream.of(newInstanceMethod).forEach(System.out::println);
}
}
4.2 Method类介绍
4.2 Method类方法摘要
4.4 方法反射调用
package pojo;
import lombok.Data;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@Data
public class User {
/** 静态ID **/
private static final String ENV = "TEST";
/** 姓名 */
public String userName;
/** 年龄 */
private Integer age;
/** 住所 */
private String address;
/** private修饰符, 带参构造器 **/
private User(String userName, Integer age, String address) {
this.userName = userName;
this.age = age;
this.address = address;
}
/** public修饰符, 无参方法 */
public void printInfo() {
System.out.printf("%s is %d years old, and his hometown is %s\n", userName, age, address);
}
/** private修饰符, 无参方法 */
private void gotoAddress(String gotoAddress) {
System.out.printf("%s is %d years old, went to work in %s\n", userName, age, gotoAddress);
}
/** private和static修饰符, 带参方法 */
private static User newInstance(String userName, Integer age, String address) {
return new User(userName, age, address);
}
public static void main(String[] args)
throws ClassNotFoundException, NoSuchMethodException,
InstantiationException, IllegalAccessException, InvocationTargetException {
Class<?> forNameClass = Class.forName("pojo.User");
System.out.println("******获取公有、无参构造方法******");
Constructor<?> constructor = forNameClass.getDeclaredConstructor(String.class, Integer.class, String.class);
constructor.setAccessible(true);
Object instance = constructor.newInstance("ioteye", 18, "sz");
System.out.println("****获取单个公有、无参方法****");
// 打印信息
// ioteye is 18 years old, and his hometown is sz
Method printInfoMethod = forNameClass.getMethod("printInfo");
printInfoMethod.invoke(instance);
System.out.println("****获取单个私有、带参方法****");
// 打印信息
// ioteye is 18 years old, went to work in bj
Method gotoAddressMethod = forNameClass.getDeclaredMethod("gotoAddress", String.class);
gotoAddressMethod.setAccessible(true);
gotoAddressMethod.invoke(instance,"bj");
System.out.println("****获取单个有返回值、私有类方法****");
// 打印信息
// User(userName=ioteye-1, age=18, address=sz)
Method newInstanceMethod = forNameClass.getDeclaredMethod("newInstance", String.class, Integer.class, String.class);
newInstanceMethod.setAccessible(true);
Object invokeResult = newInstanceMethod.invoke(null, "ioteye-1", 18, "sz");
System.out.println(invokeResult);
}
}