反射基础

 

概念:
    java反射机制是在运行状态中,对任意一个类,都能够知道这个类的所有属性和方法;
    对于任意一个对象,都能够调用它的任意一个方法;
    这种动态获取的信息以及动态调用对象方法的功能称为java语言的反射机制。

一些人听着反射,可能有些懵。主要是工作中几乎不需要接触。就像玩王者荣耀或lol,没有接触过的英雄,总觉得自己玩不好。

不过,反射比学一个英雄还简单点。主要是理解。

反射要点:
1. 获取需要的类  (Class类)
2. 获取该类的构造函数、成员变量、方法
3. 这步不说也知道是什么了吧。使用该类,赋值、调用方法。

第一步: 获取需要的Class类,直接看方式三; 方式1、2都可以不用了解。

package com.demo;

/**
 * @author: wangqinmin
 * @date: 2019/1/7 10:11
 * @description: 仰天大笑出门去,我辈岂是蓬蒿人
 */
public class DemoTestOne {

    /**
     * 反射,最基本的获取class(字节码文件对象)的3种方式
     *
     * @param args
     */
    public static void main(String[] args) {
        getClassObjectOne();
        System.out.println("----------");
        getClassObjectTwo();
        System.out.println("----------");
        try {
            getClassObjectThree();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }


    /**
     * 获取字节码对象的第一种方式:不适合扩展
     * 1. Object类中的getClass方法
     * 要求:想用这种方法,必须要明确知道具体的类,并创建对象
     */
    public static void getClassObjectOne() {
        Person p = new Person();
        Class<? extends Person> c1 = p.getClass();
        Person p1 = new Person();
        Class<? extends Person> c2 = p1.getClass();
        System.out.println(c1 == c2);
    }


    /**
     * 第二种方式:不适合扩展
     * 任何数据类型都具备一个静态的属性.class,所以通过这个获取其对应的Class对象。
     * 要求:这种方式,相对简单。但是还是要明确知道类中的静态成员
     */
    public static void getClassObjectTwo() {
        Class<Person> c1 = Person.class;
        Class<Person> c2 = Person.class;
        System.out.println(c1 == c2);
    }


    
    方式三:(上面的方式一,方式二,看看就好了)
    要求:给定类的字符串名称
    java.lang
    类 Class<T>,该类的方法,有很多。用于反射正好
    public static void getClassObjectThree() throws ClassNotFoundException {
        // 传入参数:包名 + 类名
        String className = "com.demo.Person";
        Class<?> c1 = Class.forName(className);
        System.out.println(c1);
    }
}

我把反射要用的Person类,也贴出来:

package com.demo;

/**
 * @author: wangqinmin
 * @date: 2019/1/7 10:44
 * @description: 仰天大笑出门去,我辈岂是蓬蒿人
 */
public class Person {

    private Integer age;
    private String name;

    public Person(Integer age, String name) {
        this.age = age;
        this.name = name;
        System.out.println("有参构造方法");
    }

    public Person() {
        System.out.println("无参构造方法");
    }

    public void show() {
        System.out.println(name + ",show方法," + age);
    }

    public void method() {
        System.out.println("方法运行");
    }

    public void paramMethod(String str, int num) {
        System.out.println("传入参数:" + str + "," + num);
    }

    public static void staticMethod() {
        System.out.println("静态方法运行");
    }
}

接下来就是第二步了:

使用反射的Class对象,获取构造函数、成员变量,成员方法,一个完整的例子。

先说要点:
1. 反射相当于new 对象,既然是new 对象。
注意问题: 该对象是否有无参构造,或者构造函数是否被私有


package com.demo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

/**
 * @author: wangqinmin
 * @date: 2019/1/8 10:27
 * @description: 仰天大笑出门去,我辈岂是蓬蒿人
 */
public class DemoTestTwo {

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

        若该对象有public修饰的无参构造,反射new 对象
        Class<?> personClass = Class.forName("com.demo.Person");
        创建Class对象所表示的新对象,被创建对象必须提供无参构造
        Person person = (Person) personClass.newInstance();
        System.out.println("----------------");

        1. 获取所有public、private等修饰的构造方法
        Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors();

        1. 若被反射的对象,没有无参构造时。先获取构造函数
        Constructor<?>[] constructors = personClass.getConstructors();
        for (Constructor con : constructors) {
            System.out.println(con);
            // public com.demo.Person(java.lang.Integer,java.lang.String)
            // public com.demo.Person()
        }
        System.out.println("----------------");


        1.1 通过获取构造函数  创建对象
        Constructor<?> constructor = personClass.getConstructor(Integer.class, String.class);
        System.out.println(constructor);
        通过构造器对象,初始化对象(实例化)
        Object obj = constructor.newInstance(12, "蔡文姬");
        System.out.println("----------------");

        2. 获取public修饰的成员变量
        Field[] fields = personClass.getFields();
        for (Field f : fields) {
            System.out.println(f);
        }
        System.out.println("----------------");

        2. 能够获取private修饰的成员变量
        Field[] declaredFields = personClass.getDeclaredFields();
        for (Field d : declaredFields) {
            System.out.println(d);
        }
        System.out.println("----------------");

        3. 获取public修饰的方法方法
        Method[] methods = personClass.getMethods();
        for (Method m : methods) {
            System.out.println(m);
            // public void com.demo.Person.method()
            // public void com.demo.Person.paramMethod(java.lang.String,int)
            // public void com.demo.Person.show()
            // public static void com.demo.Person.staticMethod()
            // public final void java.lang.Object.wait() throws java.lang.InterruptedException
            // public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
            // public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
            // public boolean java.lang.Object.equals(java.lang.Object)
            // public java.lang.String java.lang.Object.toString()
            // public native int java.lang.Object.hashCode()
            // public final native java.lang.Class java.lang.Object.getClass()
            // public final native void java.lang.Object.notify()
            // public final native void java.lang.Object.notifyAll()
        }
        System.out.println("----------------");


        3. 获取所有本类中的所有方法
        Method[] declaredMethods = personClass.getDeclaredMethods();
        for (Method m : declaredMethods) {
            System.out.println(m);
            // public void com.demo.Person.method()
            // public void com.demo.Person.show()
            // public void com.demo.Person.paramMethod(java.lang.String,int)
            // public static void com.demo.Person.staticMethod()
        }
        System.out.println("----------------");
    }
}

接下来就是一个小练习,使用反射,这里面深度解析为什么使用反射,反射的应用场景:

https://blog.csdn.net/chuxin_mm/article/details/86507928

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值