Java 学习之反射机制“解刨”分解类,并获取内容!

简介: 正常情况下,单纯的做开发是接触不到反射机制的(额,当然并不排除例外的情况了)。下面我就对我学到的反射方面的知识做一个小小的总结,旨在复习和以后的查看。原理分析: 所谓反射就是将一个类当做我们研究的对象,进行分解,获取其中的内容的过程。

正常情况下,单纯的做开发是接触不到反射机制的(额,当然并不排除例外的情况了)。下面我就对我学到的反射方面的知识做一个小小的总结,旨在复习和以后的查看。


原理分析:
所谓反射就是将一个类当做我们研究的对象,进行分解,获取其中的内容的过程。其核心就是Class类,他是所有类的研究的对象,基于Class我们就可以获取一个类的字节码,进而获取想要的值。

目标类(待解刨的类)



package reflect;

public class Person {

    public Person(){}

    private String name;
    public int address;

    public int getAddress() {
        return address;
    }

    public void setAddress(int address) {
        this.address = address;
    }

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

    public Person(String name ){
        this.name = name;
    }

    public String getName(){
        return this.name;
    }

    private Person(int name){
        System.out.println("这里是私有的带有参数的构造方法!");
    }

    public void eat(){
        System.out.println("吃饭!");
    }

    public void drink(String name){
        System.out.println("正在喝 :"+ name);
    }

    public void purchase(String address ,int [] number , String [] item){
        System.out.println("这个人在  " + address +"  买了 "+item +"  分别  "+ number+" 个!");
    }

    private String flay(String tool){
        return "I Can Flay By "+ tool;
    }

    public static String spend(String money){
        System.out.println("我只能够花费 "+money +"钱!");
        return "你造吗?";
    }

    public static void main(String[] args) {
        System.out.println(args[0]);
    }

}

反射构造方法小例子


package reflect;

import java.lang.reflect.Constructor;

import org.junit.Test;

public class ReflectConstructor {


    /**
     * 反射得到无参的构造函数的方法
     * @throws Exception
     */
    @Test
    public void reflect1() throws Exception{
        Class cls = Class.forName("reflect.Person");
        Constructor c = cls.getConstructor(null);
        Person person = (Person) c.newInstance(null);
        System.out.println("反射得到的结果是:"+ person.toString());
    }


    /**
     * 反射出带有参数的构造方法
     * @throws Exception
     */
    @Test
    public void reflect2() throws Exception {
        Class cls = Class.forName("reflect.Person");
        Constructor c = cls.getConstructor(String.class);
        Person person = (Person) c.newInstance("Name");
        System.out.println("反射获得的有参的结果是:"+ person.getName());
    }

    /**
     * 反射出私有的带有参数的构造方法
     * @throws NoSuchMethodException
     * @throws Exception
     */
    @Test
    public void reflect3() throws NoSuchMethodException, Exception {
        Class cls = Class.forName("reflect.Person");
        Constructor c = cls.getDeclaredConstructor(int.class);
        //java语言默认私有的方法是不能被外界访问的到的,但要进行强制的访问需要加上一层权限
        c.setAccessible(true);
        Person person = (Person) c.newInstance(201492115);

        System.out.println("反射出私有的带有参数的构造方法!"+ person.toString());
    }

}

反射所有方法的小例子


package reflect;

import java.lang.reflect.Method;

import org.junit.Test;

public class ReflectMethods {

    /**
     * 反射测试一个无参的方法
     * public void eat()
     * @throws Exception
     */
    @Test
    public void feflect1() throws Exception {
        Class cls = Class.forName("reflect.Person");
        Method method =cls.getMethod("eat", null);
        System.out.println(method.toString());
        method.invoke(new Person(), null);
        method.invoke(cls.newInstance(), null);
    }

    /**
     * 反射测试一个带有参数的方法
     * public void drink(String name)
     * @throws Exception
     */
    @Test
    public void reflect2() throws  Exception {

        Class cls = Class.forName("reflect.Person");
        Method method =cls.getMethod("drink", String.class);
        System.out.println(method.toString());
        method.invoke(new Person(), "中国凉茶");
        method.invoke(cls.newInstance(), "中国凉茶");
    }

    /**
     * 反射测试含有多个复杂类型的参数的方法
     * public void purchase(String address ,int [] number , String [] item)
     * @throws Exception
     */
    @Test
    public void reflect3() throws Exception {
        Class cls = Class.forName("reflect.Person");
        Method method = cls.getMethod("purchase", String.class,int[].class,String[].class);
        method.invoke(cls.newInstance(), "大连",new int[]{1,2,3},new String[]{"鱿鱼","贝壳","螃蟹"});
    }


    /**
     * 反射测试一个带有返回值的不含参数的方法
     * public String getName()
     * @throws Exception
     */
    @Test
    public void reflect4() throws Exception {
        Class cls = Class.forName("reflect.Person");
        Method method = cls.getMethod("getName", null);
        String result = (String) method.invoke(cls.newInstance(), null);
        System.out.println("测试带有返回值的无参的方法,所得的结果是: "+result);

    }


    /**
     * 反射测试私有含参数的方法
     * private String flay(String tool)
     */
    @Test
    public void reflect5() throws Exception {

        Class cls = Class.forName("reflect.Person");
        //对于私有的方法只能通过getDeclaredMethod方式得到
        Method method = cls.getDeclaredMethod("flay", String.class);
        //记得强制将访问人权限提升起来到"可以访问的到"
        method.setAccessible(true);
        String result = (String) method.invoke(cls.newInstance(), "蝙蝠侠的风衣!");
        System.out.println("反射测试私有的含参数的方法的结果是: "+ result);
    }

