Java语言的反射机制

本文介绍了Java反射机制,包括如何在运行时获取Class对象,以及通过Class对象获取构造器、成员变量和方法。通过反射,可以在运行时动态获取类的信息并进行操作,如创建对象、访问私有成员,甚至绕过泛型约束。同时,文章也指出反射可能导致封装性的破坏,并强调其在高级框架开发中的重要用途。
摘要由CSDN通过智能技术生成

概述

  • 反射是指对于任何一个Class类,在"运行的时候"都可以直接得到这个类全部成分。
  • 在运行时,可以直接得到这个类的构造器对象:Constructor
  • 在运行时,可以直接得到这个类的成员变量:Field
  • 在运行时,可以直接得到这个类的成员方法对象:Methon
  • 这种运行时动态获取类信息的以及动态调用类中成分的能力称为Java语言的反射机制

反射的基本作用和关键

  • 作用: 反射是在运行时获取类的字节码文件对象:然后可以解析类中的全部成分
  • 关键: 反射的第一步都是先得到编译后的Class类对象,然后就可以得到Class的全部成分

反射第一步:获取Class类的对象(三种)

  • 1.通过 Class类中的一个静态方法:forName(全限名:报名 + 类名)
  • 2.通过 类名.class
  • 3.通过 对象.getClass(); 获取对象对应类的Class对象
/**
 - 目标:反射第一步,获取Class对象
 */
public class Test {
    public static void main(String[] args) throws Exception {
        /**
         * 获取Class对象的第一种方法 forName(全限名:报名 + 类名)
         */
        //1.Class类中的一个静态方法:forName(全限名:报名 + 类名)
        Class c = Class.forName("com.Reflect.Study.Student");
        System.out.println(c);//c:Student.class 文件

        /**
         * 获取Class对象的第二种方法 类名.class
         */
        //2.类名.class
        Class c1 = Student.class;
        System.out.println(c1);

        /**
         * 获取Class对象的第三种方法 对象.getClass() 获取对象对应类的Class对象
         */
        //2.对象.getClass() 获取对象对应类的Class对象
        Student s = new Student();
        Class c2 = s.getClass();
        System.out.println(c2);
    }
}

使用反射技术获取构造器对象并使用

想要获取构造器首先要获取类对象

四种方法获取不同的的构造器

  • 1.getConstructors(); 拿公共的权限的构造器(由public修饰)
  • 2.getDeclaredConstructors(); 获取全部构造器的方法 无所谓什么权限
  • 3.getConstructor(Class ... parameterTypes); 获取投个构造器 只能拿public修饰的构造器
  • 4.getDeclaredConstructor(); 通过参数定位有参构造器
import org.junit.Test;

import java.lang.reflect.Constructor;

public class TestStudent {

    /**
     * 1.getConstructors()  拿公共的全限的构造器
     */
    @Test
    public void getConstructors() {
        //1.获取类Class对象
        Student s = new Student();
        Class c = s.getClass();
        //2.提取类中全部的构造器对象  这里只能拿Public的构造器
        Constructor[] constructors = c.getConstructors();
        //3.遍历构造器数组
        for (Constructor constructor : constructors) {
            System.out.println(constructor.getName() + "==" + constructor.getParameterCount());
        }
    }

    /**
     * 2.getDeclaredConstructors() 获取全部构造器的方法 无所谓什么权限
     */
    @Test
    public void getDeclaredConstructors() {
        //1.获取类Class对象
        Student s = new Student();
        Class c = s.getClass();
        //2.提取类中全部的构造器对象  这里只能拿全部的构造器
        Constructor[] constructors = c.getDeclaredConstructors();
        //3.遍历构造器数组
        for (Constructor constructor : constructors) {
            System.out.println(constructor.getName() + "==" + constructor.getParameterCount());
        }
    }

    /**
     * 3.getConstructor(Class ... parameterTypes)  获取投个构造器 只能拿public修饰的构造器
     */
    @Test
    public void getConstructor() throws Exception {
        //1.获取类Class对象
        Student s = new Student();
        Class c = s.getClass();
        //2.提取类中全部的构造器对象  这里只能拿Public的构造器
        //定位单个构造器对象  定位无参数构造器
        Constructor cons = c.getConstructor();
        //3.
        System.out.println(cons.getName() + "==" + cons.getParameterCount());

    }

    /**
     * 4.getDeclaredConstructor()  通过参数定位有参构造器
     */
    @Test
    public void getDeclaredConstructor() throws Exception {
        //1.获取类Class对象
        Student s = new Student();
        Class c = s.getClass();
        //2.提取类中全部的构造器对象  这里只能拿Public的构造器
        //定位单个构造器对象  定位有参数构造器
        Constructor cons = c.getDeclaredConstructor(int.class,String.class);
        //3.
        System.out.println(cons.getName() + "==" + cons.getParameterCount());

    }
}

使用获取来的构造器(创建对象)

  • 获取构造器的作用依旧是初始化一个对象返回
    newInstance(); 构造器的创建对象的方法
    cons1.setAccessible(true) ; 暴力打开权限,如果遇到了私有的构造器,可以暴力反射
    注意:反射可以破坏封装性,私有的也可以执行了
