java-23:反射机制

1.反射的概念:

在Java中运行的类,有这么一面镜子,可以反射该类的一些行为和属性,而这个反射就体现在java.lang.Class中;

通过Class对象,可以得到某个类的一些行为和属性,甚至我们通过反射可以操作这个对象的行为和属性;这就是反射机制;

2.反射类class对象:在运行期间,只有一个class对象产生,唯一对应一个类。无论new出多少个对象,class对象只有一个。

3.反射使用场景:仅能拿到类的描述,拿不到类,却需要操作类的属性或方法。好比要买苹果,却不能拿出一个苹果的样品给卖家看,只能描述苹果的名称,样子。

4.实例代码

package org.szxu.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import javax.lang.model.element.VariableElement;


public class ReflectionMyself {

    //public Object initByDefaultConst(Object obj) throws Throwable {
	public Object initByDefaultConst() throws Throwable {

    	String className = "org.szxu.reflection.Car";
    	
    	System.out.println(System.getProperty("sun.boot.class.path"));
    	System.out.println(System.getProperty("java.ext.dirs"));
    	System.out.println(System.getProperty("java.class.path"));
    	
    	/* 第一部分:获取类的class信息 */
    	//1.通过类名.class方式获取类元数据对象,前提是能够类可见(这里没必要使用反射,只需知道类有个class属性即可)
    	//Class clazz = Car.class;
    	
    	//2.通过getClass()方式获取类元数据对象,任何数据类型(包括基本数据类型)都有一个静态的class属性
        //Class<?> clazz = new Car().getClass();
    	
    	//3.通过Class.forName获取类元数据对象
        Class clazz = Class.forName(className);
        
        //4.1.通过本类装载器获取类元数据对象
    	//ClassLoader classLoader00 = this.getClass().getClassLoader();   //局限:仅能在非static方法中使用
    	ClassLoader classLoader = ReflectionMyself.class.getClassLoader();    //方法所在类名.class
    	Class clazz_12 = classLoader.loadClass(className);
    	
    	//4.2.通过类装载器获取类元数据对象
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        Class clazz_11 = loader.loadClass(className);
    	    	
    	//System.out.println(clazz_11 == clazz_12);
    	//System.out.println(clazz_12 == clazz_2);
    	//System.out.println(clazz_2 == clazz);
    	
    	/* 第二部分:获取类的实例 */
        //1.1.获取类的默认构造器对象:公有构造器
    	//Constructor constructor_public = clazz.getConstructor();   //仅取到构造器为public,不能获取private修饰的构造器
    	//System.out.println(constructor_public.getName());
        
    	//1.2.获取类的默认构造器对象:私有构造器
    	Constructor constructor_private = clazz.getDeclaredConstructor();  //可获取private修饰的Constructor对象
        System.out.println(constructor_private.getName());
        
        //1.3.获取指定参数的公有构造器
        Constructor constructor_params = clazz.getConstructor(String.class, String.class, int.class);
        System.out.println(constructor_params.getName());
        
        //1.4.获取指定参数的私有构造器
        Constructor constructor_params_private = clazz.getDeclaredConstructor(String.class, String.class, int.class, int.class);
        System.out.println(constructor_params.getName());
        constructor_params_private.setAccessible(true);
        
        //2.1.通过构造器实例化对象:公有构造器
        //Object carObject = constructor_public.newInstance();
        
        //2.2.通过构造器实例化对象:私有构造器,前提是调用一下setAccessible(true)获取调用私有方法的权限,否则会报异常
        /*constructor_private.setAccessible(true);
        Object carObject = constructor_private.newInstance();
        System.out.println(carObject.toString());*/
        
        //2.3.通过公有构造器实例化对象:带参数构造器
        //Object carObject = constructor_params.newInstance("宝马", "白色", 200);
        
        //2.4.通过私有构造器实例化对象:带参构造器
        Object carObject = constructor_params_private.newInstance("宝马", "白色", 200, 2);
        
        
        /* 第三部分:使用类的方法和属性 */
        //1.1.直接设置字段值;直接获取字段值
        Field brandField = clazz.getDeclaredField("brand");  //设置铭牌
        brandField.setAccessible(true);
        brandField.set(carObject, "别克300");   
        System.out.println("brand:" + (String)brandField.get(carObject));
        Field colorField = clazz.getDeclaredField("color");  //设置颜色
        colorField.setAccessible(true);
        colorField.set(carObject, "别克白色");   
        System.out.println("brand:" + (String)colorField.get(carObject));
        Field speedField = clazz.getDeclaredField("maxSpeed");  //设置最大速度
        speedField.setAccessible(true);
        speedField.set(carObject, 260);   
        System.out.println("brand:" + (int)speedField.get(carObject));
        
        //1.2.通过属性方法设置私有字段
        Method setBrand = clazz.getDeclaredMethod("setBrand", String.class);  //设置铭牌
        setBrand.invoke(carObject, "红旗CA72");
        System.out.println(clazz.getMethod("getBrand").invoke(carObject));
        Method setColor = clazz.getMethod("setColor", String.class);  //设置颜色
        setColor.invoke(carObject, "黑色");
        System.out.println(clazz.getMethod("getColor").invoke(carObject));
        Method setMaxSpeed = clazz.getMethod("setMaxSpeed", int.class);  //设置最大速度
        setMaxSpeed.invoke(carObject, 200);
        System.out.println(clazz.getMethod("getMaxSpeed").invoke(carObject));
                
        //2.1.调用一般方法:public方法,公有方法也可以使用getDeclaredMethod来调用保证参数正确即可
        Method introduceMethod_public = clazz.getDeclaredMethod("introduce");
        introduceMethod_public.invoke(carObject, null);
        
        //2.2.调用一般方法:private方法(参数严格匹配)    +   方法返回值为object
        //Method introduceMethod_private = clazz.getDeclaredMethod("introduce", null);
        Method introduceMethod_private = clazz.getDeclaredMethod("introduce", String.class);
        introduceMethod_private.setAccessible(true);
        Object result = introduceMethod_private.invoke(carObject, "别克");
        
        //2.3.调用一般方法:static方法,invoke的第一个参数是null,不能去掉这个参数
        Method introduceMethod_static = clazz.getMethod("introduce", String.class, String.class, int.class);
        introduceMethod_static.invoke(null, "别克", "白色", 200);
        
        //2.3.1.打印方法签名
        int a = introduceMethod_static.getModifiers();  //拿到修饰符代表的数字 
        String aString  = Modifier.toString(a);    //对数字进行解析,这里是public static
        Class reTy = introduceMethod_static.getReturnType();  //返回类型,全称
        Class[] paTy = introduceMethod_static.getParameterTypes();  //参数类型,全称的数组
        
        StringBuilder strBuilder = new StringBuilder();
        strBuilder.append(Modifier.toString(introduceMethod_static.getModifiers()) + " " + 
        		introduceMethod_static.getReturnType().getSimpleName() + " " + introduceMethod_static.getName() + "(");
        
        for (Class pC : paTy) {
			String parameterTypeString = pC.getSimpleName();
			strBuilder.append(parameterTypeString + ",");
		}
        
        if(strBuilder.toString() != "") {
        	strBuilder.delete(strBuilder.length() - 1, strBuilder.length());
        }
        
        strBuilder.append(")");
		System.out.println(strBuilder);
        
        //第四部分:获取所有方法参数和返回值
		//构造方法
		Constructor[] constructors = clazz.getDeclaredConstructors();
		for(Constructor cons : constructors) {
			StringBuilder strBuild = new StringBuilder();
            strBuild.append(Modifier.toString(cons.getModifiers()) + " ");
            strBuild.append(cons.getName() + "(");
            
            String pTypeString = "";
            for (Class pC : cons.getParameterTypes()) {
    			pTypeString = pC.getSimpleName();
    			strBuild.append(pTypeString + ",");
    		}
            
            if(pTypeString != "") {
            	strBuild.delete(strBuild.length() - 1, strBuild.length());
            }
            
            strBuild.append(")");
			System.out.println(strBuild);
		}
		
		//字段
		Field[] fields = clazz.getDeclaredFields();
		for(Field fied : fields) {
			System.out.println(fied.getType().getSimpleName() + " " + fied.getName());
		}
		
		//成员方法
        Method[] methods= clazz.getDeclaredMethods();   //获取类中所有方法,一定用getDeclaredMethods
        for (Method method: methods) {
        	int aa = method.getModifiers();  //拿到修饰符代表的数字 
            String aaString  = Modifier.toString(a);    //对数字进行解析,这里是public static
            Class reType = method.getReturnType();  //返回类型,全称
            Class[] paType = method.getParameterTypes();  //参数类型,全称的数组
            
            StringBuilder strBuild = new StringBuilder();
            strBuild.append(Modifier.toString(method.getModifiers()) + " ");
            strBuild.append(method.getReturnType().getSimpleName() + " ");
            strBuild.append(method.getName() + "(");
            
            for (Class pC : method.getParameterTypes()) {
    			String pTypeString = pC.getSimpleName();
    			strBuild.append(pTypeString + ",");
    		}
            
            if(strBuild.toString() != "") {
            	strBuild.delete(strBuild.length() - 1, strBuild.length());
            }
            
            strBuild.append(")");
			System.out.println(strBuild);
		}
        
        return carObject;
    }

    public static void main(String[] args) throws Throwable {
        //Object car = new ReflectionMyself().initByDefaultConst(new Car());
    	Object car = new ReflectionMyself().initByDefaultConst();
    }
}

参考文章:

1.https://www.jianshu.com/p/736e58d99bcf

2.待补充

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值