反射
能够分析类能力的程序(reflective)
作用:
在运行时分析类的能力
在运行时检查对象
实现泛型数据操作代码
利用Method对象
Class类
在程序运行期间,Java运行时系统始终未所有对象维护一个运行时类型标识,这个信息会追踪每个对象所属的类
Class类保存了这些信息,所以可以通过Class类访问这些信息
获取Class对象的3种方法
1.可以用Object类中的getClass方法返回一个Class类型的实例
Class c=Object.getClass();
String name=c.getName();//返回类名(包名也作为类名的一部分)
2.静态方法forName获取类名对应的Class对象(手动强制加载类)
Class c=Class.forName();//会抛出检查型异常(checked exception)[如果不是类或者接口的话]
3.如果T是任意的Java类型(或void关键字),T.class将代表匹配的类的对象
Class c=Random.class;
Class c1=int.class;
Class c2=Double[].class;
一个Class对象实际表示的是一个类型,它可能是类,也可能不是类
Class类实际是一个泛型类
JVM为每个类型管理一个唯一的Class对象,因此可以使用==运算符实现2个类对象的比较
if(e.getClass()==Employee.class)...//只有同类型才为true,子类为false
利用反射构造对象
var className="java.util.Random";
Class c=Class.forName(className);
Object o=c.getConstructor().newInstance();//如果这个类没有无参构造器getConstructor()会抛出异常
反射常用函数:
java.lang.Class
static Class<?> forName(String className)
//返回一个Class对象,表示名为className的类
public Constructor<T> getConstructor(Class<?>... parameterTypes)
//生成一个对象,描述有指定参数类型的构造器
java.lang.reflect.Constructor
public T newInstance(Object ... initargs)
//将params传递给构造器,来构造这个构造器声明类的一个新实例
反射获取路径资源
1.获取拥有资源的类的Class对象,例如Test.class
2.有些方法,如ImageIcon类的getImage方法,接受描述资源位置的URL。则要调用
URL url=c.getResource("...");
3.否则,使用getResourceAsStream方法得到一个输入流来读取文件中的数据
JVM知道如何查找一个类,所以它能搜索相同位置上的关联资源
Class c=Test.class;//获取Class对象
// 从类所在目录开始检索
URL url = class1.getResource("a.jpg");//获取URL(统一资源定位器)
InputStream stream = class1.getResourceAsStream("a.jpg");//获取输入流
// 从类的上一级目录开始检索
InputStream stream = class1.getResourceAsStream("../a.jpg");//获取输入流
// 从Java虚拟机启动目录开始检索(即:System.getProperty("user.dir");)
InputStream stream4 = class1.getClassLoader().getResourceAsStream("resource/a.jpg");
反射检查类的结构
先介绍3个类:
Field:描述类的字段
拥有getType方法,用来返回描述字段类型的一个对象,这个对象类型也是Class
Method:描述类的方法
Constructor:描述类的构造器
它们都有getName方法,返回字段、方法或构造器的名称
getModifier方法,返回以1个整数,用不同的0/1位描述所使用的修饰符
例:通过输入完整的包名加类名,输出类的所有信息(类本身、类中方法、类的字段)
package resource;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Scanner;
public class ReflectionTest {
@SuppressWarnings("rawtypes") // 忽略编译未检查泛型(这行注解新手就不要去深究,不加不会影响使用)
public static void main(String[] args) throws ClassNotFoundException {
String name;
var in = new Scanner(System.in);
System.out.println("Enter class name (e.g.java.util.Date): ");
name = in.nextLine();
Class class1 = Class.forName(name);// 获取Class对象
Class superClass = class1.getSuperclass();// 获取其父类对象
String modefiers = Modifier.toString(class1.getModifiers());// 返回一个整数,描述(类、方法、字段)的修饰符,包括4种访问限制符,static,final,transient等
if (modefiers.length() > 0) {
System.out.print(modefiers + " ");// 如果修饰符不为空(即defualt)
}
System.out.print("class " + name);
if (superClass != null && superClass != Object.class) {
System.out.print(" extends " + superClass.getName());// 输出继承的父类
}
System.out.print("\n{\n");
printConstructors(class1);// 输出所有构造器方法
System.out.println();
printMethods(class1);// 输出所有常规方法
System.out.println();
printField(class1);// 输出所有字段
System.out.println("}");
in.close();
}
@SuppressWarnings("rawtypes")
public static void printConstructors(Class c) {
Constructor[] constructors = c.getDeclaredConstructors();// 获取此类中定义的所有构造器
for (Constructor constructor : constructors) {
String name = constructor.getName();
System.out.print(" ");
String modifiers = Modifier.toString(constructor.getModifiers());
if (modifiers.length() > 0) {
System.out.print(modifiers + " ");// 输出修饰符
}
System.out.print(name + "(");
Class[] paramTypes = constructor.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
if (i > 0) {
System.out.print(", ");
}
System.out.print(paramTypes[i].getName());// 输出变量名称
}
System.out.print(") ");
Class[] exceptionTypes = constructor.getExceptionTypes();
if (exceptionTypes.length > 0) {
System.out.print("throws ");
}
for (int i = 0; i < exceptionTypes.length; i++) {
System.out.print(exceptionTypes[i].getName() + " ");// 输出变量名称
}
System.out.println(";");
}
}
@SuppressWarnings("rawtypes")
public static void printMethods(Class c) {
Method[] methods = c.getDeclaredMethods();// 获取此类中定义的所有方法
for (Method method : methods) {
Class retType = method.getReturnType();// 获取返回类型
String name = method.getName();
System.out.print(" ");
String modifiers = Modifier.toString(method.getModifiers());
if (modifiers.length() > 0) {
System.out.print(modifiers + " ");// 输出修饰符
}
System.out.print(retType.getName() + " " + name + "(");
Class[] paramTypes = method.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
if (i > 0) {
System.out.print(", ");
}
System.out.print(paramTypes[i].getName());// 输出变量名称
}
System.out.println(");");
}
}
@SuppressWarnings("rawtypes")
public static void printField(Class c) {
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
Class type = field.getType();
String name = field.getName();
System.out.print(" ");
String modifiers = Modifier.toString(field.getModifiers());
if (modifiers.length() > 0) {
System.out.print(modifiers + " ");// 输出修饰符
}
System.out.println(type.getName() + " " + name + ";");// 输出变量类型和变量名称
}
}
}
结果: