栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java基础(二十一)——反射(机制、获取Class对象、获取构造方法、获取成员方法、反射案例)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java基础(二十一)——反射(机制、获取Class对象、获取构造方法、获取成员方法、反射案例)

Java基础(二十一)——反射 一、反射 1、解释

后续补上

2、延伸

反射是框架的灵魂,所有的框架都需要使用到反射技术,使用框架开发的效率会更高 所有的类在反射面前都能看的一清二楚。比如一些私有方法,私有属性,都能够通过某些手段轻易调用。

3、机制

反射机制::将类的各个部分,组合成一个新类,这个类就是Class。

4、反射获取 Class 对象的三种方法

先定义一个 Student 类,里面定义一些方法跟属性。

a、方法一:obj . getClass(通过对象获取)

b、方法二:类名 . Class( 通过类名获取)

c、方法三:Class.forName(…)(通过包名+类名获取)

一般主要通过这种方法来操作反射。

先看下项目的路径结构:

所以,代码是:

这样一来,就可以获取到 Student 这个类。

5、通过反射获取类的构造方法

先来看下通过反射获取类的构造方法的一些方法:


这个 Student 类,其中方法有公有的也有私有的,有无参也有有参,这里仅贴出部分主要的:

a、getConstructors——获取这个类下所有的公有的构造方法(不包括私有构造方法)

b、getDeclaredConstructors——获取这个类下所有的构造方法(包括私有的)

c、getConstructor()和 newInstance()——获取这个类下单个公有的构造方法;实例化对象


这里再强调一下:如果获取有参构造方法,参数类型个数顺序必须一一对应。

d、getDeclaredConstructor()——获取这个类下单个私有的构造方法

这里再强调一下:因为是私有的,所以需要 setAccessible(true),来暴力反射强制性去除私有化,才能成功调用。

6、通过反射获取成员方法

先来看下通过反射获取成员方法的一些方法:

然后看一下,Student 类的一些成员方法:

要调用成员方法,离不开对象,所以,根据上面的知识,可以通过反射调用构造方法来创建对象,这样就能通过对象来调用到成员方法。这里先实例化对象:

注意:这里不用 Student 来接收,因为每次都需要强转;这里图省事用 Object 类来接收。

a、getMethods()——获取所有的公有方法(包括父类公有的方法;不包括私有)

b、getDeclaredMethods()——获取所有公有以及私有的方法

c、getMethod()——获取单个公有的无参方法以及调用

调用方法:xx . invoke(obj)

d、getDeclaredMethod()——获取单个私有的有参方法以及调用

二、反射案例 1、反射案例一

使用集合时,通常会有泛型进行约束。这里通过反射破解泛型的约束,填入不同的数据类型进去(或者说扩大其数据类型为 Object 类型 就可以存在String):

2、反射案例二

有一个配置文件,还有一些 java 文件,仅改变配置文件里面的信息,就可以调用不同的功能。

详细点说,就是类A里面有不同的功能任君调用;
类B专门负责加载配置文件信息并生成一个对象,方便获取其信息。
类C专门负责获取配置文件里面的信息。

配置文件里面存放类名和方法名。修改不同的方法名,便调用不同的方法。

类A:

public class Student {
    private void showinfo1(){
        System.out.println("哈哈哈");
    }
    private void showinfo2(String name,int age,String hobby){
        System.out.println(name+" "+age+" "+hobby);
    }
}

类B:

package com.qf.cmf.fs_lx2;
public class PropertiesUtils {
    //私有的属性。因为静态方法只能调用静态属性
    private static PropertiesUtils propertiesUtils;
    private Properties properties;

    //定义一个私有的构造方法   确保这个类,只有一个实例化的对象。
    private PropertiesUtils(){
        try {
            //实例化 properties 对象
            properties = new Properties();
            //通过反射来加载配置文件到输入流中
            InputStream is = PropertiesUtils.class.getResourceAsStream("demo.properties");  //  这里返回值是流
            //加载properties
            properties.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //定义一个方法来实例化这个对象
    //静态方法锁的对象的是class对象
    //普通的成员方法锁的是当前对象
    public static synchronized PropertiesUtils getInstance(){   //  因为构造方法私有化了,所以创建一个普通方法,通过这个普通方法去调用构造方法
        if (propertiesUtils == null){   //  这里意思是,如果这个类是空的,意味着没有创建过对象
            propertiesUtils = new PropertiesUtils();    //  没有创建过对象就创建,创建过就直接返回。这个类就只允许创建一个对象
        }
        return propertiesUtils;
    }
    //定义一个方法来获取Properties 对象的资源 通过键值对来获取
    public String getValue(String key){
        return properties.getProperty(key);
    }
}

类C:

public class Factory {
    public static void main(String[] args) {
        //获取配置文件中的资源
        try {
            String className = PropertiesUtils.getInstance().getValue("className");
            String met = PropertiesUtils.getInstance().getValue("met");
            String parm = PropertiesUtils.getInstance().getValue("parm");
            //获取Class对象
            Class cls = Class.forName(className);
            Constructor con =  cls.getConstructor();
            //实例化对象
            Object obj = con.newInstance();
            //获取方法
            Class[] clsArray = getClassArrays(parm);

            if (clsArray == null || clsArray.length<=0){        //  满足这个条件,就是私有无参方法
                Method mt1 = cls.getDeclaredMethod(met,clsArray);
                //使用暴力反射去除私有
                mt1.setAccessible(true);
                mt1.invoke(obj);
            }else {
                Method mt1 = cls.getDeclaredMethod(met,clsArray);   //  满足这个条件,就是私有有参方法
                //使用暴力反射去私有
                mt1.setAccessible(true);
                mt1.invoke(obj,"张三",18,"打飞机");       //  这里需要传参
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
    public static Class[] getClassArrays(String parm){
        //实例化集合来进行存储
        ArrayList classlist = new ArrayList<>();
        if (parm == null || "".equals(parm)){
            return null;
        }else {
            //根据逗号来进行分割
            String[] str = parm.split(",");
            //对数组进行非空验证
            if (str !=null && str.length>0){
                for (String s:str) {
                    if (s.equals("String")){
                        classlist.add(String.class);
                    }else if(s.equals("int")){
                        classlist.add(int.class);
                    }else {
                        classlist.add(Object.class);
                    }
                }
            }
            //将集合转换为数组
            return classlist.toArray(new Class[classlist.size()]);
        }
    }
}

配置文件(properties结尾的文件):

className=com.qf.cmf.fs_lx2.Student
met=showinfo2
parm=String,int,String

这里的配置文件,对应的是 Student 类里面的方法和参数。只需要改动配置文件,就可以执行不同的方法。这里的功能可以说是框架也用到了,是部分底层源码。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/584899.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号