第十九章:反射

一、使用反射解决读取配置文件的问题

作用:可以在不修改源代码的基础上就可以实现功能,很牛啊 案例1

(1)在src下新建配置文件 re.properties

classfullpath=com.hspedu.Cat
method=hi

(2)在src下新建com.hspedu包下新建Cat类

package com.hspedu;

public class Cat {
    private String name = "招财猫";
    public void hi(){
        System.out.println("hi"+name);
    }
}

(3)主方法

@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
    public static void main(String[] args) throws Exception{
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\re.properties"));
        String classfullpath = properties.get("classfullpath").toString();//"com.hspedu.Cat
        String methods = properties.get("method").toString();//hi
//        System.out.println(classfullpath+methods);

        //3.使用反射机制解决
        //(1)加载类,返回Class类型对象 cls
        Class<?> cls = Class.forName(classfullpath);
        //(2)通过 cls 得到你加载的类 com.hspedu.Cat的对象实例
        Object o = cls.newInstance();
        System.out.println("运行类型:"+o.getClass()); //运行类型
        //(3)通过cls得到你加载类的method的methodName 的方法对象 在反射中 可以把方法看为对象
        Method method1 = cls.getMethod(methods);
        //(4)通过method1调用方法,即通过方法对象来实现调用方法
        method1.invoke(o);//传统方法 对象.方法() , 反射机制  方法.invoke(对象)
    }
}

二、反射机制

(1)反射机制

  1. 在运行时判断任意一个对象所属的类
  2. 在运行时构造任意一个类的对象
  3. 在运行时得到任意一个类所具有的成员变量和方法
  4. 在运行时调用任意一个对象的成员变量和方法
  5. 生成动态代理

(2)反射相关的主要类

  1. java.lang.Class:代表一个类
  2. java.lang.reflect.Method:代表类的方法
  3. java.lang.reflect.Filed:代表类的成员变量
  4. java.lang.reflect.Constructor:代表类的构造方法
@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
    public static void main(String[] args) throws Exception{
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\re.properties"));
        String classfullpath = properties.get("classfullpath").toString();//"com.hspedu.Cat
        String methods = properties.get("method").toString();//hi
        //3.使用反射机制解决
        //(1)加载类,返回Class类型对象 cls
        Class<?> cls = Class.forName(classfullpath);
        //(2)通过 cls 得到你加载的类 com.hspedu.Cat的对象实例
        Object o = cls.newInstance();
        System.out.println("运行类型:"+o.getClass()); //运行类型
        //(3)通过cls得到你加载类的method的methodName 的方法对象 在反射中 可以把方法看为对象
        Method method1 = cls.getMethod(methods);
        //(4)通过method1调用方法,即通过方法对象来实现调用方法
        method1.invoke(o);//传统方法 对象.方法() , 反射机制  方法.invoke(对象)
        //得到name字段
        Field name = cls.getField("name");//getFild不能获取私有属性
        System.out.println(name.get(o)); //传统写法 对象.成员变量  反射 :  成员变量对象.get(对象)
        //获取构造器
        Constructor<?> constructor = cls.getConstructor(); //()可以指定构造器
        System.out.println(constructor);
    }
}

三、反射调用方法的优化

hi.setAccessible(true); //在反射调用方法时,取消访问检查

//(3)通过cls得到你加载类的method的methodName 的方法对象 在反射中 可以把方法看为对象
        Method method1 = cls.getMethod(methods);
        method1.setAccessible(true);

 四、Class类常用的方法

@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
    public static void main(String[] args) throws Exception{
        String classAllPath = "com.hspedu.Cat";
        //获取Cat类 对应 的Class对象
        //<?> 表示不确定Java类型
        Class<?> cls = Class.forName(classAllPath);
        //输出cls
        System.out.println(cls.getClass());//获取运行类型
        //获取包名
        System.out.println(cls.getPackage().getName());
        //获取类名
        System.out.println(cls.getName());
        //通过cls创建对象实例
        Object o = cls.newInstance();
        //获取成员  私有属性会报错的
        Field name = cls.getField("name");
        System.out.println(name.get(o)); //反射原理
        //通过反射给属性设置值
        name.set(o,"汤姆猫");
        System.out.println(name.get(o));
    }
}

