我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Hutool开发利器MapProxy类使用技巧详解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Hutool开发利器MapProxy类使用技巧详解

概述

Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。

目前公司项目中主要采用Hutool作为项目的工具包,相对于google的guava, hutool的工具类采用中文注释,更加符合国人使用。所谓知己知彼,我们需要了解Hutool都具有什么样的功能,才能够最大化发挥它的价值。

本文主要就hutool 5.8.8版本中MapProxy的使用。

场景引入

其实Map在get的时候是比较危险的,你可能不知道它是什么类型,需要进行强制,举个例子如下:

@Test
public void testMapProxy1() {
    Map<String, Object> userMap = MapUtil.newHashMap(16);
    userMap.put("username", "alvin");
    userMap.put("age", 20);
    // 使用map的时候, 需要进行强转,一旦类型错误,会报错
    String age = (String)userMap.get("age");
}

运行结果:

那有什么更好的解决方案吗?Hutool提供了一种解决方案给我们。

MapProxy使用

依赖引入

<dependency>
  <groupId>cn.hutool</groupId>
  <artifactId>hutool-all</artifactId>
  <version>5.8.8</version>
</dependency>

定义一个可访问接口

interface MapUser {
    String getUsername();
    Integer getAge();
    MapUser setAge(Integer age);
}

通过MapProxy访问

@Test
public void testMapProxy2() {
    Map<String, Object> userMap = MapUtil.newHashMap(16);
    userMap.put("username", "alvin");
    userMap.put("age", 20);
    MapProxy mapProxy = MapProxy.create(userMap);
    Integer age = mapProxy.getInt("age", 18);
    Assert.assertTrue(age == 20);
    // 通过代理的方式
    MapUser mapUser = mapProxy.toProxyBean(MapUser.class);
    // 后续访问会变的更加安全
    Assert.assertTrue(mapUser.getAge() == 20);
    mapUser.setAge(30);
    Assert.assertTrue(mapUser.getAge() == 30);
}

MapProxy源码解析

Map代理,提供各种getXXX方法,并提供默认值支持,它的类结构图如下:

  • 实现了OptNullBasicTypeFromObjectGetter接口, 提供了基本类型的get, 在不提供默认值的情况下, 如果值不存在或获取错误,返回null, 比如:mapProxy.getInt("age", 18)
  • 实现了InvocationHandler接口,支持jdk的动态代理,生成代理对象。
public <T> T toProxyBean(Class<T> interfaceClass) {
    return (T) Proxy.newProxyInstance(ClassLoaderUtil.getClassLoader(), new Class<?>[]{interfaceClass}, this);
}
  • toProxyBean方法就是生成代理对象,最终会调用代理类的invoke方法,这里的代理类就是MapProxy本身。
public Object invoke(Object proxy, Method method, Object[] args) {
    final Class<?>[] parameterTypes = method.getParameterTypes();
    // 如果调用方法参数为空
    if (ArrayUtil.isEmpty(parameterTypes)) {
        final Class<?> returnType = method.getReturnType();
        // 方法返回值不是void
        if (void.class != returnType) {
            // 匹配Getter
            final String methodName = method.getName();
            String fieldName = null;
            if (methodName.startsWith("get")) {
                // 匹配getXXX
                fieldName = StrUtil.removePreAndLowerFirst(methodName, 3);
            } else if (BooleanUtil.isBoolean(returnType) && methodName.startsWith("is")) {
                // 匹配isXXX
                fieldName = StrUtil.removePreAndLowerFirst(methodName, 2);
            }else if ("hashCode".equals(methodName)) {
                return this.hashCode();
            } else if ("toString".equals(methodName)) {
                return this.toString();
            }
            if (StrUtil.isNotBlank(fieldName)) {
                if (false == this.containsKey(fieldName)) {
                    // 驼峰不存在转下划线尝试
                    fieldName = StrUtil.toUnderlineCase(fieldName);
                }
                return Convert.convert(method.getGenericReturnType(), this.get(fieldName));
            }
        }
        // 如果方法参数不为空
    } else if (1 == parameterTypes.length) {
        // 匹配Setter
        final String methodName = method.getName();
        if (methodName.startsWith("set")) {
            final String fieldName = StrUtil.removePreAndLowerFirst(methodName, 3);
            if (StrUtil.isNotBlank(fieldName)) {
                this.put(fieldName, args[0]);
                final Class<?> returnType = method.getReturnType();
                // 判断返回类型是不是代理类的实例
                if(returnType.isInstance(proxy)){
                    return proxy;
                }
            }
        } else if ("equals".equals(methodName)) {
            return this.equals(args[0]);
        }
    }
    throw new UnsupportedOperationException(method.toGenericString());
}