import org.junit.Test;

import java.lang.reflect.Constructor;

public class TestStudentDemo2 {
    /**
     * 1.调用无参构造器得到一个类的对象返回
     * @throws Exception
     */
    @Test
    public void getDeclaredConstructor() throws Exception {
        //a.获取类Class对象
        Student s = new Student();
        Class c = s.getClass();
        //b.定位单个构造器对象(按照参数定位无参数构造器对象)
        Constructor cons1 = c.getDeclaredConstructor();
        System.out.println(cons1.getName() + "==" + cons1.getParameterCount());
        Student stu = (Student)cons1.newInstance();
        System.out.println(stu);
        //如果遇到了私有的构造器,可以暴力反射
        cons1.setAccessible(true);

        //c.定位单个构造器对象  (定位有参数构造器)
        Constructor cons2 = c.getDeclaredConstructor(int.class,String.class);
        System.out.println(cons2.getName() + "==" + cons2.getParameterCount());

    }
}

反射获取成员变量并使用

两种方法获取不同的成员方法

  • 1.获取全部的成员变量 Field[] getDeclaredFields(); 获得所有的成员变量对应的Field对象,只要申明了就可以得到
  • 2.根据名字获取某个成员变量 Filed getDeclaredField(String name);
import org.junit.Test;

import java.lang.reflect.Field;

public class TestStudent {
    /**
     * 1.获取全部的成员变量
     * Field[] getDeclaredFields();
     * 获得所有的成员变量对应的Field对象,只要申明了就可以得到
     */
    @Test
    public void getDeclaredFields(){
        //a.获取Class对象
        Class c = Student.class;
        //b.定位全部成员变量
        Field[] fields = c.getDeclaredFields();
        //c.遍历一下
        for (Field field : fields) {
            System.out.println(field.getName() + "==>" + field.getType());
        }
    }

    /**
     * 2.获取某个成员变量
     * Filed getDeclaredField(String name);
     */
    @Test
    public void getDeclaredField() throws NoSuchFieldException {
        //a.获取Class对象
        Class c = Student.class;
        //b.根据名称定位某个成员变量
        Field age = c.getDeclaredField("age");
        //c.打印变量
        System.out.println(age.getName() + "===>" + age.getType());
    }
}

使用获取来的成员变量

  • set(Object obj,Object value) ; 对获取得变量进行赋值。参数一:要负值的对象,参数二:要赋得值
  • **get(Object obj) ; ** 对获取得变量进行取值。参数:要取值得对象
import org.junit.Test;

import java.lang.reflect.Field;

public class TestStudentDemo2 {

    @Test
    public void getDeclaredField() throws NoSuchFieldException, IllegalAccessException {
        //a.获取Class对象
        Class c = Student.class;
        //b.根据名称定位某个成员变量
        Field age = c.getDeclaredField("age");
        //c.打印变量
        System.out.println(age.getName() + "===>" + age.getType());
        //暴力设置权限
        age.setAccessible(true);

        //对获取来的age变量进行赋值
        Student student = new Student();
        age.set(student,18);
        System.out.println(student);
    }
}

反射获取方法Method

四种获取Method方法对象的方式

  1. Method getMethod(String name,Class... args);
    根据方法名和参数类型获得对应的方法对象,只能获得public修饰的
  2. Method getDeclaredMethod(String name,Class... args);
    根据方法名和参数类型获得对应的方法对象,包括private修饰的
  3. Method[] getMethods();
    获得类中的所有成员方法对象,返回数组,只获得public修饰的且包含父类的方法
  4. Method[] getDeclaredMethods();
    获得类中的所有成员方法对象,返回数组,只获得本类申明的方法

使用通过反射技术获取的方法对象

  • 获取成员方法的作用依然是再某个对象中执行此方法

Method类中用于出发执行的方法:
Object incoke(Object obj,Object... args);

  • 参数一:用obj对象调用该方法
  • 参数二:调用方法的传递参数,如果没有就不写
  • 返回值:方法的返回值,如果没有就不写

通过invoke方法启动Student类中的求和方法:

import org.junit.Test;

import java.lang.reflect.Method;

public class TestStudent {
    @Test
    public void getMethod() throws Exception {
        //1.获取class对象
        Class c = Student.class;
        //2.获取方法
        Method getSum = c.getMethod("getSum", int.class, int.class);

        //3.使用方法
        Student s = new Student();
        //这里用的强转为int类型
        int sum = (int)getSum.invoke(s, 2, 3);
        System.out.println(sum);
    }
}

反射的作用(了解)

  1. 可以在运行时得到一个类的全部成分然后操作
  2. 可以破坏封装性(很突出)
  3. 也可以破坏泛型的约束性(很突出)
  4. 更重要的用途是适合:做Java高级框架

绕过编译阶段为集合添加数据

  • 反射是作用再运行时的技术,此时集合的泛型将不能产生约束了,此时是可以为集合存入其他任意类型的元素的。
  • 泛型只是在编译阶段可以约束集合只能操作某种数据类型,在编译成Class文件进入运行阶段的时候,其真实类型都是ArrayList了,反向相当于被擦除了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_细嗅蔷薇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值