Java反射机制学习过程——笔记

Class类

在Java中所有的反射操作都是围绕Class类来展开的,Class这个类是在JDK1.0的时候出现的,可以说这个类是Java类中的元老李,那么这个类究竟有什么特别之处呢?查看文档发现Class类是一个final类,也就是我们所说的太监类,不可能有子类,但是虽说没有子类,但是却仍与所有的类都有着关系。Class定义如下:

好吧,处理Serializable,其他都看不懂,就先过滤掉吧!

一、取得Class对象

所以的类都是Object类的子类,在Object类中有一个getClass方法,通过此方法可以获得Class类,所以说Class类虽说没有子类,但却能通过Object类间接的与所有的类有关系。

  1. Object的getClass方法:public final Class<?> getClass()返回的是一个Class对象。调用该方法必须先实例化对象
  2. 使用Class字面常量:类名.class得到Class对象
  3. 使用Class类的静态方法:Class.forName("类")。不需要实例化

这三种方法都是可以获取Class对象,前两种比较安全,因为要使用前两种就必须先导入所要使用的类,例如:我要使用Date类,那么就必须先 import java.util.Date,----编译器会检查这个类,如果不存在会报错。而使用Class.forName不需要提前导入需要的类,不管类存不存在都不会报错,这个只在运行时才报错,所以使用时要抛异常。虽说还有较多区别,但是这里仅仅补充我所学到的。将来需要再补充。

下面是代码:

public static void getClassObject() {
		// 三种取得Class对象的方式
		try {
			Class<?> cls1 = Class.forName("java.util.Date");
			System.out.println(cls1.getName());
			System.out.println(cls1.getSimpleName());
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		Class<?> cls2 = Date.class;
		System.out.println(cls2.getName());
		Class<?> cls3 = new Date().getClass();
		System.out.println(cls3.getName());
	}

二、java.lang.reflect反射包

Java的反射机制可以说是一个重要的概念,利用反射,程序可以在运行状态中调用查看一个类的所有属性与方法(静态)以及调用任意一个对象的属性与方法。在Java中提供了java.lang.reflect包对反射的支持,在反射包中有几个常用的类:Constructor、Method、Field。使用他们可以随时创建对象,使用对象,以及修改对象属性。

1、Constructor

Construct定义如下:

public final class Constructor<T> extends Executable

Constructor同Class一样也是一个final类,且构造方法私有化 ,Constructor常用方法定义及使用如下:

public static void getConstructor() {
		// 获取类的构造方法
		Class<?> cls;
		try {
			cls = Class.forName("Basketball");
			// Constructor con = cls.getConstructor();// 取得类的指定构造,可带参数
			Constructor<?>[] cons = cls.getConstructors();// 取得全部构造
			// Constructor<?>[] cons = cls.getDeclaredConstructors();//取得当前类的构造
			for (int i = 0; i < cons.length; i++) {
				System.out.println("构造函数名:" + cons[i].getName());
				System.out.println("参数个数:" + cons[i].getParameterCount());
				Type[] type = cons[i].getParameterTypes();
				System.out.println("参数类型:");
				for (int y = 0; y < type.length; y++) {
					System.out.println("\t" + type[y].toString());
				}
				System.out.println("当前类:" + cons[i].getDeclaringClass());
				System.out.print("构造方法修饰符:" + cons[i].getModifiers());
				// 输出结果为1,代表public,但是将构造方法改成private和protected均不输出所以放弃
				// 若要输出结果为public则可以使用toString方法
				System.out.println("----" + Modifier.toString(cons[i].getModifiers()));
				try {
					// 实例化对象
					Object obj = cons[i].newInstance("篮球");
					System.out.println("实例化对象:" + obj.toString());
				} catch (Exception e) {
					Object obj;
					try {
						obj = cons[i].newInstance();
						System.out.println("实例化对象:" + obj.toString());
					} catch (Exception e1) {
					}
				}
				// 获取异常对象
				Class<?>[] exp = cons[i].getExceptionTypes();
				System.out.println("获取异常:");
				for (int y = 0; y < exp.length; y++) {
					System.out.println("\t" + exp[i].getName());
				}
				System.out.println("****************************");
			}

		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

运行结果:

2、Method

Method定义如下:

public final class Method extends Executable

常用方法及使用:

public static void getClassMethod() {
		try {
			Class<?> cls = Class.forName("Basketball");
			Method[] methods = cls.getMethods();// 这个类所有的方法
			System.out.println("当前类所对应的方法修饰符、返回值、方法名以及参数:");
			for (Method method : methods) {
				StringBuffer sbuffer = new StringBuffer();
				sbuffer.append("\t");
				sbuffer.append(Modifier.toString(method.getModifiers())).append(" ");// 方法修饰符
				sbuffer.append(method.getReturnType().getSimpleName()).append(" ");// 方法返回值
				sbuffer.append(method.getName()).append("(");
				Class<?>[] types = method.getParameterTypes();// 获取全部参数类型
				if (types.length > 0) {
					for (int i = 0; i < types.length; i++) {
						sbuffer.append(types[i].getSimpleName()).append(" argv" + i + ",");
					}
					sbuffer.delete(sbuffer.length() - 1, sbuffer.length());
				}
				sbuffer.append(");");
				System.out.println(sbuffer.toString());
			}
			System.out.println("调用特定的方法--invoke");
			// 取得某一方法:参数1 方法名称,参数2方法参数类型(无参数可省略),此处直接写
			try {
				Basketball ball = new Basketball();
				cls.getMethod("setName", String.class).invoke(ball, "篮球");
				System.out.println(cls.getMethod("getName").invoke(ball));
			} catch (Exception e) {
				e.printStackTrace();
			}
			// 略:getExceptionTypes();getParameterCount() ;
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

运行结果:略

3.Field

Field定义如下:

public final class Field extends AccessibleObject implements Member

与Constructor不同的是Field直接继承AccessibleObject并且实现Member接口,而Constructor与Method都是间接继承AccessibleObject。

常用方法使用如下:

public static void getField() {
		try {
			Class<?> cls = Class.forName("Basketball");
			Object obj = cls.newInstance();
			// 取得全部成员,只能取得public修饰的变量
			Field[] fields = cls.getFields();
			for (Field field : fields) {
				System.out.println(field);
				System.out.println("获取属性的内容" + field.get(obj));
			}
			System.out.println("********************");
			Field field = cls.getDeclaredField("name");
			/**
			 * 设置属性的内容.pass:直接设置出现异常 </br>
			 * java.lang.IllegalAccessException: Class Reflect can </br>
			 * not access a member of class Basketball with modifiers "private"</br>
			 * name使用private封装,外部无法访问
			 * <li>方法1:将private改为public,虽然能解决但是不建议</li>
			 * <li>方法2:使用setAccessible(true);
			 */
			field.setAccessible(true);// 取消封装,该方法由父类java.lang.reflect.AccessibleObject 提供
			field.set(obj, "篮球");
			System.out.println("获取属性的内容" + field.get(obj));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

后续后面补充

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值