java反射相关知识初学

文章介绍了Java反射的基本概念,包括通过Class获取类信息的三种方式,反射获取构造方法、成员变量和方法的详细步骤,以及如何使用反射调用构造函数、设置/获取成员变量和执行方法。示例代码展示了反射在实际操作中的应用。
摘要由CSDN通过智能技术生成

概述

java的反射大体意思就是根据类或对象,反推其拥有什么成员变量、成员方法。这些内容比较适合软件或组件的开发者用于分析源代码中的内容,用于开发扩展的工具。

主要内容

1.获取类(类名)的三种方式

2.反射获取类的构造方法(以及使用)

可以使用getConstructor(入参类型...)获取Constructor构造器,同时也可以使用newInstance(具体参数)调用构造方法生成对象。

3.反射获取类的成员变量(以及修改)

可以使用Field类的对象 f 调用get和set方法去控制对应变量,如f.get(obj)和f.set(obj,value)。

4.反射获取类的方法(以及使用)

可以使用Class类的getMethod("方法名",参数类型...)获取Method对象,同时也可以使用invoke("具体对象",具体参数...)调用该方法。

示例代码

public class Student{
    public String name;
    public int age;

    public Student(){

    }
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String toString(){
        return "name:"+name+" age:"+age;
    }

    public static int add(int a,int b){
        return a+b;
    }
}
import java.lang.reflect.*;

public class reflectTest {
    public static void main(String[] args) throws Exception {
        getInfoOfClass();               //三种方式反射出目标的类具体是什么类
        getInfoOfConstructor();         //通过具体的类名称,反射获取构造方法,并构造对象
        getAndSetField(new Student());  //通过具体的对象,反射获取其成员变量及其值,并修改
        getMethodAndUse(new Student()); //通过具体的对象,反射获取其所有方法,并使用相关参数执行
    }

    public static void getMethodAndUse(Object obj) throws Exception{
        Method[] methods = obj.getClass().getDeclaredMethods();
        System.out.println("所有方法如下:");
        for(Method method:methods){
            System.out.println("Name:"+method.getName());
            //此处必须使用getSimpleName()方法,否则返回的字符串将会带有Class前缀
            //因为getReturnType()方法返回的是Class<?>类型的对象
            System.out.println("ReturnType:"+method.getReturnType().getSimpleName());
            //由唯一确定的"方法"可以获取变量集合
            Class<?>[] parameters = method.getParameterTypes();
            System.out.print("parameters:");
            for(Class<?> parameter:parameters){
                System.out.print(parameter.getSimpleName()+",");
            }System.out.println();
            //以下是通过具体的方法名确定方法并使用invoke()方法调用
            if(method.getName().equals("add")){
                int temp = (int) method.invoke(obj,2,3);
                System.out.println("result:"+temp);
            }else if(method.getName().equals("toString")){
                String temp = (String) method.invoke(obj);
                System.out.println("result:"+temp);
            }System.out.println();
        }
    }

    private static void getAndSetField(Object obj) throws Exception{
        Class<?> clazz = obj.getClass();
        Field[] fields = clazz.getFields();
        System.out.println("以下是具体对象obj中所有变量的类型、名称和值:");
        for(Field field:fields){
            //此处必须使用getSimpleName()方法,否则返回的字符串将会带有Class前缀
            //因为getType()方法返回的是Class<?>类型的对象
            String type = field.getType().getSimpleName();
            String name = field.getName();
            Object value = field.get(obj);
            System.out.printf("type:%-8s name:%-8s value:%-8s\n",type,name,value);
            //以下是通过捕获变量类型的方法来set对应成员变量的值
            if(type.equals("String")) {
                field.set(obj,"小红");
            }else if (type.equals("int")){
                field.set(obj,17);
            }
        }
        System.out.println(obj);
    }

    private static void getInfoOfConstructor() throws Exception {
        Class<?> clazz = Class.forName("Student");
        Constructor<?>[] constructors = clazz.getConstructors();
        System.out.println("以下是Student类所有的构造方法:");
        for(Constructor<?> constructor:constructors){
            System.out.println(constructor);
        }
        System.out.println("以下是通过反射而构造的两个实例:");
        //反射获取Student类的空构造方法,并使用newInstance方法创建实例
        Constructor<?> constructor1 = clazz.getConstructor();
        Object obj1 = constructor1.newInstance();
        Student stu1 = (Student) obj1;
        System.out.println(stu1);
        //反射获取Student类有参构造方法,并使用参数实例化
        Constructor<?> constructor2 = clazz.getConstructor(String.class,int.class);
        Object obj2 = constructor2.newInstance("小明",18);
        Student stu2 = (Student) obj2;
        System.out.println(stu2);
        System.out.print("\n");
    }

    private static void getInfoOfClass() throws Exception{
        //以下是三种获取Class<?>类的方法
        //1.使用Class类的普通方法getClass获取:e.getClass()
        Student student = new Student();
        Class<? extends Student> clazz = student.getClass();
        System.out.println(clazz);
        //2.使用类的隐含静态变量class获取:E.class
        Class<Student> clazz1 = Student.class;
        System.out.println(clazz1);
        //3.使用Class类的静态方法forName():Class.forName(String s)
        Class<?> clazz2 = Class.forName("Student");
        System.out.println(clazz2);
        System.out.print("\n");
    }
}

以下是代码输出结果: 

"C:\Program Files\Eclipse Adoptium\jdk-8.0.362.9-hotspot\bin\java.exe" ...
class Student
class Student
class Student

以下是Student类所有的构造方法:
public Student()
public Student(java.lang.String,int)
以下是通过反射而构造的两个实例:
name:null age:0
name:小明 age:18

以下是具体对象obj中所有变量的类型、名称和值:
type:String   name:name     value:null    
type:int      name:age      value:0       
name:小红 age:17
所有方法如下:
Name:add
ReturnType:int
parameters:int,int,
result:5

Name:toString
ReturnType:String
parameters:
result:name:null age:0


进程已结束,退出代码0

 

经验总结

1.反射的核心是获取类,也就是Class<?>类的对象,任何类都是Class<?>类的对象,获取到了目标Class<?>类的对象(变量)后,再用它去获取构造方法、方法、成员变量等。

2.所有的Class<?>类对象使用getName()方法返回的都是前缀带有地址位置的名称,比如java.lang.String,若想要纯粹的名称,如String,请使用getSimpleName()方法,最典型的就是各种“get……Type()”这类方法,这种带Type字眼的通常返回值类型都是Class<?>。

3.在获取类的方法和成员变量时,有一种多了一个Declared的方法,例如getFields()和getDeclaredFields()这两种方法,前者是获取这个类包含其父类的所有非私有成员,后者是获取这个类仅它自己本身的所有成员(包含私有的),因此在获取一个类的所有方法时,如若使用不加Declared的方法就会导致将父类的很多其他方法也访问出来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值