Java反射

本文详细介绍了Java反射机制,包括其定义、作用及使用方法。通过反射,可以在运行时动态地创建对象、访问属性和调用方法。示例代码展示了如何获取Class对象、构造器、方法以及属性,并进行了实例化、方法调用和属性访问的演示。
摘要由CSDN通过智能技术生成

目录

什么是反射?

反射的作用

反射的使用


什么是反射?
反射java语言中的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法。

反射就是把java类中的各种成分映射成一个个的Java对象

反射的作用
通过反射可以使程序代码访问装载到JVM 中的类的内部信息

● 获取已装载类的成员变量信息

● 获取已装载类的方法

● 获取已装载类的构造方法信息

简单而言,就是在运行状态时, 能够去内存中通过权限类名找到对应的的Class对象,就能够调用类中的私有化的方法、属性。

反射的使用
首先我们准备一个测试类(Student)

package com.ljq.mymvc.reflect;
 
/**
 * 测试类
 * 
 * @author 一麟
 *
 */
public class Student {
    private String sid;
 
    private String sname;
 
    public Integer age;
 
    static {
        System.out.println("加载进jvm中!");
    }
 
    public Student() {
        super();
        System.out.println("调用无参构造方法创建了一个学生对象");
    }
 
    public Student(String sid) {
        super();
        this.sid = sid;
        System.out.println("调用带一个参数的构造方法创建了一个学生对象");
    }
 
    public Student(String sid, String sname) {
        super();
        this.sid = sid;
        this.sname = sname;
        System.out.println("调用带二个参数的构造方法创建了一个学生对象");
    }
 
    @SuppressWarnings("unused")
    private Student(Integer age) {
        System.out.println("调用Student类私有的构造方法创建一个学生对象");
        this.age = age;
    }
 
    public String getSid() {
        return sid;
    }
 
    public void setSid(String sid) {
        this.sid = sid;
    }
 
    public String getSname() {
        return sname;
    }
 
    public void setSname(String sname) {
        this.sname = sname;
    }
 
    public void hello() {
        System.out.println("你好!我是" + this.sname);
    }
 
    public void hello(String name) {
        System.out.println(name + "你好!我是" + this.sname);
    }
 
    @SuppressWarnings("unused")
    private Integer add(Integer a, Integer b) {
        return new Integer(a.intValue() + b.intValue());
    }
 
    @Override
    public String toString() {
        return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]";
    }
 
    public Integer getAge() {
        return age;
    }
 
    public void setAge(Integer age) {
        this.age = age;
    }
 
}


如何拿到Class对象?

要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.那么怎么获取呢?有如下三种方法:

1.Class.forName(完整的类名)

2.类名.class

3.对象.getClass()

代码如下:        

//1、Class.forName() 获取Class
        Class<Student> clazz =(Class<Student>)Class.forName("com.zking.reflect.Student");
        
        //2、类.class
        Class clazz02=Student.class;
        
        //3、对象.getClass
        Student stu = new Student();
        Class clazz03 = stu.getClass();
        
        System.out.println(clazz);
        System.out.println(clazz02);
        System.out.println(clazz03);

主要的方法:

1.getConstructor (获得构造器对象)

2.getDeclaredConstructor(获得私有化的构造器对象)

3.newInstance (反射实例化)

/**
         * 通过反射进行实例化对象
         */
 
        // 获得无参构造
        Constructor<Student> c1 = clazz01.getConstructor();
        Student stu02 = c1.newInstance();
        stu02.setSid("3");
        System.out.println("------------无参构造------------");
        System.out.println(stu02 + "2号学生");
 
        // 有参构造
        Constructor<Student> c2 = clazz01.getConstructor(String.class);
        Student stu03 = c2.newInstance("01");
        stu03.setSname("小明" + "3号学生");
        System.out.println("------------有参构造------------");
        System.out.println(stu03);
 
        // 多个参数的有参构造
        Constructor<Student> c3 = clazz01.getConstructor(String.class, String.class);
        Student stu04 = c3.newInstance("02", "小美");
        System.out.println("------------多参构造------------");
        System.out.println(stu04 + "4号学生");
 
        // 调用私有化构造方法
        Constructor<Student> c4 = clazz01.getDeclaredConstructor(Integer.class);
        c4.setAccessible(true);
        Student stu05 = c4.newInstance(18);
        stu05.setSname("牛逼");
        System.out.println("------------私有化构造------------");
        System.out.println(stu05 + "5号学生");


获得类的方法:

主要的方法:

1.getMethod (通过方法名称获取到方法对象,若有参数放名称后面)

2.getMethod (通过方法名称获取到私有化方法对象)

3.invoke  (类实例, "参数");

注:为什么参数放后面,通过查看源代码可以看到后面是一个可变参数 要么只写一个,要么写name后面。

 继续采用上面的Student类,可以看到有三个方法,有参、无参和私有化。那么接下来我们就对这三个方法进行反射动态方法调用 

/**
         * 获得方法
         */
        
        // 调用类方法
        Method m1 = clazz01.getMethod("hello");
        System.out.println("------------普通方法------------");
        m1.invoke(stu05);
 
        // 调用带参数的方法
        Method m2 = clazz01.getMethod("hello", String.class);
        System.out.println("------------有参方法------------");
        m2.invoke(stu05, "27");
 
        // 调用私有化有参方法
        Method m3 = clazz01.getDeclaredMethod("add", Integer.class, Integer.class);
        m3.setAccessible(true);
        System.out.println("------------私有化方法------------");
        System.out.println(m3.invoke(stu05, 27, 43));


 获得类的属性:

主要的方法:

1.getField (“属性名”)  获得公开的属性

2.getDeclaredField (“属性名”)  既可以获得公开的属性又可以获得私有属性

3.getDeclaredFields (“属性名”)  获得全部

/**
         * 通过反射机制获取对象属性
         */
 
        // 反射公共属性
        Field f1 = clazz01.getField("age");
        f1.set(stu05, 56);
        System.out.println("------------公共属性方法------------");
        System.out.println(stu05 + "属性1");
        System.out.println(f1.get(stu05));
 
        // 反射私有化属性
        Field f2 = clazz01.getDeclaredField("sname");
        f2.setAccessible(true);
        f2.set(stu05, "aa");
        System.out.println("------------私有属性方法------------");
        System.out.println(stu05);
        System.out.println(f2.get(stu05));

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值