enum.values_占用内存的Enum.values()方法

enum.values

我是Java 枚举的忠实拥护者 。 似乎我们一直在等待获得它,但是当我们最终获得它( J2SE 5 )时,该枚举比C和C ++提供的枚举要好得多,对我来说似乎“ 值得等待” 。 与Java enum一样好,它也不是没有问题。 特别是,Java枚举的方法values()返回数组的新副本,该副本表示每次调用该数组时可能的值。

Java语言规范阐明了枚举行为。 在Java语言规范Java SE 10 Edition中 , 第8.9节涵盖了枚举。 第8.9.3节 (“枚举成员”)列出了两个“隐式声明的方法”: public static E[] values()public static E valueOf(String name)例8.9.3-1 (“使用增强的for循环遍历枚举常量”)演示了如何调用Enum.values()遍历枚举。 但是,问题在于Enum.values()返回一个数组,而Java中的数组是可变的[Java语言规范的10.9节 (“字符数组不是字符串”)提醒我们在区分Java时要注意这一点。 string和Java字符数组。]。 Java枚举是紧密不变的,因此有意义的是,每次调用该枚举以确保不更改与该枚举关联的数组时,该枚举必须返回由values()方法返回的数组的克隆。

最近在OpenJDK 编译器-开发邮件列表上的标题为“ 关于Enum.values()内存分配 ”的Enum.values()指出,当在紧密循环中调用Enum.values()克隆常量值数组时,它将分配大量内存。 ” 该消息的发布者补充说,这“可能是出于不变性”,并指出:“我能理解。” 该消息还引用了同一邮件列表上的2012年3月消息和相关主题。

编译器-开发邮件列表上的两个线程包括一些有趣的当前可用的解决方法。

  • 将由values()返回的枚举值数组缓存为元素的private static final数组,这些元素的初始private static final数组初始化为values()返回的数组。
  • 缓存枚举值的固定List
  • 创建一个枚举值的EnumSet

Brian Goetz在该线程上的消息开头是“这本质上是API设计错误; 因为values()返回一个数组,并且数组是可变的,所以每次都必须复制该数组。” [Goetz在该消息中还嘲笑了“ 冻结数组 ”(使Java数组变得不可变)的概念。]

这个问题不是新问题。 威廉·希尔兹(William Shields)在2009年12月发表的文章《 Java中的可变性,数组和临时对象的成本 》指出:“所有这些的最大问题是Java数组是可变的。” 在撰写有关Enum.values()提出的特定问题之前,Shields解释了Java Date类中可变性的古老而众所周知的问题:

Java枚举有一个称为values()的静态方法,该方法返回该enum的所有实例的数组 Date类的课程中,这个特殊的决定令人震惊。 List本来是更明智的选择。 在内部,这意味着实例数组每次调用时都必须进行防御性复制...

对此问题的其他引用包括“ Enums.values()方法 ”(Guava线程)和“ Java的Enum.values()隐藏分配 ”(显示缓存Enum.values()返回的数组)。 上面还写了一个JDK错误: JDK-8073381 (“需要API来获取枚举值而不创建新数组”)。

下一个代码清单中说明了本文中讨论的一些当前可用的变通方法,这是一个简单的Fruit枚举,演示了以三种不同格式缓存该枚举的值。

具有三个“值”的缓存集的Fruit.java枚举

package dustin.examples.enums;import java.util.EnumSet;
import java.util.List;/*** Fruit enum that demonstrates some currently available* approaches for caching an enum's values so that a new* copy of those values does not need to be instantiated* each time .values() is called.*/
public enum Fruit
{APPLE("Apple"),APRICOT("Apricot"),BANANA("Banana"),BLACKBERRY("Blackberry"),BLUEBERRY("Blueberry"),BOYSENBERRY("Boysenberry"),CANTALOUPE("Cantaloupe"),CHERRY("Cherry"),CRANBERRY("Cranberry"),GRAPE("Grape"),GRAPEFRUIT("Grapefruit"),GUAVA("Guava"),HONEYDEW("Honeydew"),KIWI("Kiwi"),KUMQUAT("Kumquat"),LEMON("Lemon"),LIME("Lime"),MANGO("Mango"),ORANGE("Orange"),PAPAYA("Papaya"),PEACH("Peach"),PEAR("Pear"),PLUM("Plum"),RASPBERRY("Raspberry"),STRAWBERRY("Strawberry"),TANGERINE("Tangerine"),WATERMELON("Watermelon");private String fruitName;Fruit(final String newFruitName){fruitName = newFruitName;}/** Cached fruits in immutable list. */private static final List<Fruit> cachedFruitsList = List.of(Fruit.values());/** Cached fruits in EnumSet. */private static final EnumSet<Fruit> cachedFruitsEnumSet = EnumSet.allOf(Fruit.class);/** Cached fruits in original array form. */private static final Fruit[] cachedFruits = Fruit.values();public static List<Fruit> cachedListValues(){return cachedFruitsList;}public static EnumSet<Fruit> cachedEnumSetValues(){return cachedFruitsEnumSet;}public static Fruit[] cachedArrayValues(){return cachedFruits;}
}

