什么是 Java 反射
具有分析类的能力的程序叫做反射;
Java 中具有分析类的能力的程序存在于 java.lang 以及 java.lang.reflect 包下面,这两个包中提供相关的类以及方法来实现反射这种思想。反射主要做的事情就是:在程序动态运行的过程当中,动态的检查以及修改类、接口、方法、字段中的内容。
对于反射的英文简单解释:
1、The java.lang and java.lang.reflect packages provide classes for java reflection.
2、Java Reflection is a process of examining or modifying the run time behavior of a class at run time.
3、The java.lang.Class class provides many methods that can be used to get metadata, examine and change the run time behavior of a class.
名字叫做 Class 的类
这个类在运行时保留有关对象和类的所有信息,而 Class 类的对象描述了特定类的属性,这个 Class 类的属性用于执行反射。
\
下文中用 Class 类 代替 名字叫做 Class 的类, 使用简称描述。
所谓名字叫做 Class 的类,放置在 JDK 的 java.lang 这个包下面,而这个类的定义如下:
public final class Class<T> implements java.io.Serializable,
GenericDeclaration,
Type,
AnnotatedElement {
}
在 Class 类中存在非常多的静态方法,通过这些静方法的使用,可以在程序运行的时候,对开发人员编写的代码进行检查以及修改,达到反射的作用。
Class 的类的实例(也叫 Class 类对象)(或者叫做 Class 类的对象)
Class 类只是一个类,通过 Class 类可以调用一些Class 类本身的静态方法,想要调用非静态方法,需要创建 Class 对象的实例。
创建 Class 类的实例(也可以叫做 Class 类对象)可以有下面的几种方式:
1、使用 Class.forName(); 方法
public class Dog {
Class c1 = Class.forName("Dog");
}
2、使用 实例.getClass(); 方法 这个方法继承于 Object 类
Dog dog = new Dog();
Class c2 = dog.getClass();
上面代码中, c2 这个 Class 类的对象是通过 dog 实例调用 getClass() 方法实现的。
3、使用 类.class;
Class c3 = Dog.class;
上述代码中, c3 这个 Class 类的对象是通过 Dog 这个类调用.class; 实现的。
使用 Class 类的反射获取接口信息
public class ReflectDemoGetInterface {
public static void main(String[] args) {
Dog d1 = new Dog();
// 使用 d1 对象获得 Class 类,这个 Class 类中保存了 d1 对象的信息以及 创建 d1 对象的类的相关信息
Class obj = d1.getClass();
// 使用反射获得 d1 对象 实现的接口信息
Class[] objInterface = obj.getInterfaces();
for (Class c : objInterface) {
System.out.println("实现的接口的名称是: " + c.getName());
}
}
}
使用 Class 类的反射获取父类以及类的访问修饰符
public class ReflectDemoGetFieldAndPublic {
public static void main(String[] args) {
Dog dog = new Dog();
// 获取 Class 类的对象
Class classObj = dog.getClass();
// 获取 Dog 类的访问修饰符
int modifier = classObj.getModifiers();
System.out.println("修饰符号:" + Modifier.toString(modifier));
// 获取 Dog 类的父类
Class superClass = classObj.getSuperclass();
System.out.println("super class is : " + superClass.getName());
}
}
使用 java.lang.reflect 包下面的相关类以及方法反射获取类中字段、方法以及构造函数
测试需要的代码
Animal 接口
interface Animal {
void display();
}
Mammal 接口
public interface Mammal {
void makeSound();
}
Dog 类
public class Dog implements Animal, Mammal{
public String type;
private String color;
@Override
public void display() {
System.out.println("this is a dog...");
}
@Override
public void makeSound() {
System.out.println("dog is backing...");
}
protected void eat() {
System.out.println("dog is eating...");
}
public Dog(String type) {
this.type = type;
}
public Dog() {
}
public Dog(String type, String color) {
this.type = type;
this.color = color;
}
}
获取字段以及字段修饰符
public static void main(String[] args) {
Dog d1 = new Dog();
Class obj = d1.getClass();
try {
Field field1 = obj.getField("type");
field1.set(d1, "Hello type has been changed");
String typeValue = (String) field1.get(d1);
System.out.println("type : " + typeValue);
/**
* 获取类型的访问修饰符
*/
int mod1 = field1.getModifiers();
String modifier1 = Modifier.toString(mod1);
System.out.println("字段的修饰符是: " + modifier1);
System.out.println("");
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
获取私有字段
/**
* 利用反射访问私有字段
*/
public static void testPrivateField() {
try {
Dog d1 = new Dog();
Class obj = d1.getClass();
Field field2 = obj.getDeclaredField("color");
field2.setAccessible(true);
field2.set(d1, "Blue");
String colorValue = (String) field2.get(d1);
System.out.println("利用反射获取到的私有字段的颜色是: " + colorValue);
System.out.println("");
} catch (Exception e) {
e.printStackTrace();
}
}
获取方法以及方法的修饰符
public static void testPublicMethod() {
try {
// 创建动物对象
Dog d1 = new Dog();
// 使用动物对象获取到 Class 对象
// Class 对象中保留了有关类以及对象的所有信息 d1 的 Class 对象中保存了 Dog 类以及 Dog 类创建出来的对象的所有信息
Class obj = d1.getClass();
// 使用 Class 对象,调用实例方法,得到相关类的方法信息
Method[] method = obj.getDeclaredMethods();
for (Method m : method) {
System.out.println("方法名称是: " + m.getName());
// 获取修饰方法的修饰符 public protected default private 四种修饰符号
int modifier = m.getModifiers();
System.out.println("方法的修饰符是: " + Modifier.toString(modifier));
// 获取方法的返回值类型
System.out.println("Return Types: " + m.getReturnType());
System.out.println("");
}
} catch (Exception e) {
e.printStackTrace();
}
}
\
获取构造方法
public static void testReflectConstructor() {
try {
Dog dog = new Dog();
Class obj = dog.getClass();
Constructor[] constructor = obj.getDeclaredConstructors();
for (Constructor c : constructor) {
System.out.println("构造函数的名字是: " + c.getName());
int modifier = c.getModifiers();
System.out.println("构造方法的修饰符是:" + Modifier.toString(modifier));
System.out.println("构造函数中参数的个数: " + c.getParameterCount());
System.out.println("");
}
} catch (Exception e) {
e.printStackTrace();
}
}
小结
本文介绍了 Java 反射的相关概念,以及使用 Class 类与 java.lang.reflect 包下面的相关类实现了动态的对于类、接口、方法、字段的检查以及修改,加深了对于 Java 反射的理解。需要注意的是 反射 是一种思想,在 Spring 等框架中有大量使用,这种反射思想在 JDK 不同包下面的不同类相互协作下实现的,反射的主要实现方法是在 java.lang.reflect 包中实现的。