Java基础---反射 取属性值、执行方法

1.为啥用反射?

用框架时,
想要调用 哪个类 中的 哪个方法。
不必改源码,
直接在 配置文件=解耦=封装性 中改。

2.子类 通过反射 能拿到父类公有,拿不到 父类私有

尝试拿 父类 的 私有属性、方法:
私有的不能被子类继承 
肯定 即便是 子类用 declared也不能拿到

3.单例模式 不让new对象;反射 直接通过字节码文件获取对象
岂不是和单例模式冲突了???

没有冲突。
不存在冲突 不冲突的问题。
设计模式不属于java中真正的底层知识点,
他只是一种代码的 设计思想
一共有23例设计模式,用了有更好的效果 不用也可以。

那单例模式里面有办法可以避免反射吗?

没有。
私有属性方法  用反射都能打破,更别说只是个设计模式了。

4.用反射 属性值要怎么拿到?方法要怎么执行?

面向对象!
属性、方法
都由 对象  搞

5.写代码吧
5.1 创建1个Animal类

import javax.xml.transform.Source;
import java.sql.SQLOutput;

public class Animal {
    //私有属性  爱人
    private String lover="person";

    //公有属性 名字
    public String name="lucy";


    //此处不必要 加 私有构造方法   仅可拿公有构造getConstructor
    //公有、无参 构造
    public Animal() {
        System.out.println("公有 、 无参 构造执行了");
    }


    //私有方法
    private void sleep(){
        System.out.println("私有方法睡觉  执行了");
    }

    //公有方法
    public void eat(String name,String food){
        System.out.println(name+"开始吃"+food);
        System.out.println("公有方法吃饭 执行了");
    }

}

5.2测试类:

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

public class MyReflect {
    public static void main(String[] args) throws Exception {
            //show属性
//            showField();

            //show方法
            showMethod();

    }


    //通过反射   拿到 指定属性  的  值
    //    1.拿到类对象=字节码对象
    //    2.拿到属性
    //    3.拿到属性值
    public static void showField() throws Exception {

        //forName(String className)
        //返回与给定字符串名称的类或接口相关联的 类对象=字节码对象。
        //框架中 读取配置文件 获取到的都是字符串数据类型,所以常用此种 参数正好为字符串数据类型
        Class aClass = Class.forName("Animal");//全限定名=绝对路径
//        Class<Animal> animalClass = Animal.class;
//        Class<? extends Animal> aClass1 = new Animal().getClass();

        //----------------拿 公有属性值  开始---------------------------

        Field name = aClass.getField("name");
//        System.out.println(name);
        //public java.lang.String Animal.name

        //get(Object obj)
        //返回该所表示的字段的值 Field ,指定的对象上。   =属性值
        //此中obj
        //  面向对象  属性、方法 均由 对象执行

        Object o = aClass.newInstance();
//        System.out.println(o);
        //公有无参 构造执行了
        //Animal@1540e19d

        Object o2 = name.get(o);
        System.out.println(o2);
        //lucy
        //----------------拿 公有属性值  结束---------------------------

        //----------------拿 私有属性值  开始---------------------------
        //1.拿到字节码
        //2.拿到私有属性
        //3.设置可访问为true
        //4.拿到属性值

//        Field[] fields = aClass.getDeclaredFields();
//        Field field = fields[0];
        Field lover = aClass.getDeclaredField("lover");
        //拿到属性后  直接获取私有值=报错   先暴力破解
        lover.setAccessible(true);//Accessible=可访问

        Object o3 = lover.get(new Animal());
        System.out.println(o3);
        //公有 、 无参 构造执行了
        //person
        //----------------拿 私有属性值  结束--------------------------

    }


    /**
     *通过反射   执行 指定方法
     *      1.拿 字节码对象
     *      2.拿方法
     *      3.invoke执行
     */
    public static void showMethod() throws Exception{
        Class aClass = Class.forName("Animal");

        //getMethod(String name, 类<?>... parameterTypes)
        Method eat = aClass.getMethod("eat",String.class,String.class);

        eat.invoke(aClass.newInstance(),"苏溪","披萨");
        //公有 、 无参 构造执行了
        //苏溪开始吃披萨
        //公有方法吃饭 执行了


        //------------执行  私有方法   开始--------------
        //只要是 私有   设可访问为true
//        Method[] declaredMethods = aClass.getDeclaredMethods();
        Method sleep = aClass.getDeclaredMethod("sleep");
        sleep.setAccessible(true);
        sleep.invoke((Animal)aClass.getConstructor(null).newInstance());
        //公有 、 无参 构造执行了
        //私有方法睡觉  执行了

    }

}

6.总结
6.1 由以上可看出

反射创建实例的难点在于,很多人不知道:
clazz.newInstance()底层还是调用Contructor对象的newInstance()。
所以,要想调用clazz.newInstance(),必须保证编写类的时候有个 无参构造。

6.2浅谈反射机制【有空深入理解一下这篇文章】

https://zhuanlan.zhihu.com/p/66853751
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值