在许多情况下,每次调用Enum.values()必须克隆其数组的事实实际上并不重要。 也就是说,不难设想在“紧缩循环”中反复调用Enum.values()会很有用,然后每次将枚举值复制到数组中都会开始对内存产生明显影响的情况并不难使用以及与更大内存使用相关的问题。 最好有一种标准的方法来以更有效的内存方式访问枚举的值。 前面提到的两个线程讨论了一些潜在实现此功能的想法。

翻译自: https://www.javacodegeeks.com/2018/08/memory-hogging-enum-values-method.html

enum.values

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/333121.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

搭建配置中心微服务

一、实现步骤&#xff1a; 创建配置中心SpringBoot项目config_server配置坐标依赖启动类添加开启配置中心服务注解配置服务中心application.yml文件启动测试 二、创建配置中心SpringBoot项目config_server 配置坐标依赖 需要依赖父工程 <?xml version"1.0" en…

Linux命令之 users -- 显示当前登录的用户

文章目录命令介绍参考示例查看当前登录的所有用户命令介绍 users 命令用于显示当前登录系统的所有用户的用户列表。每个显示的用户名对应一个登录会话。如果一个用户有不止一个登录会话&#xff0c;那他的用户名将显示相同的次数。 参考示例 查看当前登录的所有用户 [rooth…

使用Spring Boot和H2可以正常工作的原型

我们确实在弹簧上使用了很多h2&#xff0c;特别是对于单元测试。 但是&#xff0c;我们可能希望有一个功能齐全的原型来显示数据&#xff0c;而不是进行单元测试。 H2是最理想的选择&#xff0c;它在spring上运行良好&#xff0c;与大多数数据库都具有良好的语法兼容性&#x…

服务去获取配置中心配置

目标&#xff1a;改造user_service工程&#xff0c;配置文件不再由微服务项目提供&#xff0c;而是从配置中心获取。 实现步骤&#xff1a; 添加配置中心客户端启动依赖修改服务提供者的配置文件启动服务测试效果 一、添加依赖 <!--spring cloud 配置中心--> <depe…

Linux查看用户信息/查看所有用户信息的命令

文章目录通过文件 /etc/passwd 来查看所有用户信息通过文件 /etc/shadow 查看所有用户信息使用 getent 命令查看所有用户信息使用 compgen 命令查看所有的用户信息相关文件/etc/passwd/etc/passwd 文件内容格式说明/etc/shadow/etc/group/etc/group 文件内容格式说明/etc/gshad…

graalvm_GraalVM上的Picocli:极快的命令行应用程序

graalvmGraalVM GraalVM允许您提前将程序编译为本地可执行文件。 与Java VM相比&#xff0c;生成的程序具有更快的启动时间和更低的运行时内存开销。 这对于通常寿命很短的命令行实用程序尤其有用。 GraalVM对Java反射的支持有限&#xff0c;它需要提前知道反射访问的程序元素…

Linux 命令之 getent -- 查看记录

文章目录命令介绍常用选项参考示例查看文件 /etc/protocols 中的所有记录查看指定用户组是否存在&#xff0c;若不存在则创建指定的用户组根据主机名称&#xff0c;查看对应的IP地址根据域名查找对应的IP根据用户名查找对应的UID获取当前登陆用户的信息根据UID查找用户名查找那…

运行SpringBoot时:Type javax.xml.bind.JAXBContext not present

原因和简单介绍 我有一些代码使用JAXB API类&#xff0c;它们是作为Java 6/7/8中JDK的一部分提供的。当我使用Java 9运行相同的代码时&#xff0c;在运行时我得到错误&#xff0c;指示无法找到JAXB类。 自Java 6以来&#xff0c;JAXB类已作为JDK的一部分提供&#xff0c;为什么…

