反射技术是Java生态中的重要内容,在Spring以及其他框架中得到了广泛的应用。
有了反射技术,我们可以在程序运行的过程中:
实体类中包含私有方法、公有方法、私有变量、公有变量。
public class Student {
private String name;
private Integer age;
public String className;
public Student() {
}
private Student(String name) {
this.name = name;
}
public Student(Integer age) {
this.age = age;
}
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
private void getAge(){
System.out.println("这是一个私有方法");
}
public void getName(){
System.out.println("这是一个公有方法");
}
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
public void setClassName(String className) {
this.className = className;
}
}
首先需要通过上一篇文章中提到的方法,获取到 class对象,再通过 getDeclaredConstructors()
获取到该类下所有构造方法。
import java.lang.reflect.Constructor;
public class Test {
public static void main(String[] args) {
Class<Student> student = Student.class;
Constructor<?>[] constructors = student.getDeclaredConstructors();
for (Constructor constructor : constructors){
System.out.println(constructor);
}
}
}
输出的结果如下:
public com.reflect.Student(java.lang.String,java.lang.Integer) public com.reflect.Student(java.lang.Integer) private com.reflect.Student(java.lang.String) public com.reflect.Student()
从输出的结果中,可以看到:实体类中四个构造方法都被获取到了,包括一个私有构造方法。及构造方法中的参数列表也能被取出来。
不同于获取所有构造方法的反射方法,这里使用 getConstructors()
即可。
import java.lang.reflect.Constructor;
public class Test {
public static void main(String[] args) {
Class<Student> student = Student.class;
Constructor<?>[] constructors = student.getConstructors();
for (Constructor constructor : constructors){
System.out.println(constructor);
}
}
}
输出如下:
public com.reflect.Student(java.lang.String,java.lang.Integer) public com.reflect.Student(java.lang.Integer) public com.reflect.Student()
没有获取到类中类型为 private 的构造方法,仅有 public 方法。
如果我们想要根据参数列表,获取到特定的构造方法时,可以使用 getDeclaredConstructor()
方法,方法中指明构造方法需要的参数:
import java.lang.reflect.Constructor;
public class Test {
public static void main(String[] args) {
try {
Class<Student> student = Student.class;
//获取私有构造方法
Constructor<?> constructor = student.getDeclaredConstructor(String.class);
System.out.println(constructor);
//获取公有构造方法
Constructor<?> constructor2 = student.getDeclaredConstructor(String.class, Integer.class);
System.out.println(constructor2);
//获取无参构造方法
Constructor<?> constructor3 = student.getDeclaredConstructor(null);
System.out.println(constructor3);
}catch (Exception e){
e.printStackTrace();
}
}
}
输出结果为
private com.reflect.Student(java.lang.String) public com.reflect.Student(java.lang.String,java.lang.Integer) public com.reflect.Student()
getConstructor()
方法,当对应的构造方法为 private 时,会报异常 java.lang.NoSuchMethodException
;java.lang.NoSuchMethodException
。使用class对象的 getDeclaredMethods()
,可以获取当前类下所有普通方法(非构造方法)。
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) {
Class<Student> student = Student.class;
//获取所有方法
Method[] declaredMethods = student.getDeclaredMethods();
for (Method method : declaredMethods){
System.out.println(method);
}
}
}
输出结果为
public void com.reflect.Student.getName() public void com.reflect.Student.setName(java.lang.String) private void com.reflect.Student.getAge() public void com.reflect.Student.setAge(java.lang.Integer) public void com.reflect.Student.setClassName(java.lang.String)
类型为 private 和 public 的方法,都被获取到了。
使用class对象的 getMethods()
,可以获取当前类及其所有父类下所有被 public 修饰的普通方法(非构造方法)。
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) {
Class<Student> student = Student.class;
//获取所有方法
Method[] declaredMethods = student.getMethods();
for (Method method : declaredMethods){
System.out.println(method);
}
}
}
输出结果中,包含了 Student 类及默认父类 Object 类下所有由 public 修饰的方法。
public void com.reflect.Student.getName() public void com.reflect.Student.setName(java.lang.String) public void com.reflect.Student.setAge(java.lang.Integer) public void com.reflect.Student.setClassName(java.lang.String) 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()
getMethod()
方法;
getDeclaredMethod()
方法。
getMethod()
方法中第一个参数指定要获取的方法名,后边为参数列表;
getMethod()
获取 private 修饰的方法时,也会抛出方法找不到的异常。
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) {
Class<Student> student = Student.class;
try {
//获取带参方法
Method method = student.getMethod("setAge", Integer.class);
System.out.println(method);
//获取无参方法
Method method2 = student.getMethod("getName", null);
System.out.println(method2);
//获取无参方法
Method method3 = student.getMethod("getName");
System.out.println(method3);
}catch (Exception e){
e.printStackTrace();
}
}
}
输出结果
public void com.reflect.Student.setAge(java.lang.Integer) public void com.reflect.Student.getName() public void com.reflect.Student.getName()
获取所有成员变量
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) {
Class<Student> student = Student.class;
Field[] declaredFields = student.getDeclaredFields();
for (Field field: declaredFields){
System.out.println(field);
}
}
}
输出结果
private java.lang.String com.reflect.Student.name private java.lang.Integer com.reflect.Student.age public java.lang.String com.reflect.Student.className
public class Test {
public static void main(String[] args) {
Class<Student> student = Student.class;
System.out.println(student.getName());
}
}
获取类名其实有多种方式:
要么是通过类名获取,
或者通过对象获取,
或者指定类的全路径获取。
可以拿到该类所在的包的全路径信息。
public class Test {
public static void main(String[] args) {
Class<HighSchoolStudent> student = HighSchoolStudent.class;
Package aPackage = student.getPackage();
System.out.println(aPackage);
}
}
public class Test {
public static void main(String[] args) {
Class<HighSchoolStudent> student = HighSchoolStudent.class;
Class<? super HighSchoolStudent> superclass = student.getSuperclass();
System.out.println(superclass);
}
}
这种方式只能拿到该类的直接父类,如果想要获取所有父类,可以在拿到父类后循环遍历,直到父类为 Object 为止。
public class Test {
public static void main(String[] args) {
Class<ArrayList> arrayListClass = ArrayList.class;
Class superclass = arrayListClass.getSuperclass();
System.out.println(superclass);
while (! "java.lang.Object".equals(superclass.getName())) {
superclass = superclass.getSuperclass();
System.out.println(superclass);
}
}
}
输出:
class java.util.AbstractList class java.util.AbstractCollection class java.lang.Object
该方法可以获取到该类实现的所有接口。
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
Class<ArrayList> arrayListClass = ArrayList.class;
Class<?>[] interfaces = arrayListClass.getInterfaces();
for(Class clazz: interfaces){
System.out.println(clazz.getName());
}
}
}
输出如下:
java.util.List java.util.RandomAccess java.lang.Cloneable java.io.Serializable