2个菜鸟Java常量和枚举陷阱

在对Java和Groovy代码进行的各种代码审查中,我经常看到魔术数字和其他随机字符串在整个代码库中乱七八糟。

例如,魔术数字是下面的代码(Groovy)中的4.2:

if (swashbuckle >= 4.2) {...
}

4.2是什么意思?

我的建议是将一个数字提取为一个常数,并为其赋予一个有意义的意图显示名称,以便我们所有人都可以继续理解我们的代码。

每次平台特定的常量

重构成

if (swashbuckle >= MAX_ALLOWED_CAPACITY) {...
}

即使是初学者,也可以理解The Constant的值,并开始将各地的值提取为常量。 当我谈论枚举时,编写可读代码甚至更有可能,但是经验不足的开发人员很快就会陷入以下陷阱。

陷阱#1全球Über-Constants文件

应尽可能避免使用全局常量文件,例如

class Constants {private static final String PEACH_FLAME = "PFL"private static final int MAX_TOOGIT = 17private static final int MIN_TOOGIT = 8private static final String USER_NAME_AGE_PROPERTY =  "age"private static final String USER_NAME_FLOPPY_PROPERTY =  "floppy"private static final int CUSTOM_HYSLERIA_DONE = -99private static final List<String> WOBBA_RANGE = ['BZ, 'FLL', 'BZZ']// dozens of other constants...

引用StackOverflow总结得很好 :

我强烈建议不要使用单个常量类。 当时这似乎是个好主意,但是当开发人员拒绝记录常量并且该类增长到包含多达500个完全不相关的常量(与应用程序的完全不同的方面)时,这通常会变成完全不可读的常量文件。 代替:

  • 如果可以访问Java 5+,请使用枚举为应用程序区域定义特定的常量。 对于这些常量,应用程序区域的所有部分都应引用枚举,而不是常量。 您可以声明类似于声明类的枚举。 枚举也许是Java 5+的最(也是唯一的)有用的功能。
  • 如果您的常量仅对特定类或其子类之一有效,则将其声明为protected或public,然后将其放在层次结构中的顶级类上。 这样,子类可以访问这些常量值(如果其他类通过public访问它们,则这些常量不仅仅对特定的类有效……这意味着使用该常量的外部类可能与包含该常量的类紧密耦合。常数)
  • 如果您有一个定义了行为的接口,但是返回值或参数值应该是特定的,那么在该接口上定义常量是完全可以接受的,以便其他实现者可以访问它们。 但是,请避免创建仅用于保存常量的接口:它可能与仅为保存常量而创建的类一样糟糕。

一个类(例如上面的Constants示例)很快就变成了一切 。 新秀开发人员认为他通过将魔术数字和魔术字符串提取为常量来遵循良好的(代码审查)建议,但是团队很快就承担了新的维护负担。

如果你发现自己(或你的团队)这样做,请把负责任的车主如用户相关的常数常量UserService在和wobba相关常量WobbaConverter -不管它是什么

还请阅读上面评论中有关枚举的部分,因为常量并不是镇上唯一的孩子。 有时我的建议是……

首选枚举

如果您的常量可以很好地建模为枚举,请考虑枚举结构。 枚举比普通常量更通用 ; 它们是类,可以包含属性和方法。

在负责任的父类中。

更喜欢

class Person {enum Gender { M, F }String nameGender gender
}

过度

class Person {static final String GENDER_MALE = 'M'static final String GENDER_FEMALE = 'F'String nameString gender
}

或作为使用它的班级附近的一个单独的班级 (如果它变大了)。 带有功能名称的enum类的一个很好的例子是例如一些相关的(技术)数据

/*** Represents medicine domain codes.*/
public enum MedicineCode {/** Diagnosis e.g. "Muscle damage". */DIAGNOSIS("X357"),/** Units in medicinal context e.g. "cc/ml". */MEDICINE_UNIT("X523"),/*** Cause codes for diagnosis = 'Masitis' e.g. "E.coli (ECO)".*/CAUSE_CODE("X536"),/** TreatmentType e.g. "Antibiotics". */INTERVAL_TYPE("X520"),
MedicineCode(String code) {this.code = code;}private final String code;public String code() {return code;}/*** Find a {@link MedicineCode} by given String code.** @param code The code e.g. "X261"* @return found medicine code, or null*/public static MedicineCode findByCode(String code) {values().find { it.code() == code }}@Overridepublic String toString() {return name() + "(" + code() + ")"}
}

每当需要表示一组固定的常量时,都应使用枚举类型。 因此,新秀开发人员认为他通过遵循一些很好的(代码审查)建议,将内容提取到枚举中,封装了技术数据,使用功能名称等,但通常会陷入

陷阱#2定义枚举,并非真正正确地使用它们

因此,如果您最初具有以下方法和调用:

Medicine findMedicineForDomainCode(String code)// which you call like: 
String intervalTypeCode = "X520"
findMedicineForDomainCode(intervalTypeCode)

并且您可能会引入像MedicineCode这样的枚举(请参见上文),将所有这些特定于域的技术代码(例如数据库“ X…”)(例如“ X520”)封装在一起,然后不要这样做:

Medicine findMedicineForDomainCode(String domainCode)// which one keeps calling like:
String intervalTypeCode = MedicineCode.findByCode("X520")
findMedicineForDomainCode(intervalTypeCode)

我见过像这样的团队。 是的,有一个带有值的枚举类型,但是团队在整个代码中并不十分了解如何处理它们。

枚举

第一步是直接引用枚举 。 某些菜鸟开发人员通常最初已经理解了这一点,这取决于他们是否遵循Oracle Java Enum Types教程或类似内容,但是通常会导致如下所示:

Medicine findMedicineForDomainCode(String code)// which one calls like:
String intervalTypeCode = INTERVAL_TYPE.code()
// WRONG! still using Strings here
findMedicineForDomainCode(intervalTypeCode)

有了枚举意味着我们现在可以键入所有内容,包括返回类型和方法参数

只是将枚举用作容纳字符串的容器并不是我们这样做的原因:为了获得更好的类型安全性和可读性,您应该重构代码中的所有内容,以便将域代码用作MedicineCode枚举的字符串类。

更好:

// first refactor method parameter from String to MedicineCode
Medicine findMedicineForDomainCode(MedicineCode code)// now just pass an enum value
findMedicineForDomainCode(INTERVAL_TYPE)

然后,直到那时,在最后一个可能的时刻,您需要实际的封装String代码(“ X520”)–可以从枚举值中提取出它。

希望这有助于定义常量和使用枚举。 对于适当设计的枚举类型,我无法涵盖所有​​其他可能的“有效”用法和OO优势场景,但是希望本文能够防止Java新手陷入所描述的陷阱。

翻译自: https://www.javacodegeeks.com/2016/04/2-rookie-java-constants-enums-pitfalls.html

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

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

相关文章

欧拉函数 euler

O - 找新朋友1、欧拉函数 euler&#xff08;&#xff09;在数论&#xff0c;对正整数n&#xff0c;欧拉函数是 少于或等于n的数中与n 互质 的数的数目。互质&#xff1a;公约数只有 1 的两个整数&#xff0c;称为互质整数。即 最大的公约数也就是 1 euler&#xff08;&#xf…

mysql cluster 外键_Mysql外键约束

Mysql集群创建外键&#xff0c;分为四种约束&#xff1a;no action&#xff0c;restrict&#xff0c;cascade&#xff0c;set null。如果表A的主关键字是表B中的字段&#xff0c;则该字段称为B的外键&#xff0c;表A称为主表&#xff0c;表B称为从表。外键是用来实现参照完整性…

Map类集合遍历

转载于:https://www.cnblogs.com/Neil223/p/7275035.html

小米10解锁bl跳过168_2021年小米红米手机官方解锁BL详细教程+跳过168小时方法合集...

MIUI的解锁风控一直在改动&#xff0c;从之前的无需解锁到现在的168小时绑定限制&#xff0c;时至2021年我们再次重新整理下小米的解锁新规则以及小米解锁常见问题解决方法。比如大家常问的如果跳过168小时解锁时间限制等等小米解锁工具下载&#xff1a;http://miuirom.xiaomi.…

orderby排序慢_使用@OrderBy对Spring Data MongoDB集合进行排序

orderby排序慢这是关于调整和增强Spring Data MongoDB功能的第三篇文章。 这次&#xff0c;我发现我错过了一个JPA功能– OrderBy批注。 OrderBy指定在检索关联值时集合值关联的元素的顺序。 在本文中&#xff0c;我将展示如何使用Spring Data MongoDB使用OrderBy批注实现排序 …

细节取胜的javadoc

今个以为开发经验丰富的同事提出有个改动有问题&#xff0c;希望改一下。老前辈发话&#xff0c;心虚的紧&#xff0c;立即看了下&#xff0c;问题说是我的方法凝视中写了一个 ** doesnt ** 建议改为 does not 说这个生成javadoc有问题。咦。不禁困惑&#xff0c;这个写法我记得…

android实现箭头流程列表_Android开发关于ExpandableListView上下箭头左右显示的笔记...

释放双眼&#xff0c;带上耳机&#xff0c;听听看~&#xff01;关键属性&#xff1a;android:layoutDirection""当安卓的layoutDirection “rtl” 时&#xff0c;箭头在右边显示布局&#xff1a;android:layout_width"match_parent"android:layout_height…

Java A的新本地变量类型推断

对于编程语言迷来说&#xff0c;新闻几乎比这更令人兴奋&#xff01; 现在有一个状态为“候选”的本地变量类型推断的JEP 286 。 以及Brian Goetz的反馈请求&#xff0c;我很想邀请您参加&#xff1a; http : //mail.openjdk.java.net/pipermail/platform-jep-discuss/2016-Ma…

扩展kmp

拓展kmp是对KMP算法的扩展&#xff0c;它解决如下问题&#xff1a; 定义母串S&#xff0c;和字串T&#xff0c;设S的长度为n&#xff0c;T的长度为m&#xff0c;求T与S的每一个后缀的最长公共前缀 其中next数组表示T[i,m-1]和T的最长公共前缀 1 const int maxn100010; //字符…

linux中mysql导入数据库命令_linux下mysql数据库导入导出命令

首先linux 下查看mysql相关目录rootubuntu14:~# whereis mysqlmysql:/usr/bin/mysql—- mysql的运行路径/etc/mysql/usr/lib/mysql—– mysql的安装路径/usr/bin/X11/mysql/usr/share/mysql/usr/share/man/man1/mysql.1.gz此外还有一个&#xff1a;var/lib/mysql ——–mys…

转载:FilenameUtils的工具类

一、概述 这是一个Java操作文件的常用库&#xff0c;是Apache对java的IO包的封装&#xff0c;这里面有两个非常核心的类FilenameUtils跟FileUtils&#xff0c;其中FilenameUtils是对文件名操作的封装;FileUtils是文件封装&#xff0c;开发中对文件的操作&#xff0c;几乎都可以…

mysql 5.5.41 下载_MySQL 5.5.41/5.6.22 发布下载

MySQL 5.5.41 发布下载&#xff0c;此版本更新内容如下&#xff1a;编译改进移除了旧版本 Mac OS X 和 XCode 版本的CMake 工作区 (Bug #18510941)Previously, the MYSQL_MAINTAINER_MODE CMake option was turned on by default for debug builds and off for release builds…

envers_分代缓存和Envers

enversKonrad最近在我们公司的技术室中分享了有关如何完成缓存的有趣文章&#xff0c;这是一个大型的波兰社交网络nk.pl。 算法中的核心概念之一是分代缓存 &#xff08;请参阅此处或此处 &#xff09;。 基本思想是&#xff0c;对于缓存键&#xff0c;您使用一些特定于实体的字…

mysql ado.net 实体数据模型_Visual Studio2017中如何让Entity Framework工具【ADO.NET实体数据模型】支持MYSQL数据源...

熟悉Entity Framework应该对以下图片不陌生&#xff0c;他就是ADO.NET实体数据模型向导&#xff1a;可以将数据库的表自动生成模型类&#xff0c;或者创建Code First的模型文件。但是这个模型向导默认只显示微软自己的SQL Server数据源&#xff0c;如果想使用Mysql数据源&#…

ESP8266学习笔记6:ESP8266规范wifi连接操作

一、前言 我整理了从2015年至今关于ESP8266的学习笔记&#xff0c;梳理出来了开发环境、基础功能、进阶学习三大部分。方便自己和他人。可点此查看&#xff0c;欢迎交流。 之前在笔记4《ESP8266的SmartConfig》http://blog.csdn.net/iotisan/article/details/54849410中&#x…

使用Java 8进行分组,转换和归约

1.简介 在上一篇文章中 &#xff0c;我写了关于如何使用流和分组对对象集合进行分组的文章。 这很有用&#xff0c;但不涵盖特定的用例。 例如&#xff0c;有时我们不仅需要对事物进行分组&#xff0c;还需要将结果转换为更合适的对象。 在这篇文章中&#xff0c;我们将学习如…

rhel6.9 yum安装mysql_在RHEL6.9上安装MySQL5.7

通过YUM方式安装MySQL 5.7Step 1、下载MySQL源wget dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpmyum localinstall mysql-community-release-el6-5.noarch.rpmStep 2、配额yum源并安装MySQLyum-config-manager --disable mysql55-communityyum-config-manager …

正则表达式的\b与\B总结

\b 单词边界&#xff0c;是指单词与符号之间的边界&#xff0c;是一个位置&#xff0c;不是空格或字符。(这里单词可以是中文字符&#xff0c;英文字符&#xff0c;数字&#xff1b;   符号可以是中文符号&#xff0c;英文符号&#xff0c;空格&#xff0c;制表符&#xff0c…

php mysql 取最小值_php – 根据另一个值更新最小值 – MySql

循环遍历数组并检查num是否低于前一个数字.$data数组的示例&#xff1a;$data array([0] > array(id > 9267399, code > 5D:148, num > 64),[1] > array(id > 9267398, code > 5D:186, num > 71));–$array_to_add array();foreach($data AS $val) {…

关于flex,好像有12个属性非常重要

关于Flex&#xff0c;有12个属性非常重要 这几天在学习Flex布局&#xff0c;发现Flex真的好厉害&#xff01; Flex是Flexible Box的缩写&#xff0c;意为“弹性布局”&#xff0c;用来为盒模型提供最大的灵活性。 Flex是它能够简单、完整、响应式的实现各种网页布局&#xff0c…