Java中的常量:如何避免反模式

简介:

在应用中,我们往往需要一个常量文件,用于存储被多个地方引用的共享常量。在设计应用时,我也遇到了类似的情况,很多地方都需要各种各样的常量。

我确定需要一个单独的文件来存储这些静态公共常量。但是我不是特别确定是应该用接口还是类(枚举不满足我的需求)。我有两种选择:

使用接口,如:

1

2

3

4

5

package one;

public interface Constants {

String NAME="name1";

int MAX_VAL=25;

}

1

2

3

4

5

package two;

public class Constants {

public static final String NAME="name1";

public static final int MAX_VAL=25;

}

我的观点是使用接口。因为接口会自动将成员变量设置为静态的(static)、不可变的(final),这一点可以防止某些情况下错误地添加新的常量。这也使得代码看起来更简单和清晰。

同时,一个的简单测试显示,同样的接口(字节码文件)占用的空间是209个字节(ubuntu 14.04机器上),而类(字节码文件)占用的空间是366个字节(同样的操作系统)。更少的字节码文件意味着加载和维护的成本更低。此外,JVM 加载接口的时候,不需要担心类提供的额外特征(如重载、方法的动态绑定等),因此加载更快。

这看起来非常好,但是这是一个典型反模式的例子。虽然使用接口来保存常量看起很有帮助,但是这给应用后期的扩展留下一个漏洞。

假设存在在一个类,紧密】依赖于这些常量。开发者在该类中写满了通过接口对常量的引用。如:

1

packagename.Constant.CONSTANT_NAME

所以,为了“清理”这段代码,他可能想实现该接口,这样他就不需要到处写“packagename.Constants”,所有的常量可以直接访问。

但是,一旦他实现了该接口,所有的常量就都变成“契约”(因为所有的常量都是公共的、静态的)的一部分。这导致为这个类增加了不必要的常量。这会动摇整个基础,并引起混乱。Java 中没有一种方式可以阻止类实现接口。

而另一种方式,我们可以将类设置为final,这样就不能扩展。甚至,我们可以将构造器设置为私有的,以防止对这个类实例化,这样就永远不会破坏约定。此外,如果一个特殊的常量在同一个类中被多次使用,则开发者可以使用静态引入。

所有对于常量类,比较好的设计应该是:

1

2

3

4

5

6

7

package three;

//make the class non-extendable by adding final 增加final关键字来避免继承

public final class Constants {

//Hide the constructor 隐藏构造器

private Constants(){}

public static String NAME="name";

}

静态引入的例子:

1

2

3

4

5

6

import static three.Constants.NAME;

public class UseConstants {

  public static void main(String[] args) {

      System.out.println("the value of constants is"+NAME);

  }

}

这个设计问题也称为接口常量反模式(Constant Interface Anti-pattern)。


作者:paddx

来源:51CTO

相关文章
|
10月前
|
Java 应用服务中间件 Docker
java-web部署模式概述
本文总结了现代 Web 开发中 Spring Boot HTTP 接口服务的常见部署模式,包括 Servlet 与 Reactive 模型、内置与外置容器、物理机 / 容器 / 云环境部署及单体与微服务架构,帮助开发者根据实际场景选择合适的方案。
554 25
|
供应链 JavaScript 前端开发
Java基于SaaS模式多租户ERP系统源码
ERP,全称 Enterprise Resource Planning 即企业资源计划。是一种集成化的管理软件系统,它通过信息技术手段,将企业的各个业务流程和资源管理进行整合,以提高企业的运营效率和管理水平,它是一种先进的企业管理理念和信息化管理系统。 适用于小微企业的 SaaS模式多租户ERP管理系统, 采用最新的技术栈开发, 让企业简单上云。专注于小微企业的应用需求,如企业基本的进销存、询价,报价, 采购、销售、MRP生产制造、品质管理、仓库库存管理、财务应收付款, OA办公单据、CRM等。
853 23
|
10月前
|
存储 Java 大数据
Java 大视界 -- Java 大数据在智能家居能源消耗模式分析与节能策略制定中的应用(198)
简介:本文探讨Java大数据技术在智能家居能源消耗分析与节能策略中的应用。通过数据采集、存储与智能分析,构建能耗模型,挖掘用电模式,制定设备调度策略,实现节能目标。结合实际案例,展示Java大数据在智能家居节能中的关键作用。
|
Java
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
225 24
|
Java 程序员 容器
Java中的变量和常量:数据的‘小盒子’和‘铁盒子’有啥不一样?
在Java中,变量是一个可以随时改变的数据容器,类似于一个可以反复打开的小盒子。定义变量时需指定数据类型和名称。例如:`int age = 25;` 表示定义一个整数类型的变量 `age`,初始值为25。 常量则是不可改变的数据容器,类似于一个锁死的铁盒子,定义时使用 `final` 关键字。例如:`final int MAX_SPEED = 120;` 表示定义一个名为 `MAX_SPEED` 的常量,值为120,且不能修改。 变量和常量的主要区别在于变量的数据可以随时修改,而常量的数据一旦确定就不能改变。常量主要用于防止意外修改、提高代码可读性和便于维护。
275 3
|
安全 Java
java BigDecimal 的赋值一个常量
在 Java 中,`BigDecimal` 是一个用于精确计算的类,特别适合处理需要高精度和小数点运算的场景。如果你需要给 `BigDecimal` 赋值一个常量,可以使用其静态方法 `valueOf` 或者直接通过字符串构造函数。 以下是几种常见的方法来给 `BigDecimal` 赋值一个常量: ### 使用 `BigDecimal.valueOf` 这是推荐的方式,因为它可以避免潜在的精度问题。 ```java import java.math.BigDecimal; public class BigDecimalExample { public static void
475 4
|
设计模式 XML 存储
【二】设计模式~~~创建型模式~~~工厂方法模式(Java)
文章详细介绍了工厂方法模式(Factory Method Pattern),这是一种创建型设计模式,用于将对象的创建过程委托给多个工厂子类中的某一个,以实现对象创建的封装和扩展性。文章通过日志记录器的实例,展示了工厂方法模式的结构、角色、时序图、代码实现、优点、缺点以及适用环境,并探讨了如何通过配置文件和Java反射机制实现工厂的动态创建。
【二】设计模式~~~创建型模式~~~工厂方法模式(Java)
|
Java
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
306 5
|
存储 Java 开发者
【Java新纪元启航】JDK 22:解锁未命名变量与模式,让代码更简洁,思维更自由!
【9月更文挑战第7天】JDK 22带来的未命名变量与模式匹配的结合,是Java编程语言发展历程中的一个重要里程碑。它不仅简化了代码,提高了开发效率,更重要的是,它激发了我们对Java编程的新思考,让我们有机会以更加自由、更加创造性的方式解决问题。随着Java生态系统的不断演进,我们有理由相信,未来的Java将更加灵活、更加强大,为开发者们提供更加广阔的舞台。让我们携手并进,共同迎接Java新纪元的到来!
351 11
|
消息中间件 Java
【实战揭秘】如何运用Java发布-订阅模式,打造高效响应式天气预报App?
【8月更文挑战第30天】发布-订阅模式是一种消息通信模型,发送者将消息发布到公共队列,接收者自行订阅并处理。此模式降低了对象间的耦合度,使系统更灵活、可扩展。例如,在天气预报应用中,`WeatherEventPublisher` 类作为发布者收集天气数据并通知订阅者(如 `TemperatureDisplay` 和 `HumidityDisplay`),实现组件间的解耦和动态更新。这种方式适用于事件驱动的应用,提高了系统的扩展性和可维护性。
379 2