美文网首页Java工程师知识树
Java基础-反射-反射的使用

Java基础-反射-反射的使用

作者: HughJin | 来源:发表于2021-01-22 10:00 被阅读0次

Java工程师知识树 / Java基础


反射的使用

通过反射查看类信息

  • 类的构造方法:Class类提供了用于获取某个类的构造方法。
Constructor getConstructor(Class<?>... parameterTypes)     根据构造函数的参数,返回一个具体的具有public属性的构造函数
Constructor getConstructors()     返回所有具有public属性的构造函数数组
Constructor getDeclaredConstructor(Class<?>... parameterTypes)     根据构造函数的参数,返回一个具体的构造函数(不分public和非public属性)
Constructor getDeclaredConstructors()    返回该类中所有的构造函数数组(不分public和非public属性)
  • 类的属性:Class类提供了获取成员属性的方法
Field getField(String name)    根据变量名,返回一个具体的具有public属性的成员变量
Field[] getFields()    返回具有public属性的成员变量的数组
Field getDeclaredField(String name)    根据变量名,返回一个成员变量(不分public和非public属性)
Field[] getDelcaredFields()    返回所有成员变量组成的数组(不分public和非public属性)
  • 类的方法:Class类提供了获取成员方法的方法
Method getMethod(String name, Class<?>... parameterTypes)    根据方法名和参数,返回一个具体的具有public属性的方法
Method[] getMethods()    返回所有具有public属性的方法数组
Method getDeclaredMethod(String name, Class<?>... parameterTypes)   根据方法名和参数,返回一个具体的方法(不分public和非public属性)
Method[] getDeclaredMethods()    返回该类中的所有的方法数组(不分public和非public属性)

通过反射生成并操作对象代码实例:

package com.wechat.management.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class TestRefFieldAndMethod {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("com.wechat.management.reflection.UserDTO");
        //1、获得类的名字--->获得包名+类名
        System.out.println(c1.getName());//com.wechat.management.reflection.UserDTO
        //2、获得类的简单名字-->获得类名
        System.out.println(c1.getSimpleName());//User

        System.out.println("=======================");
        //3、获得类的属性
        //3.1 获得public的属性
        Field[] fields = c1.getFields();//只能找到public的属性

        //3.2  能够找到所有的属性
        Field[] fields1 = c1.getDeclaredFields();
        for (Field field: fields1) {
            System.out.println(field);
        }

        /**
         * private int com.wechat.management.reflection.UserDTO.id
         * private java.lang.String com.wechat.management.reflection.UserDTO.name
         * private int com.wechat.management.reflection.UserDTO.age
         */
        //3.3、获得指定的属性
        Field name = c1.getDeclaredField("name");
        System.out.println(name);//private java.lang.String com.wechat.management.reflection.UserDTO.name

        //4、获得类的方法
        System.out.println("====================================");
        Method[] methods = c1.getMethods();//获得本类及其父类的全部public方法
        for (Method method : methods) {
            System.out.println("c1.getMethods():"+method);
        }
        Method[] methods1 = c1.getDeclaredMethods();//获得本类的全部方法
        for (Method method : methods1) {
            System.out.println("c1.getDeclaredMethods():"+method);
        }
        //获取指定的方法   重载,所以要添加参数
        Method getName = c1.getMethod("getName", null);
        System.out.println(getName);//public java.lang.String com.wechat.management.reflection.UserDTO.getName()
        Method setName = c1.getMethod("setName", String.class);
        System.out.println(setName);//public void com.wechat.management.reflection.UserDTO.setName(java.lang.String)

        //5、获取指定的构造器
        System.out.println("=================================");
        Constructor[] constructors = c1.getConstructors();//获取public
        for (Constructor constructor : constructors) {
            System.out.println("c1.getConstructors():"+constructor);
        }
        Constructor[] constructors1 = c1.getDeclaredConstructors();//获取所有的构造器
        for (Constructor constructor : constructors1) {
            System.out.println("c1.getDeclaredConstructors():"+constructor);
        }

        //获取指定的构造器
        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        System.out.println("获取指定的构造器"+declaredConstructor);//获取指定的构造器public com.wechat.management.reflection.UserDTO(int,java.lang.String,int)
    }
}


class UserDTO {

    private int id;
    private String name;
    private int age;

    public UserDTO() {
    }

    public UserDTO(String name, int id, int age) {
        super();
        this.name = name;
        this.id = id;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "User [name=" + name + ", id=" + id + ", age=" + age + "]";
    }
}

通过反射调用对象方法

public class TestInvoke {

    public String invokeMethod() {
        System.out.println("invokeMethod已执行!");
        return "invokeMethod已执行!";
    }
    
    public static void main(String[] args) throws Exception {  
        //1.通过反射获取Class对象
        Class stuClass = Class.forName("com.wechat.management.reflection.TestInvoke");//"com.wechat.management.reflection.TestInvoke"
        //2.获取invokeMethod()方法
        Method method = stuClass.getMethod("invokeMethod");
        //3.创建对象
        TestInvoke testInvoke = (TestInvoke) stuClass.newInstance();
        //4.调用invokeMethod()方法
        String retrunStr = (String) method.invoke(testInvoke, null);
        System.out.println("获取方法执行后的返回值:"+retrunStr);
    }
}

