反射(笔记)

反射

能够分析类能力的程序(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 + ";");// 输出变量类型和变量名称

		}
	}
}

结果:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值