栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

反射学习笔记

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

反射学习笔记

反射 1 反射的根基

在整个反射体系中,Java 的作者提供了一个类用来描述 Java 文件,这个类为 Class。

Class 类型的对象代表某一个类的字节码文件。

2 如何获取类的 Class 对象 2.1 类名.class
Class userClass1 = User.class;
2.2 Class.forName(“全路径类名”)
Class userClass2 = Class.forName("com.yonxao.study.jdk8api.reflect.User");
2.3 对象.getClass()
User user = new User();
Class userClass3 = user.getClass();

userClass1 == userClass2 == userClass3

3 反射的核心思想

所谓的反射是将一个类中的各个成员映射成相对应的 Java 类型。

成员:

包 --> Package构造器 --> Constructor属性 --> Filed方法 --> Method 4 通过反射创建对象

创建对象时一定会调用构造方法。因此步骤如下:

    需要通过反射先获取字节码(根基),然后通过字节码来获取指定的构造器,再通过构造器创建对象。
package com.yonxao.study.jdk8api.reflect.constructor;


import org.junit.jupiter.api.Test;

import java.lang.reflect.Constructor;


public class ConstructorTest {

    
    @Test
    public void test1() {
        Class userClass = User.class;
        Constructor[] constructors = userClass.getConstructors();

        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        // public com.yonxao.study.jdk8api.reflect.constructor.Man()
        // public com.yonxao.study.jdk8api.reflect.constructor.Man(java.lang.String,int,float,boolean)
    }

    
    @Test
    public void test2() {
        Class userClass = User.class;

        try {
            Constructor constructor = userClass.getConstructor();
            System.out.println(constructor);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        // public com.yonxao.study.jdk8api.reflect.constructor.Man()
    }

    
    @Test
    public void test3() {
        Class userClass = User.class;

        try {
            Constructor constructor = userClass.getConstructor(String.class, int.class, float.class, boolean.class);
            System.out.println(constructor);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        // public com.yonxao.study.jdk8api.reflect.constructor.Man(java.lang.String,int,float,boolean)
    }


    
    @SuppressWarnings({"java:S112"})
    @Test
    public void test4() throws Exception {
        Class userClass = User.class;
        // 使用构造器创建对象
        Constructor constructor = userClass.getConstructor(String.class, int.class, float.class, boolean.class);
        User user = constructor.newInstance("王五", 22, 1.80f, false);
        System.out.println(user);
        // 使用字节码创建对象, 只能使用无参构造器创建
        User u = userClass.newInstance();
        System.out.println(u);
    }
}


@SuppressWarnings("all")
class User {

    public String username = "张三";
    int age = 11;
    protected float height = 1.75F;
    private boolean sex = true;

    public User() {
    }

    public User(String username, int age, float height, boolean sex) {
        this.username = username;
        this.age = age;
        this.height = height;
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "User{" + "username='" + username + ''' + ", age=" + age + ", height=" + height + ", sex=" + sex + '}';
    }
}
5 反射创建对象效率问题
    
    @SuppressWarnings("all")
    @Test
    public void test5() throws Exception {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            Class userClass = User.class;
            // 使用构造器创建对象
            Constructor constructor = userClass.getConstructor(String.class, int.class, float.class, boolean.class);
            User user = (User) constructor.newInstance("王五", 22, 1.80f, false);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("通过反射创建对象, 时间: " + (endTime - startTime) + " ms");
        // 通过反射创建对象, 时间: 123 ms
    }

    
    @SuppressWarnings("all")
    @Test
    public void test6() {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            User user = new User("王五", 22, 1.80f, false);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("通过传统方式创建对象, 时间: " + (endTime - startTime) + " ms");
        // 通过传统方式创建对象, 时间: 3 ms
    }

次数越多差距越大,至少 10 倍起,所以对效率要求比较高的项目,都不会直接使用框架,比如说 mybatis 等,会直接使用 JDBC 来提升效率。

6 通过反射获取属性 6.1 通过反射获取属性
package com.yonxao.study.jdk8api.reflect.filed;

import org.junit.jupiter.api.Test;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;


public class FiledTest {

    
    @Test
    public void test1() {
        Class userClass = User.class;
        // 获取所有共有属性字段
        Field[] fields = userClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        /// public java.lang.String com.yonxao.study.jdk8api.reflect.filed.User.username

        System.out.println("---");

        // 获取所有声明的属性字段
        Field[] declaredFields = userClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        /// public java.lang.String com.yonxao.study.jdk8api.reflect.filed.User.username
        /// int com.yonxao.study.jdk8api.reflect.filed.User.age
        /// protected float com.yonxao.study.jdk8api.reflect.filed.User.height
        /// private boolean com.yonxao.study.jdk8api.reflect.filed.User.sex
    }

    
    @Test
    public void test2() throws NoSuchFieldException {
        Class userClass = User.class;
        Field field = userClass.getDeclaredField("username");

        Class fieldType = field.getType();
        System.out.println("属性的类型: " + fieldType);
        /// 属性的类型: class java.lang.String

        String fieldOfClassName = field.getDeclaringClass().getTypeName();
        System.out.println("属性所属的类全路径: " + fieldOfClassName);
        /// 属性所属的类全路径: com.yonxao.study.jdk8api.reflect.filed.User

        String fieldName = field.getName();
        System.out.println("属性的名称: " + fieldName);
        /// 属性的名称: username

        int modifiers = field.getModifiers();
        System.out.printf("属性的修饰符的值: %s, 修饰符: %s%n", modifiers, ((modifiers == 0) ? "" : (Modifier.toString(modifiers))));
        /// 属性的修饰符的值: 1, 修饰符: public

        System.out.println(field.toString());
    }

    
    @SuppressWarnings("all")
    @Test
    public void test3() {
        for (int i = 0; i <= 256; i++) {
            String name = Modifier.toString(i);
            if (!name.contains(" ")) {
                System.out.printf("数字: %3d,名称: %s%n", i, name);
            }
        }
        /// 数字:   0,名称: 默认的
        /// 数字:   1,名称: public
        /// 数字:   2,名称: private
        /// 数字:   4,名称: protected
        /// 数字:   8,名称: static
        /// 数字:  16,名称: final
        /// 数字:  32,名称: synchronized
        /// 数字:  64,名称: volatile
        /// 数字: 128,名称: transient
        /// 数字: 256,名称: native
    }

}


@SuppressWarnings("all")
class User {

    public String username = "张三";
    int age = 11;
    protected float height = 1.75F;
    private boolean sex = true;

    public User() {
    }

    public User(String username, int age, float height, boolean sex) {
        this.username = username;
        this.age = age;
        this.height = height;
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "User{" + "username='" + username + ''' + ", age=" + age + ", height=" + height + ", sex=" + sex + '}';
    }
}
6.2 通过(暴力)反射来获取属性的值
    
    @SuppressWarnings("all")
    @Test
    public void test4() throws Exception {
        Class userClass = User.class;
        Field[] declaredFields = userClass.getDeclaredFields();

        User user = userClass.newInstance();

        for (Field declaredField : declaredFields) {
            // 被 private 修饰的属性, 其值无法通过反射直接获取到, 需要通过暴力反射来获取值
            if (declaredField.getModifiers() == 2) {
                // 所谓的暴力反射
                declaredField.setAccessible(true);
            }
            Object o = declaredField.get(user);
            System.out.printf("字段名: %s, 字段值: %s%n", declaredField.getName(), o.toString());
        }
    }
7 通过反射执行类的方法
package com.yonxao.study.jdk8api.reflect.method;

import org.junit.jupiter.api.Test;

import java.lang.reflect.Method;


public class MethodTest {

    
    @Test
    public void test1() {
        Class birdClass = Bird.class;
        Method[] methods = birdClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        /// public void com.yonxao.study.jdk8api.reflect.method.Bird.fly()
        /// public void com.yonxao.study.jdk8api.reflect.method.Bird.fly(long)
        /// 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 final void java.lang.Object.wait() 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()
    }

    
    @Test
    public void test2() {
        Class birdClass = Bird.class;
        Method[] methods = birdClass.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        /// private void com.yonxao.study.jdk8api.reflect.method.Bird.fly(java.lang.String,long)
        /// public void com.yonxao.study.jdk8api.reflect.method.Bird.fly()
        /// public void com.yonxao.study.jdk8api.reflect.method.Bird.fly(long)
    }

    
    @SuppressWarnings("all")
    @Test
    public void test3() throws Exception {
        Class birdClass = Bird.class;
        Method fly = birdClass.getMethod("fly");
        Method fly2 = birdClass.getMethod("fly", long.class);
        Method fly3 = birdClass.getMethod("fly", String.class, long.class);
    }

    
    @SuppressWarnings("all")
    @Test
    public void test4() throws Exception {
        Class birdClass = Bird.class;

        Bird bird = birdClass.newInstance();

        Method fly = birdClass.getMethod("fly");
        Method fly2 = birdClass.getMethod("fly", long.class);
        Method fly3 = birdClass.getDeclaredMethod("fly", String.class, long.class);

        fly.invoke(bird);
        fly2.invoke(bird, 9);

        // 在其它类中是无法调用目标类的私有方法的, 但反射可以
        fly3.setAccessible(true);
        fly3.invoke(bird, "麻雀", 8);
    }


}


class Bird {

    public void fly() {
        System.out.println("鸟会飞");
    }

    public void fly(long l) {
        System.out.println("鸟会飞" + l + "分钟");
    }

    private void fly(String name, long l) {
        System.out.println(name + "会飞" + l + "分钟");
    }
}
8 反射练习

对象和 Map 互相转化

package com.yonxao.study.jdk8api.reflect.practice;

import org.junit.jupiter.api.Test;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;


public class ReflectTest {

    @SuppressWarnings("all")
    @Test
    public void test1() throws Exception {
        User user = new User();
        Map map = bean2map(user);
        System.out.println(map);
    }

    @Test
    public void test2() throws Exception {
        Map map = new HashMap<>(8);
        map.put("username", "老王");
        map.put("age", 44);
        map.put("height", 1.88F);
        map.put("sex", false);
        User user = map2bean(map, User.class);
        System.out.println(user);
    }

    
    @SuppressWarnings("java:S3011")
    public static Map bean2map(Object obj) throws IllegalAccessException {
        Map map = new HashMap<>(8);
        Class objClass = obj.getClass();
        Field[] fields = objClass.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            map.put(field.getName(), field.get(obj));
        }

        return map;
    }

    
    @SuppressWarnings("all")
    public static  T map2bean(Map map, Class c) throws Exception {
        Field[] declaredFields = c.getDeclaredFields();
        T t = c.newInstance();
        for (Field field : declaredFields) {
            field.setAccessible(true);
            field.set(t, map.get(field.getName()));
        }

        return t;
    }
}


@SuppressWarnings("all")
class User {
    public String username = "张三";
    Integer age = 11;
    protected Float height = 1.75F;
    private Boolean sex = true;

    @Override
    public String toString() {
        return "User{" + "username='" + username + ''' + ", age=" + age + ", height=" + height + ", sex=" + sex + '}';
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/760073.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号