Java Reflect(反射一) 基本应用

Everyone’s heart is a piece of sea,shining bottomless blue.

在开发android的路上,java的编程思想一直是android开发的指南。

java的反射机制,使得类的调用,方法的使用更加的灵活。

所以对java Reflect 进行整理。

注意:使用java反射机制,对于内存的开销会大。所以在程序中,非必要的情况下,尽量少用反射,用就要用的有价值。

Let’s Beginning

反射基本使用

在java中,得到类,实例化类,然后使用对象调用类中方法。这是正常流程。
在java反射中,可以灵活的使用类。达到动态实现的效果。

/*在reflect中会主要使用到的类*/

//构造方法
import java.lang.reflect.Constructor;
//类中属性
import java.lang.reflect.Field;
//类中方法
import java.lang.reflect.Method;

Step1:创建java类,如下:

package com.example;

public class ReflectClass{

    /*无参的构造函数*/
    public ReflectClass() {
    }

    /*私有属性*/
    private String s_name;
    private String s_age;
    private String s_number;

    /*公有属性*/
    public int s_grade;

    /*保护类型属性*/
    protected String s_degree;

    /*含有参数的构造函数*/
    public ReflectClass(String s_name, String s_age, String s_number) {
        this.s_name = s_name;
        this.s_age = s_age;
        this.s_number = s_number;
    }

    public String getS_name() {
        return s_name;
    }

    public void setS_name(String s_name) {
        this.s_name = s_name;
    }

    public String getS_age() {
        return s_age;
    }

    public void setS_age(String s_age) {
        this.s_age = s_age;
    }

    public String getS_number() {
        return s_number;
    }

    public void setS_number(String s_number) {
        this.s_number = s_number;
    }

    @Override
    public String toString() {
        return "ReflectClass{" +
                "s_name='" + s_name + '\'' +
                ", s_age='" + s_age + '\'' +
                ", s_number='" + s_number + '\'' +
                '}';
    }
}

Step2: 使用反射调方法