五、反射实例

(1)反射爆破创建实例:

@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
    public static void main(String[] args) throws Exception{
        //1.先获取到User类的Class
        Class<?> userClass = Class.forName("com.hspedu.User");
        //2.通过public的无参构造器创建实例
        Object o = userClass.newInstance();
        System.out.println(o);
        //3.通过public的有参构造器创建实例
        //3.1.先得到构造器
        Constructor<?> constructor = userClass.getConstructor(int.class);
        //3.2 创建实例
        Object hsp = constructor.newInstance(19);
        System.out.println(hsp);
        //4.通过private的有参构造器创建实例
        //4.1.先得到构造器
        Constructor<?> constructor1 = userClass.getDeclaredConstructor(int.class, String.class);
        //4.2 创建实例
        constructor1.setAccessible(true); //爆破 使用反射可以访问私有(private)构造器
        Object zsf = constructor1.newInstance(100, "张三丰");
        System.out.println(zsf);
    }
}
package com.hspedu;

public class User {
    private int age = 10;
    private String name = "张三";

    public User() {
    }

    public User(int age) {
        this.age = age;
    }

    private User(int age, String name) {
        this.age = age;
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

(2)反射爆破操作属性:

@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
    public static void main(String[] args) throws Exception{
        //1.先获取到User类的Class
        Class<?> userClass = Class.forName("com.hspedu.User");
        //2.创建对象
        Object o = userClass.newInstance();
        System.out.println(o.getClass());
        //3.使用反射得到age属性对象
        Field age = userClass.getField("age");
        age.set(o,88);
        System.out.println(age.get(o));//返回属性值
        //使用反射操作name属性
        Field name = userClass.getDeclaredField("name");
        //对name进行爆破,可以操作private属性
        name.setAccessible(true);
        name.set(o,"老韩");
        System.out.println(o);
    }
}
package com.hspedu;

public class User {
    public int age;
    private static String name;

    public User() {
    }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

(3)使用反射获取方法:

@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
    public static void main(String[] args) throws Exception {
        //1.先获取到User类的Class
        Class<?> userClass = Class.forName("com.hspedu.User");
        //2.创建对象
        Object o = userClass.newInstance();
        //3.调用public的hi方法
//        Method h1 = userClass.getMethod("hi",String.class); //获取public
        Method h1 = userClass.getDeclaredMethod("hi", String.class);//获取全部方法包括私有
        //3.2调用
        h1.invoke(o, "韩顺平教育");
        //4.调用private static 方法
        //4.得到say 方法对象
        Method say = userClass.getDeclaredMethod("say", int.class, String.class, char.class);
        //私有方法所以我们需要爆破一下
        say.setAccessible(true);
        Object invoke = say.invoke(o, 12, "张三", 'A');
        System.out.println(invoke);
    }
}
package com.hspedu;

public class User {
    public int age;
    private static String name;

    public User() {
    }

    private static String say(int n, String s, char c) {
        return n + " " + s + " " + c;
    }

    public void hi(String s) {
        System.out.println("hi " + s);
    }

    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

六、课后作业

@SuppressWarnings({"all"}) //取消文件警告
public class Hello {
    public static void main(String[] args) throws Exception {
        //1.先获取到User类的Class
        Class<?> userClass = Class.forName("com.hspedu.User");
        //2.创建对象
        Object o = userClass.newInstance();
        Field name = userClass.getDeclaredField("name");
        name.setAccessible(true); //爆破啊
        System.out.println(name.get(o)); //获取未修改前
        name.set(o,"韩老师");
        Method getName = userClass.getMethod("getName");
        System.out.println(getName.invoke(o));
    }
}
package com.hspedu;

public class User {
    private  String name = "hellokitty";

    public String getName() {
        return name;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值