java 反射详解

本文介绍了Java反射的定义,即在程序运行时可动态获取对象属性和方法信息,还能执行指定方法或修改属性。同时阐述了Java反射的实现,包括获取Class对象、类的全限定名等信息,以及获取类的接口、属性、方法和构造方法等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

反射定义
反射实现
通过反射获取对应类的Class对象
根据对应类的Class对象得到全限定名、类名、包名
获取类的所有实现接口
获取类的属性(Filed 类)
通过Class对象构造对应的实例对象(不通过new)
修改或获取指定对象的属性
获取类的方法 (Method 类)
构造方法相关操作

反射定义

反射式在java程序运行时,我还能动态的得到某个对象的所有属性和方法信息。并且可以动态执行某个对象的指定方法,或修改指定属性。这就是反射。

java反射实现

首先定义我们的操作类,Person

public class Person  implements Serializable{
    /**
     * 序列化  序列化编号
     */
    private static final long serialVersionUID = -5293639382415756109L;
    public int pid;
    private String pname;
    
    public Person() {
        
    }
    public Person(String name) {
        this.pname = name;
    }
    
    public Person(int pid, String pname) {
        this.pid = pid;
        this.pname = pname;
    }
    public String getPname() {
        return pname;
    }
    
    //getPid是一个私有的方法
    public int getPid() {
        return pid;
    }
    
    public void setPid(int pid) {
        this.pid = pid;
    }
    
    public void setPname(String pname) {
        this.pname = pname;
    }
    
    //add是一个私有的方法
    private String add(Integer i, Integer j) {
        return i + j + "";
    }
}

通过反射获取对应类的Class对象

class对象在类加载时会由虚拟机内部产生,并且一个类有且只有一个对应的class对象。还有 基础数据类型、数组、包括关键字 void (void.class)都有对应的class对象.下面我们看看如何获取class对象

        //(1)类.class
         Class c = Person.class;
         
        // (2)对象名.getClass()
         Person person = new Person();
         Class c2 = person.getClass();
    
        // (3)Class.forName("全限定名")
        // 全限定名 一定是包含包名的 包名.类名
         Class c3 = Class.forName("com.cpc.temp.Person");
    
        // (4)类.getClassLoader().loadClass("全限定名")
         Class c4 = Person.class.getClassLoader().loadClass("com.cpc.temp.Person");

        // (5)子类.class.getSuperClass()
        // 这是等到父类class对象  (这返回的是Object的Class对象)
        Class c5 = Person.class.getSuperclass();
        
        // (6)包装类.class
        Class c6 = Integer.class;

根据对应类的Class对象得到全限定名、类名、包名

         Class c1 = Class.forName("com.cpc.temp.Person");
         System.out.println("全限定名" + c1.getName());
         System.out.println("类名" + c1.getSimpleName());
         System.out.println("包名" + c1.getPackage());

执行结果

全限定名com.cpc.temp.Person
类名Person
报名package com.cpc.temp

获取类的所有实现接口

         Class c1 =  Person.class;
         //这是所有接口对应的Class对象数组
         Class[] classin = c1.getInterfaces();
         //遍历
         for(int i = 0; i < classin.length; i ++) {
             System.out.println(classin[i].getName());
         }

执行结果

java.io.Serializable

获取类的属性(Filed 类)

获取Class对象的属性返回的就是Filed类实例

        // 4获取类的属性(Filed 类)
        Class c1 = Person.class;
        // getField("属性名") 获取公有属性
        System.out.println("---------获取公有属性--------");
        Field pid = c1.getField("pid");
        // getName() 获取属性名
        System.out.println("pid的属性名" + pid.getName());
        // getModifiers() 获取访问修改符
        System.out.println("pid的访问修饰符" + pid.getModifiers());
        // 上面的getModifiers输出结果是数字,对应的修饰符就是下面几个常量值
        System.out.println("----属性访问修饰符------");
        System.out.println("public:" + Modifier.PUBLIC);
        System.out.println("private:" + Modifier.PRIVATE);
        System.out.println("protected:" + Modifier.PROTECTED);
        
        // getType() 获取属性的类型对应的Class对象
        System.out.println("----获取属性的类型对应的Class对象------");
        Class cla = pid.getType();
        System.out.println(cla.getName());
        
        // getDeclaredField("属性名") 获取私有属性值
        Field pname = c1.getDeclaredField("pname");
        System.out.println("-----获取私有属性----");
        //输出属性名
        System.out.println(pname.getName());
        //输出属性的访问修饰符
        System.out.println(pname.getModifiers());
        //setAccessible(true) 设置私有属性可访问
        pname.setAccessible(true);
        pname.set(person, "zs");
        System.out.println(person.getPname());
        
        // getDeclaredFields() 获取所有的属性(公有私有都能获取到)
        Field[] fileds = c1.getDeclaredFields();
        System.out.println("------遍历所有属性,并输出属性名-----");
        for (Field field : fileds) {
            System.out.println(field.getName());
        }

