Java中的反射

Java中的反射机制

上文我们讲了类文件是如何加载到JVM内存中(类加载过程),这些加载到JVM 的类不仅JVM 能调用它,我们也能通过编程的方式对着写Class对象进行操作,这就要通过反射机制来实现了。

Java中反射主要是通过java.reflect包中的对象来实现的,下面详细介绍下一些常见的反射使用方法。

1.如何获取一个类对象

方式一.通过类的getClass()方法

/**
 *  方式一.通过类的getClass()方法
 *  都已经得到对象了,反射显得多余
 **/
public Class getClassMethod1(){
    ManDemo md = new ManDemo();
    return md.getClass();
}

方式二.通过类的.class 获取

 /**
  *  方式二.通过类的.class 获取
  *  强依赖,需要引入相关类
 **/
public Class getClassMethod2(){
    return ManDemo.class;
}

方式三.通过 Class.forName("") 获取

    /**
     *  方式三.通过 Class.forName("") 获取
     *  灵活 首要选择
     *  这里需要注意,通过类的全路径名获取Class对象会抛出一个异常,如果根据类路径找不到这个类那么就会抛出这个异常。
     **/
public Class getClassMethod3(){
    Class c = null;
    try {
        c = Class.forName("try1.ManDemo");
        c.getName();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    return c;
}

方式四.通过类装载器 ClassLoader获取

 public Class getClassMethod4(){
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        Class c = null;
        try{
            c = loader.loadClass("try1.ManDemo");
        }catch (Exception e){
            e.printStackTrace();
        }
        return c;
    }

其中方式三灵活,是一般进行反射操作的首要选择。

2.如何获取构造方法

    /**
     * 获取构造方法
     **/
    public void getConstructors(){
        Class c = getClassMethod3();
        //获取所有构造方法
        System.out.println("----------获取所有public构造方法-----------");
        Constructor[] constructors = c.getConstructors();
        for (Constructor cc:constructors) {
            System.out.println(cc);
        }
        System.out.println("----------获取所有声明过的构造方法-----------");
        Constructor[] constructors2 = c.getDeclaredConstructors();
        for (Constructor cc:constructors2) {
            System.out.println(cc);
        }
        try {
            System.out.println("----------获取类中指定参数类型的public构造方法-----------");
            System.out.println( c.getConstructor(String.class,Integer.class));
            System.out.println( c.getConstructor(Integer.class,String.class));
            System.out.println( c.getConstructor());


            System.out.println("----------获取类中指定参数类型的所有构造方法-----------");
            System.out.println( c.getDeclaredConstructor(String.class));
            System.out.println( c.getDeclaredConstructor(Integer.class,String.class));

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

1.class.getConstructors():获取类中所有public构造方法

2.class.getDeclaredConstructors():获取类中所有声明过的构造方法

3.class.getConstructor(Class<?>… parameterTypes):获取类中指定参数类型的public构造方法

4.class.getDeclaredConstructor(Class<?>… parameterTypes):获取类中指定参数类型的所有构造方法

3.获取类中属性

    /**
     * 获取类中属性
     **/
    public void getFields(){
        Class c = getClassMethod3();
        System.out.println("----------1.获取所有共有字段------------");
        Field[] fields = c.getFields();
        for (Field f: fields) {
            System.out.println(f);
        }
        System.out.println("----------2.获取所有声明过的字段------------");
        Field[] fields1 = c.getDeclaredFields();
        for (Field f: fields1) {
            System.out.println(f);
        }
        System.out.println("----------3.获取共有字段并使用-----------");
        try {
            //获得指定的共有字段
            Field field = c.getField("sex");
            //获取一个公有构造方法,并实例化
            Object obj = c.getConstructor().newInstance();
            //为属性设置值
            field.set(obj,true);
            ManDemo man = (ManDemo)obj;
            System.out.println(man.sex);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("----------4.获取私有字段并使用-----------");
        try {
            Field nameField = c.getDeclaredField("name");
            Object obj2 = c.getConstructor().newInstance();
            //设置暴力反射 允许修改私有字段 否则修改私有字段会产生异常
            nameField.setAccessible(true);
            nameField.set(obj2,"王舞");
            ManDemo man = (ManDemo)obj2;
            System.out.println(man.getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

1.class.getFields() :获取所有public字段

2.class.getDeclaredFields() :获取所有声明过的字段

3.class.getField(String name) :获取指定名字的public字段

4.class.getDeclaredField(String name) :获取私有字段并使用

获取字段后使用,方法见上文的实例代码

4.获取类中方法

    /**
     * 获取类中方法
     **/
    public void geMethods(){
        Class c = getClassMethod3();
        System.out.println("----------1.获取所有共有方法------------");
        Method[] methods = c.getMethods();
        for (Method m:methods) {
            System.out.println(m);
        }
        System.out.println("----------2.获取所有方法------------");
        Method[] methods1 = c.getDeclaredMethods();
        for (Method m:methods1) {
            System.out.println(m);
        }
        try {
            Object obj = c.getConstructor().newInstance();

            System.out.println("----------3.获取特定的方法并使用(不带参)------------");
            Method m = c.getMethod("sleep");
            Method m0 = c.getMethod("sleep",Integer.class); //带参
            m.invoke(obj);
            System.out.println("----------4.获取特定的方法并使用(不带参、私有)------------");
            Method m1 =  c.getDeclaredMethod("think");
             //设置暴力反射 允许修改私有字段 否则调用私有方法会产生异常
            m1.setAccessible(true);
            m1.invoke(obj);
            System.out.println("----------5.获取特定的方法并使用(带参)------------");
            Method m2 =  c.getDeclaredMethod("eat1",String.class);
            m2.invoke(obj,"杨梅");
            c.getDeclaredMethod("drunk",String.class,Integer.class).invoke(obj,"橙汁",3);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

1.class.getMethods():获取类中所有public方法

2.class.getDeclaredMethods():获取类中所有方法

3.class.getMethod(String name, Class<?>… parameterTypes):获取特定的public方法并使用(只传name代表方法不带参)

4.class.getDeclaredMethod(String name, Class<?>… parameterTypes):获取特定的方法并使用(只传name代表方法不带参)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值