总结

本文主要讲解了Hutool中的MapProxy类的使用,希望对大家有帮助

以上就是Hutool开发利器MapProxy类使用技巧详解的详细内容,更多关于Hutool开发MapProxy类的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Hutool开发利器MapProxy类使用技巧详解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

详解Python开发中如何使用Hook技巧

什么是Hook,就是在一个已有的方法上加入一些钩子,使得在该方法执行前或执行后另在做一些额外的处理,那么Hook技巧有什么作用以及我们为什么需要使用它呢,事实上如果一个项目在设计架构时考虑的足够充分,模块抽象的足够合理,设计之初为以后的扩展
2022-06-04

flutter开发技巧自定页面指示器PageIndicator详解

这篇文章主要为大家介绍了flutter开发技巧自定页面指示器PageIndicator详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-01-15

详解Android开发中ContentObserver类的使用

ContentObserver——内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于 数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它。触发
2022-06-06

精通Golang开发利器:常用标准库的关键技巧!

Golang开发利器:掌握常用标准库的关键!摘要:Golang是一门快速、高效、安全的编程语言,而其中的标准库更是使得Golang成为了现代编程语言中的佼佼者。本文将介绍Golang常用标准库的关键,帮助读者更好地掌握这些利器,提高开发效率
精通Golang开发利器:常用标准库的关键技巧!
2023-12-29

go并发利器sync.Once使用示例详解

这篇文章主要为大家介绍了go并发利器sync.Once使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-03-14

Android开发效率提升利器-ButterKnife最全使用详解及ButterKnife插件的使用

本文目录ButterKnife 概述使用前准备添加依赖ButterKnife绑定Activity绑定Fragment绑定RecyclerView Adapter绑定基本用法控件注解事件注解资源注解ButterKnife 插件插件添加插件使用
2022-06-06

有效利用虚拟选择器:提升开发效率的高级技巧与应用

提升开发效率:掌握虚拟选择器的高级技巧与应用摘要:随着互联网的迅猛发展,Web开发已经成为一个必不可少的技能。然而,开发者们常常陷入代码冗长和重复的困境中。本文将介绍一种提升开发效率的高级技巧——虚拟选择器,让我们能够更加灵活地操作DOM
有效利用虚拟选择器:提升开发效率的高级技巧与应用
2024-01-15

Java开发JUC交换器Exchanger使用详解

这篇文章主要为大家介绍了Java开发JUC交换器Exchanger使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-12-08

JavaWeb开发中过滤器和监听器使用详解

这篇文章主要为大家详细介绍了Java中的过滤器Filter和监听器Listener的使用以及二者的区别,文中的示例代码讲解详细,需要的可以参考一下
2022-11-13

ImageMagick免费开源图片批处理利器使用详解

这篇文章主要为大家介绍了ImageMagick免费开源图片批处理利器使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-05-16

阿里云服务器下发文件全面解析与使用技巧

阿里云服务器是一种基于云的计算资源,具有高效、安全、灵活等特点。在阿里云服务器中,如何高效地下发文件是很多用户关注的问题。本文将详细介绍阿里云服务器下发文件的流程和技巧,希望能对用户有所帮助。一、阿里云服务器下发文件的流程1.创建文件在阿里云服务器中,我们需要首先创建文件。创建文件的步骤很简单,只需要使用“tou
阿里云服务器下发文件全面解析与使用技巧
2023-12-12

Android开发中类加载器DexClassLoader的简单使用讲解

简介 “类装载器”(ClassLoader),顾名思义,就是用来动态装载class文件的。标准的Java SDK中有个ClassLoader类,借助此类可以装载需要的class文件,前提是ClassLoader类初始化必须制定class文件
2022-06-06

SqlServer开发神器'SQLPrompt'插件的使用详解

目录一:可以用缩写来代替命令语句。二:可以忽略大小写以及会自动补全,当表名或存储过程名字忘记时,只需要写几个关键字母就可以看到提示。三:任何表,视图,存储过程以及函数,作业等都可以快速预览其creat语句四:当输入完“inser
2023-03-06

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录