通过反射执行类方法的步骤:

  1. 通过反射获取Class对象
  2. 通过getMethod()指定方法名获取方法
  3. 通过反射获取的Class类创建实例对象
  4. 通过invoke()执行指定方法

反射与泛型

Java采用泛型擦除的机制来引入泛型,Java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换的问题,但是,一旦编译完成,所有和泛型有关的类型全部擦除。

通过反射越过泛型检查:

import java.lang.reflect.Method;
import java.util.ArrayList;

public class InvokeDemo {

    public static void main(String[] args) throws Exception {
        ArrayList<Integer> strList = new ArrayList<>();
        strList.add(100);
        strList.add(200);
        
        //获取ArrayList的Class对象,反向的调用add()方法,添加数据
        Class listClass = strList.getClass(); //得到 strList 对象的字节码 对象
        //获取add()方法
        Method method = listClass.getMethod("add", Object.class);
        //调用add()方法
        method.invoke(strList, "数字");

        //遍历集合
        for (Object obj : strList) {
            System.out.println(obj);
        }
    }
}

执行结果:

100
200
数字

为了通过反射操作泛型代表的类型,Java新增了ParameterizedTypeGenericArrayTypeTypeVariableWildcardType几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型。

类型 说明
ParameterizedType 表示一种参数化类型,比如Collection< String >
GenericArrayType 表示一种元素类型是参数化类型或者类型变量的数组类型
TypeVariable 是各种类型变量的公共父接口
WildcardType 代表一种通配符类型表达式
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
public class TestReflectGen {
    /**
     * 通过泛型传参
     * @param map
     * @param list
     */
    public void test01(Map<String,User> map, List<Integer> list){
        System.out.println("test01");

    }

    /**
     * 通过泛型返回值
     * @return
     */
    public Map<String,User> test02(){
        System.out.println("test02");
        return null;
    }

    public static void main(String[] args) throws NoSuchMethodException {
        //获得参数类型
        Method method = Test11.class.getMethod("test01", Map.class, List.class);
        //获取参数类型  即Map和 List
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            System.out.println("1:"+genericParameterType);

            //判断genericParameterType参数类型 是否属于 ParameterizedType 参数化类型
            if (genericParameterType instanceof ParameterizedType){
                //如果属于参数化类型,获得他的真实类型 getActualTypeArguments
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();

                //再次输出真实的泛型信息
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println("2:"+actualTypeArgument);
                }
            }
        }
        
        
        //获得返回值类型
        method = Test11.class.getMethod("test02",null);
        Type genericReturnType = method.getGenericReturnType();
        if (genericReturnType instanceof ParameterizedType){
            //如果genericReturnType返回值类型属于参数化类型,获得他的真实类型 getActualTypeArguments
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            
            //再次输出真实的泛型信息
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println("3:"+actualTypeArgument);
            }
        }
    }
}

反射与注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;

public class TestReflectAnnotation {
    public static void main(String[] args) throws Exception {
        TestAccountAnnotation testAccountAnnotation = new TestAccountAnnotation();
        Class<?> class1 = TestAccountAnnotation.class;
        Method method = class1.getMethod("show", String.class, int.class, String.class);
        Account annotation = method.getAnnotation(Account.class);
        String name = annotation.name();
        int age = annotation.age();
        String gender = annotation.gender();
        method.invoke(testAccountAnnotation, name, age, gender);
    }
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Account {
    String name();

    int age() default 18;

    String gender();
}

class TestAccountAnnotation {

    @Account(name = "法外狂徒", gender = "男")
    public void show(String name, int age, String gen) {
        System.out.println(name);
        System.out.println(age);
        System.out.println(gen);
    }

}

执行结果:

法外狂徒
18
男

相关文章

  • Java基础之反射

    Java基础之反射 反射基本介绍 反射的使用通过反射调用属性和方法通过反射获取配置文件 反射基本介绍 Java反射...

  • Java基础之反射

    Java基础之—反射(非常重要)Java中反射机制详解Java进阶之reflection(反射机制)——反射概念与...

  • Java基础:反射

    反射注解动态代理相关阅读 Java基础:类加载器 Java基础:反射 Java基础:注解 Java基础:动态代理 ...

  • Java基础-反射-反射的使用

    Java工程师知识树[https://www.jianshu.com/p/db77d19a25f6] / Ja...

  • Java笔记之——反射

    这篇文章来谈谈Java基础——反射的内容。主要通过以下几点进行介绍:反射机制、反射的使用及有关反射的API。 一、...

  • Java反射与joor反射库的使用

    java原生反射的使用 反射构造对象 反射方法 反射字段 joor反射库的使用 github:https://gi...

  • Java高级知识

    反射 sczyh30 深入解析Java反射(1) - 基础深入解析Java反射(2) - invoke方法深入探究...

  • java 反射进阶

    1.java反射基础 2.java反射进阶 上一节介绍了反射基础,本节介绍更深入的反射概念。 1.获取不到Clas...

  • java 反射基础

    1.java反射基础 2.java反射进阶 反射的两个显著的作用 反编译: .class —> .java 通过...

  • Java互联网公司-经典面试题附答案

    基础:Java 反射?反射有什么缺点?你是怎么理解反射的(为什么框架需要反射)?优点:反射具有解耦性,缺点:反射属...

网友评论

    本文标题:Java基础-反射-反射的使用

    本文链接:https://www.haomeiwen.com/subject/mwbnaktx.html