执行结果

---------获取公有属性--------
pid的属性名pid
pid的访问修饰符1
----属性访问修饰符------
public:1
private:2
protected:4
----获取属性的类型对应的Class对象------
int
-----获取私有属性----
pname
2
zs
------遍历所有属性,并输出属性名-----
serialVersionUID
pid
pname

通过Class对象构造对应的实例对象(不通过new)

        Class c1 = Person.class;
        Person p = (Person)c1.newInstance();

修改或获取指定对象的属性

        Class c1 = Person.class;
        Field pid = c1.getField("pid");
        Person p = (Person) c1.newInstance();
        // 修改person的
        pid.set(person, 1);
        //// get(对象名)=对象名.get属性名 获取属性值
        System.out.println(pid.get(person));

执行结果

1

获取类的方法 (Method 类)

        Class c1 = Person.class;
        Object object = c1.newInstance();
        // getMethod(方法名,参数数据类型(无参数传Null)) 获取公共方法
        Method setPid = c1.getMethod("setPid", int.class);
        // invok (对象名, 参数列表)=对象名.方法名 执行方法
        setPid.invoke(object, 1);
        Method getPid = c1.getMethod("getPid", null);
        System.out.println("执行公共getPid返回结果:" + getPid.invoke(object, null));

        // getDeclaredMethod(方法名,参数数据类型(无参数传null)) 获取私有方法
        Method add = c1.getDeclaredMethod("add", Integer.class, Integer.class);
        add.setAccessible(true);
        System.out.println("执行私有add返回结果:" + add.invoke(object, 1, 2));
        // getReturnType() 得到返回值方法的数据类型的Class对象
        Class re = add.getReturnType();
        System.out.println("add方法的返回类型"+re.getName());

        // getParameterTypes() 得到方法参数列表()
        Class[] cal = add.getParameterTypes();
        System.out.println("----遍历add的参数列表------开始");
        for (Class cc : cal) {
            System.out.println(cc.getName());
        }
        System.out.println("----遍历add的参数列表------结束");
        // getDeclaredMethods() 得到类的所有方法
        Method[] methods = c1.getDeclaredMethods();
        System.out.println("-----遍历所有方法----开始");
        for (Method method : methods) {
            System.out.println(method.getName());
        }
        System.out.println("-----遍历所有方法-----结束");

执行结果

执行公共getPid返回结果:1
执行私有add方法:3
add方法的返回类型java.lang.String
----遍历add的参数列表------开始
java.lang.Integer
java.lang.Integer
----遍历add的参数列表------结束
-----遍历所有方法----开始
add
setPid
getPname
getPid
setPname
-----遍历所有方法-----结束

构造方法相关操作

        Class c1 = Person.class;
        // getConstructor 得到构造方法
        Constructor con = c1.getConstructor(int.class, String.class);
        // 通过指定构造方法构造对象
        Person p1 = (Person) con.newInstance(1, "张三");
        System.out.println("获取通过指定构造方法构造出来的p1对象的属性");
        System.out.println(p1.getPid());
        System.out.println(p1.getPname());
        // gitConstructors 获取所有构造方法 并输出构造方法的参数个数
        Constructor[] constructors = c1.getConstructors();
        System.out.println("------遍历构造方法-----");
        for (Constructor constructor : constructors) {
            System.out.println(constructor.getParameterCount());
        }

执行结果

获取通过指定构造方法构造出来的p1对象的属性
1
张三
------遍历构造方法-----
2
1
0

其余的操作和方法操作差不多,这里就不过的赘述了.

如果有不对的地方欢迎在留言区批评指正。如果觉得对请点个赞那是对我最大的支持~~

转载于:https://www.cnblogs.com/IT-CPC/p/10957243.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值