public static void main(String[] args){

        Scanner scanner = new Scanner(System.in);

        System.out.println("请您输入需要动态加载的类:\n");

        String className = scanner.nextLine();

        System.out.println("您输入的类名为:\n"+className);

        /*动态加载类*/
        try {
            /*通过反射加载我们想到动态加载的类*/

            /*1:获取要加载的类
            *
            *   获取class对象的三种方式
            *
            *   1> Class<?> clz = Class.forName(className);
            *   2> Class<?> clz = ClassName.class;
            *   3> ClassName className = new ClassName();
            *      Class<?> clz = className.getClass();
            * */

            Class<?> clz = Class.forName(className);

            System.out.println("clz ===="+clz);

            if(clz == null){
                System.out.println("sorry,您的Class不存在!");
            }

            /*2:实例化该类,要添加异常处理*/
            Object obj = clz.newInstance();

            /*3:得到类,并且实例化后,便可以操作方法,属性。
                先看看我们使用这种方式能够得到哪些内容
            */
            /*public Method[] getDeclaredMethods() throws SecurityException
            *
            * 获取clz中的所有方法
            * */
            Method[] methods = clz.getDeclaredMethods();

            for (int i = 0;i<methods.length;i++){
                //看看这里的所获取到所有的方法的名称,和我们的类中是否是一致
                System.out.println(className +"中中定义的所有方法----"+i+"----"+methods[i]);
            }

            /* Method getDeclaredMethod(String name, Class<?>... parameterTypes)
            *
            *  获取到固定方法,现在我想获取到getS_name()方法
            *
            * */
            Method method = clz.getDeclaredMethod("getS_name");

            System.out.println("method------->"+method.getName()+"------>"+method);

            /*
            获取某个方法的返回类型
            */
            Class<?> methodType = method.getReturnType();

            System.out.println("methodType[getS_name]------------>"+methodType);

            /*获取到类中的所有属性
            *
            * public Field[] getDeclaredFields() throws SecurityException
            * */
            Field[] fields = clz.getDeclaredFields();
            for (int i=0;i<fields.length;i++){
                /*看看输出是否是我们的target class*/
                System.out.println("fields["+i+"]"+"=========="+fields[i]);
            }

            /*获取单一确定属性
            *
            * public Field getDeclaredField(String name)
            *
            * */
            Field field = clz.getDeclaredField("s_name");

            System.out.println("Field_s_name----------------->"+field);


            /*
            * 获取所有的构造方法
            * public Constructor<?>[] getDeclaredConstructors() throws SecurityException
            *
            *
            * */
            Constructor<?>[] constructors = clz.getDeclaredConstructors();
            System.out.print("改类中的所有构造方法:\n");
            for (int i=0;i<constructors.length;i++){
                System.out.println("constructors["+i+"]"+"-------->"+constructors[i]);
            }
            /*获取具体的构造方法*/
            Constructor<?> constructor =clz.getDeclaredConstructor(String.class,String.class,String.class);
            System.out.println("constructor-------->"+constructor);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            System.out.print("sorry,The className is null point");
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }

Step3:我们现在Run Application,结果如下

这里写图片描述

summary:反射所得到的方法,属性十分的明确,所以我们是可以通过反射明确的获取到类中的每个方法。

反射的 类中继承ParentClass或者implement Interface

Step1: 创建你的parentClass类,Interface接口
Step2: 目标类extends ParentClass implements Interface
Step3: 前面步骤和上面基础一致。在代码中添加

 /*
            *
            * 获取superParentClass
            * public native Class<? super T> getSuperclass();
            * 目前并没有父类方法
            * */

            Class<?> superClass = clz.getSuperclass();
            System.out.println("superClass------->"+superClass);

            /*
            * 获取到该类所实现的接口
            *
            * public Class<?>[] getInterfaces() {
            * */
            Class<?>[] interfaceClasses = clz.getInterfaces();

            System.out.println("获取到该类所实现的接口");
            for(int i = 0;i<interfaceClasses.length;i++){
                System.out.println("interfaceClasses["+i+"]------------>"+interfaceClasses[i]);
            }

这里写图片描述

如何应用使用反射获取的方法或者属性

调用方法

在上面的代码中,我们实例化Class对象
Object obj = clz.newInstance();
一直没有使用。那么现在来看看它的用处:

1:获取到clz类中的getS_name(),并且得到它的返回值,并进行打印输出。
/*1:得到getS_name()方法*/

Method methodGetName = clz.getDeclaredMethod("getS_name");

/*2:使用方法,并且得到返回值

    @param obj
    @param args:如果你调用的方法需要传入参数就请传入相应类型的参数值

    public Object invoke(Object obj, Object... args)

    PS:因为目前调用的方法为无参方法,所以直接调用
*/

String result = methodGetName.invoke(obj);

System.out.println("result===="+result);

这里写图片描述

事实上,我们已经获得了getS_name()中返回的值了。之所以为null那是因为在java中,String类型的变量当没有为其赋值的时候,默认为null


那么现在我们为s_name赋值,然后在进行获取,看看变化:
/*1:获取setS_name(String)方法*/
Method methodSetName = clz.getDeclaredMethod("setS_name",String.class);

/*2:为setS_name(String)赋值 */
methodSetName.invoke(obj,"测试数据");

/*3:此时我们在获取getS_name()方法*/
Method methodGetName = clz.getDeclaredMethod("getS_name");

/*4: 打印输出getS_name()中的返回值*/
System.out.println("getS_name()===="+methodGetName.invoke(obj));

这里写图片描述

此时我们所赋值的数据被获取出来了。

操作属性

1:操作public属性或者protected属性
/*1:获取公有属性*/

Field field = clz.getDeclaredField("s_grade");

/*2:获取该属性的值

    方法:

    public Object get(Object obj)
*/

int grade = field.get(obj);

/*3:输出公有属性的值*/

System.out.println("public s_grade value is:----->"+grade );

这里写图片描述

java中默认的int类型值为0

为公有属性赋值:
/*1:获取公有属性*/

Field field = clz.getDeclaredField("s_grade");

/*2:设置该属性的值

    方法:

    public void set(Object obj, Object value)
*/

field.set(obj,10);

/*3:输出公有属性的值*/

System.out.println("public s_grade value is:----->"+field.get(obj));

这里写图片描述

此时该值已经被改变。

2:如果使用上述方法操作private属性,会出现错误如下:

  field = clz.getDeclaredField("s_age");
            System.out.println("private s_age value is:--------->"+field.get(obj));
run后的错误如下:

这里写图片描述

无法操作private属性

这种情况也是可以预见的,在 我们正常的使用Class的时候,是无法对其私有的属性或者方法来进行使用的。

但是,在反射中,可以通过设置
/*设置可访问权限*/
public void setAccessible(boolean flag)
来使得类对其进行访问并实现修改

如下:
field = clz.getDeclaredField("s_age");

field.setAccessible(true);

System.out.println("private s_age value is:--------->"+field.get(obj));

这里写图片描述

此时可以进行访问。值为null 相比不用在解释了吧!

关于Reflect反射的基础使用就告一段落。后续会更新关于使用Reflect工厂模式的使用。


END

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值