    /**
     * 反射测试私有的含参数的静态的方法
     * public static String spend(String money)
     */
    @Test
    public void reflect6() throws Exception {

        Class cls = Class.forName("reflect.Person");
        //对于静态的方法只能通过getDeclaredMethod方式得到
        Method method = cls.getDeclaredMethod("spend", String.class);

        String result = (String) method.invoke(cls.newInstance(), "100000000000000元人民币!");
        System.out.println("反射测试私有的含参数的方法的结果是: "+ result);
    }

    /**
     * 反射测试主方法
     * public static void main(String[] args) 
     * @throws Exception
     */
    @Test
    public void reflect7() throws Exception {
        Class cls = Class.forName("reflect.Person");
        Method method = cls.getMethod("main",String[].class);
        method.invoke(null, (Object)new String[]{"A","B","C"});
    }

}

反射字段值的小例子


package reflect;

import java.lang.reflect.Field;

import org.junit.Test;

public class ReflectField {

    /**
     * 反射测试字段(属性)的值
     * public int address
     * @throws Exception
     */
    @Test
    public void reflect1 () throws Exception {
        Class cls = Class.forName("reflect.Person");
        Field field = cls.getField("address");
        String result = field.getName();
        System.out.println("反射所得的字段的结果是:"+result);
    }

    /**
     * 反射测试私有的属性(字段)的结果
     * private String name 
     * @throws Exception
     */
    @Test
    public void reflect2() throws Exception {
        Class cls = Class.forName("reflect.Person");
        Field field = cls.getDeclaredField("name");
        field.setAccessible(true);
        String result = field.getName();
        System.out.println("反射测试所得的私有的字段(属性)的值为:"+ result);
    }

}

我的总结


  • 全部的反射方法均交给JUnit测试通过,并没有发现出错的地方
  • 反射是一个比较灵活的方式,具体情况一定要灵活的变通
  • 对于私有的变量或者方法,要想访问到其值,就必须打开访问的权限即设置为setAccessable(true);
  • 对于框架的运行,需要给出一个类的完整名称(包含完整的包名),这样才不会出错!
目录
相关文章
|
12小时前
|
设计模式 消息中间件 算法
【实习总结】Java学习最佳实践!
【实习总结】Java学习最佳实践!
16 3
|
12小时前
|
安全 Java 开发者
Java一分钟之-文件与目录操作:Path与Files类
【5月更文挑战第13天】Java 7 引入`java.nio.file`包,`Path`和`Files`类提供文件和目录操作。`Path`表示路径,不可变。`Files`包含静态方法,支持创建、删除、读写文件和目录。常见问题包括:忽略异常处理、路径解析错误和权限问题。在使用时,注意异常处理、正确格式化路径和考虑权限,以保证代码稳定和安全。结合具体需求,这些方法将使文件操作更高效。
11 2
|
12小时前
|
安全 Java 开发者
Java一分钟之-Optional类:优雅处理null值
【5月更文挑战第13天】Java 8的`Optional`类旨在减少`NullPointerException`,提供优雅的空值处理。本文介绍`Optional`的基本用法、创建、常见操作,以及如何避免错误,如直接调用`get()`、误用`if (optional != null)`检查和过度使用`Optional`。正确使用`Optional`能提高代码可读性和健壮性,建议结合实际场景灵活应用。
17 3
|
12小时前
|
存储 Java ice
【Java开发指南 | 第十六篇】Java数组及Arrays类
【Java开发指南 | 第十六篇】Java数组及Arrays类
8 3
|
12小时前
|
Java 编译器 ice
【Java开发指南 | 第十五篇】Java Character 类、String 类
【Java开发指南 | 第十五篇】Java Character 类、String 类
13 1
|
12小时前
|
存储 Java ice
【Java开发指南 | 第十四篇】Java Number类及Math类
【Java开发指南 | 第十四篇】Java Number类及Math类
10 1
|
12小时前
|
数据采集 安全 Java
Java并发编程学习12-任务取消(上)
【5月更文挑战第6天】本篇介绍了取消策略、线程中断、中断策略 和 响应中断的内容
17 4
Java并发编程学习12-任务取消(上)
|
12小时前
|
存储 缓存 Java
【Java开发指南 | 第六篇】Java成员变量(实例变量)、 类变量(静态变量)
【Java开发指南 | 第六篇】Java成员变量(实例变量)、 类变量(静态变量)
9 2
|
12小时前
|
安全 Java 调度
深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第12天】 在现代软件开发中,多线程编程是提升应用程序性能和响应能力的关键手段之一。特别是在Java语言中,由于其内置的跨平台线程支持,开发者可以轻松地创建和管理线程。然而,随之而来的并发问题也不容小觑。本文将探讨Java并发编程的核心概念,包括线程安全策略、锁机制以及性能优化技巧。通过实例分析与性能比较,我们旨在为读者提供一套既确保线程安全又兼顾性能的编程指导。
|
12小时前
|
Java 程序员 调度
Java中的多线程编程:从理论到实践
【5月更文挑战第14天】在现代计算机技术中,多线程编程是一个重要的概念。它允许多个线程并行执行,从而提高程序的运行效率。本文将从理论和实践两个角度深入探讨Java中的多线程编程,包括线程的基本概念、创建和控制线程的方法,以及如何处理线程同步和通信问题。