JAVA总结(二)-----反射

一、什么是反射机制

    java语言和C、C++一样并不是动态语言,因为它不能在运行时修改某一字段的类型,参数等信息。但它具有一种更为强大的机制,即反射机制

    反射机制说的是,在程序运行加载时,对于任意的类,或者对象,我们可以根据这个类,获取这个类的所有属性和方法。我们可以根据这个对象,调用这个对象的方法和字段。这种动态获取信息以及动态调用的对象的方法称为java的反射机制

    当我们编译一个java源文件后,会产相应的字节编译文件*.class。

    当我们执行的时候,若想实例化某个类的时候,则会调用相应的.class载入jvm中。此时在jvm会产生唯一的Class对象,这个Class对象由特定的类产生。我们可以通过反射获取这个唯一的Class对象,从而进而实现反射机制。

二、java反射类

    1.Class--通过Class类获取Field,Method,Constructor对象.

    2.Field--存放了类的变量字段,无论是否这个变量是不可访问的(比如private,protected)等字段

    3.Method--存放类的方法字段,无论这个方法是否是不可访问的

    4.Constructor--存放类的构造函数字段。

    5.AccessibleObject--是Filed,Method,Constructor类的基类,只要作用是设置取消Java语言的类型检查能力 通过AccessibleObject.setAccessible(true)

三、反射的使用

    基础类 

//首先定义一个类
class UseReflection{
	
	private int k = 2;
	
	UseReflection(){
		System.out.println("Constructor reflection");
	}
	
	private void k(int value) {
		this.k = value;
		System.out.println(this.k);
	}
	
	public void k(int key,int value) {
		
		this.k = key + value;
		System.out.println(this.k);
	}
	
	protected String re = "reflection";
	
	UseReflection(int c){
		
	}
}



    1)查看类的成员变量,方法,构造方法

        1.获取某个类的Class对象

        2.获取这个类的Field,Method,Constructor实例对象

        3.使用setAccessible(true)取消相应对象java语言类型检查,使其能访问private,protected字段