Linux 命令之 chfn -- 修改用户信息

文章目录命令简介常用选项参考示例改变用户 root 的 finger 信息命令简介 chfn 命令的英文全称是 change finger&#xff0c;即用来改变 finger 命令显示的信息。这些信息都存放在 /etc/passwd 文件里。若不指定任何选项&#xff0c;则chfn 命令会进入问答式界面。 常用选项 …

cassandra可视化_容器化Spring Data Cassandra应用程序

cassandra可视化我正在继续学习Docker的旅程。 在这一点上&#xff0c;我仍然保持简单。 这次&#xff0c;我将解决将Spring和Cassandra应用程序转换为使用容器而不是在主机上本地运行的问题。 更确切地说&#xff0c;使用Spring Data Cassandra整理应用程序。 我希望我前几天…

自定义Mybatis框架

一、开发环境的准备及统一 1、 Jdk环境&#xff1a;JDK 1.8 64bit 2、 Maven环境&#xff1a;MAVEN 3.3.9 二、创建Maven工程并引入坐标 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"…

Linux 命令之 userconf -- 设置用户账号

文章目录命令介绍常用选项参考示例新增用户账号新增群组删除用户账号删除群组命令介绍 userconf的命令全称是“user config”&#xff0c;该命令是用户账号设置程序。 userconf实际上为linuxconf的符号连接&#xff0c;提供图形界面的操作方式&#xff0c;供管理员建立与管理各…

javafx 动画没效果_通过JavaFX标注制作动画效果

javafx 动画没效果在本文中&#xff0c;您将学习如何使用JavaFX的动画API创建标注。 您可以在https://www.youtube.com/watch?vXTHbB0LRdT4的 YouTube网站上查看这些标注的演示示例。 什么是标注&#xff1f; 我敢肯定&#xff0c;您已经看过广告或科幻电影&#xff0c;它们使…

基于自定义Mybatis框架实现数据库操作

一、场景模拟 基于自定义Mybatis框架和已有的Mysql数据库Mybatis&#xff0c;查询所有用户信息。 二、创建工程并引入自定义Mybatis框架的坐标 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0…

javafx按钮设计风格_Java,JavaFX的流畅设计风格按钮,切换按钮和工具提示

javafx按钮设计风格你好&#xff0c;我们又见面了&#xff01; 这个周末&#xff0c;在业余时间&#xff0c;我继续从事JMetro的工作。 最终结果是新的Button和ToggleButton深色和浅色样式。 这些新样式包括按下按钮时的新动画。 可以通过CSS打开和关闭。 最后&#xff0c;我…

MySQL数据库变量_数据库参数_MySQL变量_系统变量_用户变量

文章目录MySQL 变量分类系统变量查看系统变量设置系统变量如何通过配置文件来设置变量值通过命令行选项来设置变量值动态设置全局级的系统变量设置静态的系统变量设置会话级的系统变量引用系统变量总结用户自定义变量用户变量声明定义用户变量查看用户变量的值参考示例使用命令…

Mybatis框架快速入门

一、场景模拟 基于自定义Mybatis框架和已有的Mysql数据库Mybatis&#xff0c;查询所有用户信息。 二、创建工程并引入Mybatis框架的坐标 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"…

oidc_使用Java EE和OIDC构建Java REST API

oidc“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕&#xff1f; 尝试使用Okta API进行托管身份验证&#xff0c;授权和多因素身份验证。 Java EE允许您使用JAX-RS和JPA快速轻松地构建Java REST API。 Java EE是保护伞标…

Mybatis实现CRUD操作

项目实现的功能 查询所有用户信息 通过Id查询用户信息 添加用户&#xff08;回显主键&#xff09; 修改用户信息 删除用户信息 通过用户名字模糊查询 一、引入依赖和工程结构 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http…

Linux系统下MySQL的导出数据语句SELECT … INTO OUTFILE的用法

文章目录关于参数 secure_file_priv按默认参数设定导出表数据到文本文件中自定义分隔符&#xff0c;将表数据导出到 txt 文件中自定义分隔符&#xff0c;将表数据导出到 csv 文件中导出数据时&#xff0c;提示“拒绝访问”总结确保 Linux 用户 mysql 对导出的目标目录拥有写入和…