反射详解加案例


java注解

image.png
image.png

反射

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.

类初始化时机

1. 创建类的实例
2. 访问类的静态变量,或者为静态变量赋值
3. 调用类的静态方法
4. 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
5. 初始化某个类的子类
6. 直接使用java.exe命令来运行某个主类

类加载器

1.负责将.class文件加载到内在中,并为之生成对应的Class对象
2. 虽然我们不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行。
3. Bootstrap ClassLoader 根类加载器
4. Extension ClassLoader 扩展类加载器
5. Sysetm ClassLoader 系统类加载器
实例
package com.the151suggestions.reflect;

/**
 * Created by wanggs on 2017/7/23.
 * 所有类的对象其实都是Class的实例。
 * 1. 反射就是通过Class文件对象,去使用文件中的成员变量,构造方法,成员方法
 * 2. 首先得到Class文件对象,其实就是得到Class类的对象
 * Class:
 * 成员变量: Field
 * 构造方法: Construction
 * 成员方法: Method
 * 获取class对象的方式
 *      A:Object类的getClass()
 *      B:数据类型的静态属性
 *      C: Class类中的静态方法
 *          Public static Class forNmae(String className)// 类的全路径
 */
public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException {
        // 获取Class文件对象
        //  方式 1
        Person person = new Person();
       Class c   = person.getClass();
       // 方式 2
       Class c1 = Person.class;
       // 方式 3
        Class c2 = Class.forName("com.the151suggestions.reflect.Person");

        System.out.println(c1 == c2); // true
        System.out.println(c2); // 输出 class com.the151suggestions.reflect.Person


    }
}


class Person {
    private String name;
    public int age;
    public String address;

    public Person() {
    }

    public Person(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

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

    // 方法
    public void show() {
        System.out.println("Person.show");
    }

    public void method(String s) {
        System.out.println("s = " + s);

    }

    public String getString(String s, int i) {
        return "s = " + s + "i = " + i;

    }

    private void function() {
        System.out.println("Person.function");
    }
}

通过反射获取构造方法并使用

  • 获取构造方法
getConstructors

getDeclaredConstructors

实例
public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException {
        // 获取Class文件对象
        Class c2 = Class.forName("com.the151suggestions.reflect.Person");

        // 获取构造方法
        Constructor[] classes = c2.getConstructors(); // 私有拿不到
        for (Constructor constructor : classes){
            System.out.println(constructor);
        }
    }
}

/**
 * public com.the151suggestions.reflect.Person(java.lang.String,int,java.lang.String)
 public com.the151suggestions.reflect.Person(int)
 public com.the151suggestions.reflect.Person(java.lang.String)
 public com.the151suggestions.reflect.Person()
 */

public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException {
        // 获取Class文件对象
        Class c2 = Class.forName("com.the151suggestions.reflect.Person");

        // 获取构造方法
        Constructor[] classes = c2.getDeclaredConstructors(); // 获取所有
        for (Constructor constructor : classes){
            System.out.println(constructor);
        }
    }
}

  • 创建对象
newInstance()
con.newInstance(“zhangsan", 20);

实例
public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        // 获取Class文件对象
        Class c2 = Class.forName("com.the151suggestions.reflect.Person");

      // 获取单个 public Constructor<T> getConstructor(Class<T>... args)
        Constructor constructor = c2.getConstructor(String.class); // 构造方法对象

       // Person p = new Person("tom);
        // public T newInstance(object... arg) 获取构造方法
        Person person = (Person) constructor.newInstance("tom");
        System.out.println(person );


    }
}

私有构造暴力访问
public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        // 获取Class文件对象
        Class c2 = Class.forName("com.the151suggestions.reflect.Person");

      // 获取单个 public Constructor<T> getConstructor(Class<T>... args)
        Constructor constructor = c2.getDeclaredConstructor(String.class); // 私有构造方法对象

        // 暴力访问
        constructor.setAccessible(true); // 取消java语言检查
        Person person = (Person) constructor.newInstance("tom");
        System.out.println(person );
        person.show();


    }
}

通过反射获取成员变量并使用

  • 获取所有成员
getFields,getDeclaredFields


  • 获取单个成员
getField,getDeclaredField