public static void main(String [] a) throws IllegalArgumentException, IllegalAccessException, InstantiationException {
		// 获取这个类的实例
		UseReflection ur = new UseReflection();
		
		// 通过反射机制获得类的所有属性
		// 获取这个类的class对象
		// 每个类在加载到jvm时,除了删除字节的.class文件,还会产生class对象(并且使唯一的)
		Class <? extends UseReflection>  urClass = ur.getClass();
		
		// field 是这个类的变量字段 设置为数组 是获取这个类的所有变量
		java.lang.reflect.Field[] flds = urClass.getDeclaredFields();
		// method 是这类的方法字段 设置为数组 是获取这个类的所有方法
		java.lang.reflect.Method[] mtd = urClass.getDeclaredMethods();
		// constructor 是这类的构造方法字段 设置为数组 是获取这个类的所有构造方法
		java.lang.reflect.Constructor<UseReflection>[] cons = (Constructor<UseReflection>[]) urClass.getDeclaredConstructors();
		// 一次遍历
		for(java.lang.reflect.Field f : flds) {
			f.setAccessible(true);
			System.out.println(f + " "+ f.get(ur));
		}
		
		for(java.lang.reflect.Method m : mtd) {
			// 
			m.setAccessible(true);
			System.out.println(m + " " + m.getName());
		}
		
		for(java.lang.reflect.Constructor<UseReflection> c : cons) {
			c.setAccessible(true);
			System.out.println(c +" "+ c.getName());
		}
    上面程序将产生结果:
    很明显我们成功访问了 “UseReflection类”的prvatie protected字段

    2)动态加载类,并实例化其对象

        我们知道当我们仅仅声明时,并不能加载某一个类。比如说这个类在其他的包里,但我们已经编译过,并产生了.class文件,此时我们可以通过Class.forName(String ClassName) 获取这个类的Class对象(即加载到jvm)并且实例化其对象

        1.调用Class.forName()方法,获取某个类的Class对象

        2.实例化该的类的对象,通过Class.newInstance()方法

        3.使用这个对象,做一些操作。

	public static void main(String [] a) throws IllegalArgumentException, IllegalAccessException, InstantiationException {

		
		// 即使没有实例化这个对象 而是通过类载入器加载类,并产生Class实例对象,我们就可以通过这个唯一的这个类Class对象
		// 创建新的类的对象
		UseReflection ur2 = null;
		try {
			// 类载入器实例化一个类,其传递的参数是包名.类名 返回的参数是 Class<?>
			Class <UseReflection> urClass2 =  (Class<UseReflection>) Class.forName("reflection.UseReflection");
			ur2 = urClass2.newInstance();
			
			ur2.k(1, 2);
			
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

        产生的结果:


        3)操作类的构造函数,成员方法,成员变量

        在上也知道了我们怎么获得某个类的所有构造函数,方法,变量。但我们并不是只想查看,而是像更加进一步的操作(比说类中private protected修饰的字段)。

            1.操作类的成员变量

                                                     Class类的方法


                                                    Field类的设置方法(其中Object obj 为需要修正的对象)

	public static void main(String [] a) throws IllegalArgumentException, IllegalAccessException, InstantiationException {
		// 获取这个类的实例
		UseReflection ur = new UseReflection();
		
		// 通过反射机制获得类的所有属性
		// 获取这个类的class对象
		// 每个类在加载到jvm时,除了删除字节的.class文件,还会产生class对象(并且使唯一的)
		Class <? extends UseReflection>  urClass = ur.getClass();
		try {
			// 获取 UseReflection类的 变量 k(private类型)
			java.lang.reflect.Field fld = urClass.getDeclaredField("k");
			// 修正变量"k"为5
			// 取消类型检查 否则将产生编译错武器
			fld.setAccessible(true);
			System.out.println("改变前 k = "+fld.get(ur));
			fld.setInt(ur, 5);
			System.out.println("改变后 k = "+fld.get(ur));
			// 修正变量 "re" 为 Change
			java.lang.reflect.Field fld2 = urClass.getDeclaredField("re");
			// 取消类型检查
			fld2.setAccessible(true);
			System.out.println("改变前re = "+fld2.get(ur));
			fld2.set(ur, "Change");
			System.out.println("改变后 re = "+fld2.get(ur));
		} catch (NoSuchFieldException | SecurityException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
}

        产生输出:


            2.操作类的成员方法


Class类的获取成员方法(其中 parameterType 的值 因根据这个类的形参设置)


Method类的调用方法 其中 args为相应类的方法的实参
	public static void main(String [] a) throws IllegalArgumentException, IllegalAccessException, InstantiationException {
		// 获取这个类的实例
		UseReflection ur = new UseReflection();
		// 通过反射机制获得类的所有属性
		// 获取这个类的class对象
		// 每个类在加载到jvm时,除了删除字节的.class文件,还会产生class对象(并且使唯一的)
		Class <? extends UseReflection>  urClass = ur.getClass();
		
		try {
			// 获取 UseReflection 类的 私有方法"k(int )"
			java.lang.reflect.Method method = urClass.getDeclaredMethod("k", int.class);
			// 获取 UseReflection 类的私有方法"k(int ,int )"
			java.lang.reflect.Method method2 = urClass.getDeclaredMethod("k", int.class,int.class);
			try {
				// 取消类型检查
				method.setAccessible(true);
				// 调用UseReflection类的 "k(int )"
				method.invoke(ur, 2);
				// 取消类型检查
				method2.setAccessible(true);
				// 调用UseReflection类的"k(int ,int )"
				method2.invoke(ur, 2,2);
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (NoSuchMethodException | SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
}

        结果输出为:

            3.操作类的构造方法

Class类的获取类的构造方法(其中parameterType参数 为构造方法形参的参数)


Constructor类的实例新的类对象

	public static void main(String [] a) throws IllegalArgumentException, IllegalAccessException, InstantiationException {
		// 获取这个类的实例
		UseReflection ur = new UseReflection();
		// 通过反射机制获得类的所有属性
		// 获取这个类的class对象
		// 每个类在加载到jvm时,除了删除字节的.class文件,还会产生class对象(并且使唯一的)
		Class <? extends UseReflection>  urClass = ur.getClass();
		
		
		try {
			// 获取 UseReflection类的构造方法
			java.lang.reflect.Constructor<UseReflection> constructor = (Constructor<UseReflection>) urClass.getDeclaredConstructor(null);
			
			// 取消类型检查
			constructor.setAccessible(true);
			// 输出这个构造函数的名字
			System.out.println(constructor.getName());
			// 通过这个构造函数 实例化新的 UseReflection对象
			UseReflection ur3 =constructor.newInstance(null);
			// 获取第二个构造函数
			java.lang.reflect.Constructor<UseReflection> constructor2 = (Constructor<UseReflection>) urClass.getDeclaredConstructor(int.class);
			constructor2.setAccessible(true);
			UseReflection ur4 = constructor.newInstance(null);
			System.out.println(constructor2.getName());
		} catch (NoSuchMethodException | SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
}
        产生结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值