- 修改成员的值
set(Object obj,Object value) //将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
实例
public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        // 获取Class文件对象
        Class c2 = Class.forName("com.the151suggestions.reflect.Person");

        // 获取所有成员变量
        Field[] fields = c2.getDeclaredFields();// 包含私有
        for (Field field : fields) {
            System.out.println(field);
/**
 * public int com.the151suggestions.reflect.Person.age
 public java.lang.String com.the151suggestions.reflect.Person.address
 */
        }

        Constructor constructor = c2.getConstructor();
        Object object = constructor.newInstance();

        // 获取单个
        Field field = c2.getField("address");
        // 设置值 public void set(Object obj, Object value)
        field.set(object,"郑州");
        // Person p = new Person("郑州");
        System.out.println(object);


    }
}

通过反射获取成员方法并使用

  • 获取所有方法
getMethods
getDeclaredMethods

实例
public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        // 获取Class文件对象
        Class c2 = Class.forName("com.the151suggestions.reflect.Person");
        Method[] methods = c2.getMethods(); // 包括父亲的公共方法
        for(Method method : methods){
            System.out.println(method);

        }

    }
}
  • 获取单个方法
getMethod
getDeclaredMethod

实例
public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        // 获取Class文件对象
        Class c2 = Class.forName("com.the151suggestions.reflect.Person");
        Constructor constructor = c2.getConstructor();
         Object object = c2.newInstance();
        /**
         * Person p = new Person();
         * p.show();
         */
        // 获取单个  public Method getMethod(String name,Class<?> args);
        Method method = c2.getMethod("show");
        // 调用方法 public Object invoke(Object object,Object...args );
        method.invoke(object); // 调用object对的show方法

    }
}

方法多个参数
public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        // 获取Class文件对象
        Class c2 = Class.forName("com.the151suggestions.reflect.Person");
        Constructor constructor = c2.getConstructor();
         Object object = c2.newInstance();
        /**
         * Person p = new Person();
         * p.show();
         */
        // 获取单个  public Method getMethod(String name,Class<?> args);
        Method method = c2.getMethod("show");
        // 调用方法 public Object invoke(Object object,Object...args );
        method.invoke(object);

        Method method1 = c2.getMethod("method", String.class);
        method1.invoke(object,"tom");

        Method method2 = c2.getMethod("getString",String.class,int.class);

        String s  = (String) method2.invoke(object,"jack",12);
        System.out.println(s);


    }
}
  • 暴力访问
method.setAccessible(true);

案例

public class Test {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        // 加载数据
        Properties properties = new Properties();
        FileReader reader = new FileReader("1.txt");
        properties.load(reader);
        reader.close();

        // 获取数据
        String className = properties.getProperty("className");
        String methodName = properties.getProperty("methodName");

        // 反射
        Class c  = Class.forName(className);
        // 无参构造
        Constructor constructor = c.getConstructor();
        // 创建对象
        Object object = c.newInstance();

        // 调用方法
        Method method = c.getMethod(methodName);
        method.invoke(object);
    }
}
案例操作集合
/**
 * Created by wanggs on 2017/7/23.
 */
public class ArrayListDemo {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        /**
         * ArrayList<Integer> 中添加字符串
         */
        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        arrayList.add(12);
        Class c = arrayList.getClass();

        Method method = c.getMethod("add", Object.class);
        method.invoke(arrayList, "tom");
        System.out.println(arrayList);
        
    }
}
案例
package com.the151suggestions.reflect01;

import java.lang.reflect.Field;

/**
 * Created by wanggs on 2017/7/23.
 * public void setProperty(Object obj, String propertyName, Object value){}
 * 此方法可将obj对象中名为propertyName的属性的值
 */
public class Tool {
    public void setProperty(Object object, String propertyName, Object value) throws NoSuchFieldException, IllegalAccessException {
        Class c = object.getClass();

        // 获取成员变量
        Field field = c.getDeclaredField(propertyName);
        // 防止私有方法暴力访问
        field.setAccessible(true);

        field.set(object,value);

    }

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Dog dog = new Dog();
        Tool tool = new Tool();
        tool.setProperty(dog,"name","花花");
        System.out.println(dog);
    }

}
class Dog{
    String name;

    public Dog() {
    }

    public Dog(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

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

动态代理

package com.the151suggestions.reflect01;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * Created by wanggs on 2017/7/23.
 */
public class MyinvocationHandler implements InvocationHandler {
    private Object target; // 目标对象

    public MyinvocationHandler(Object target) {
        this.target = target;

    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Object proxy: 被代理对象  Method method: 要调用的方法 Object[] args: 方法调用说填入的参数
        System.out.println("权限认证");
        Object o = method.invoke(target, args); // 调用方法传入真实主题和参数
        System.out.println("日志记录");
        return o; // 代理对象
    }
}


package com.the151suggestions.reflect01;

import java.lang.reflect.Proxy;

/**
 * Created by wanggs on 2017/7/23.
 */
public class UserDaoTest {
    public static void main(String[] args) {
        StudentDao studentDao = new StudentDaoImpl();
        MyinvocationHandler myinvocationHandler = new MyinvocationHandler(studentDao);
       StudentDao studentDao1 = (StudentDao) Proxy.newProxyInstance(studentDao.getClass().getClassLoader(),studentDao.getClass().getInterfaces(),myinvocationHandler);
       studentDao1.login();
    }
}


package com.the151suggestions.reflect01;

/**
 * Created by wanggs on 2017/7/23.
 */
public interface UserDao {
    public abstract void add();
    public abstract void edit();
    public abstract void delete();
}


package com.the151suggestions.reflect01;

/**
 * Created by wanggs on 2017/7/23.
 */
public class UserDaoImpl implements UserDao {
    @Override
    public void add() {
        System.out.println("权限校验");
        System.out.println("UserDaoImpl.add");
        System.out.println("日志记录");
    }

    @Override
    public void edit() {
        System.out.println("UserDaoImpl.edit");
    }

    @Override
    public void delete() {
        System.out.println("UserDaoImpl.delete");
    }
}

1.接口定义一个人类的统称

/**
 * Created by wanggs on 2017/7/14.
 */
public interface Human {
    public abstract void laugh();
    public abstract void cry();
    public abstract void talk();
}

2.然后定义具体的人种:

package com.wanggs.factory;

/**
 * Created by wanggs on 2017/7/14.
 */
public class WhiteHuman implements Human {
    @Override
    public void laugh() {
        System.out.println("WhiteHuman.laugh");
    }

    @Override
    public void cry() {
        System.out.println("WhiteHuman.cry");
    }

    @Override
    public void talk() {
        System.out.println("WhiteHuman.talk");
    }
}

package com.wanggs.factory;

/**
 * Created by wanggs on 2017/7/14.
 */
public class YellowHuman implements Human  {
    @Override
    public void laugh() {
        System.out.println("YellowHuman.laugh");
    }

    @Override
    public void cry() {
        System.out.println("YellowHuman.cry");
    }

    @Override
    public void talk() {
        System.out.println("YellowHuman.talk");
    }
}

3.人的工厂

package com.wanggs.factory;

/**
 * Created by wanggs on 2017/7/14.
 */
public class HumanFactory {

    // 第一版
   /* public static Human produceHuman(String type) {
        if ("yellow".equals(type)) {
            return new YellowHuman();

        } else if ("white".equals(type)) {
            return new WhiteHuman();

        } else if ("black".equals(type)) {
            return new BlackHuman();

        }
        System.out.println("有误");
        return null;

    }*/
    //第二版
   /* public static Human produceYellow() {
        return new YellowHuman();
    }

    public static Human produceBlack() {
        return new BlackHuman();
    }*/
    //第三版 使用反射
    public static Human createHuman(Class c) {
        Human human = null;
        try {
            human = (Human) Class.forName(c.getName()).newInstance();
        } catch (InstantiationException e) {
            System.out.println("颜色");
        } catch (IllegalAccessException e) {
            System.out.println("人定义错误");
        } catch (ClassNotFoundException e) {
            System.out.println("null");
        }
        return human;
    }


}

4. 测试

package com.wanggs.factory;

/**
 * Created by wanggs on 2017/7/14.
 */
public class NvWa {
    public static void main(String[] args) {

    Human human = HumanFactory.createHuman(YellowHuman.class);
    human.laugh();
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容