简体   繁体   English

Java中的常量与属性

[英]Constants vs properties in java

What should be best approach to declare constant value in my java program? 在我的Java程序中声明常数值的最佳方法应该是什么?

Is it the best approach to declare constant value in .properties file or declare that value as static final in nature in a different class? 是在.properties文件中声明常量值还是在不同类中本质上将该值声明为static final的最佳方法?

The answer to the question depends on what you want to accomplish. 问题的答案取决于您要完成的工作。 But there is also a misunderstanding in it. 但是其中也存在误解。

Property files 属性文件

Property files are not meant to be a substitute or an alternative to constants. 属性文件并不旨在替代常量或替代常量。 They are used to store configurable values such as an ip, languages, etc. Loading constants from a file defeats the purpose of a constant. 它们用于存储可配置的值,例如ip,语言等。从文件加载常量会破坏常量的作用。

Constants 常数

The other point is that public static final variables are not a good approach in java, the preferred way is to use an enumerator.(From Effective Java, Item 30: Use enums instead of int constatns ). 另一点是,在Java中, public static final变量不是一个好方法,首选方式是使用枚举器。(摘自Effective Java,第30条:使用枚举代替int constatns )。 An enum will force you to group the constants in a meaningful way, while a class full of random public constants is difficult to manage. enum将迫使您以有意义的方式对常量进行分组,而充满随机public常量的类则难以管理。 An Enum enables you to provide functionalities, for example checks, validation, associate the constant with multiples objects and it can be used in switch statements. Enum使您能够提供功能,例如检查,验证,将该常量与多个对象相关联,并且可以在switch语句中使用。 Enums are also compiled which makes them more efficient and typesafe. Enums也被编译,这使它们更加有效和类型安全。 The book explains the benefits of enums in much greater detail. 这本书更详细地解释了enums的好处。

I think the best approach is to consider whether the value will change depending on some external factor or if it will always remain the same. 我认为最好的方法是考虑该值是否会根据某些外部因素而改变,或者是否始终保持不变。

Property files and global access to the configuration 属性文件和对配置的全局访问

Imagine you have an ip in your property file and you want to be able to access this value from anywhere in your code. 假设您的属性文件中有一个ip,并且希望能够从代码中的任何位置访问此值。 You could just read the value and load it in a public static final variable. 您可以读取值并将其加载到公共静态最终变量中。

If you do this how are you going to control that the value is initialized, or the configured value is correct? 如果执行此操作,将如何控制该值已初始化或配置的值正确? Well in this cases you can use the singleton class pattern (Only one instance of the class can exist), that loads the file and checks that the values are correct. 在这种情况下,您可以使用单例类模式(只能存在该类的一个实例),该模式将加载文件并检查值是否正确。

It can store the value in a private static final variable and enable a getter that can perform the needed checks to ensure that the value is correct. 它可以将值存储在private static final变量中,并启用可以执行所需检查以确保值正确的吸气剂。 This gives you global access to the variables and groups the logic in a single place. 这使您可以全局访问变量并将逻辑分组在一个位置。

Next time you add a value to the file you just need to update this class, and don't need to search in the code where it was and if the checks were correct. 下次向文件中添加值时,只需更新此类,而无需在代码中查找位置以及检查是否正确。

Note 注意

Many people are saying that there is not really a "best way" of doing something. 许多人说做某事并不是真正的“最佳方法”。 I think it's true, but it's also true that if you have access to books like Effetive Java from Joshua Bloch , you should read them and learn from people that have been coding for a really long time. 我认为这是真的,但是如果您可以访问Joshua Bloch的 Effetive Java之类 ,也应该阅读它们并向已经从事编码工作很长时间的人们学习。

Declare them as static final in your code if these values are not environment ie dev,qa,stage specific and doesn't change throughout the lifecycle of your code. 如果这些值不是环境值(例如, dev,qa,stage特定且在代码的整个生命周期中都不变),则将它们声明为代码中的static final。

Downside of constants are that you need to recompile them, if you make some change to them, which will not be the case in property but if its a constant it shouldn't change at all. 常量的缺点是,如果对它们进行了一些更改,则需要重新编译它们,这在属性上不是这种情况,但是如果它是一个常量,则根本不应该更改。

For example :- you might have different credentials for user name "admin" in your dev/qa/stage/prod environment. 例如:-在您的dev / qa / stage / prod环境中,用户名“ admin”可能具有不同的凭据。

Then you can define the admin user like public static final String userId="admin" but password you want to supply from the property file and change it according to the environment in which you running your code. 然后,您可以定义admin用户,例如public static final String userId="admin"但是要从属性文件中提供密码,并根据运行代码的环境对其进行更改。

like 喜欢

dev.properties admin.password = 123456. dev.properties admin.password = 123456。

qa.properties admin.password = abcdef. qa.properties admin.password = abcdef。

And then read it these password from the properties file based on your environment. 然后根据您的环境从属性文件中读取这些密码。

The real answer depends on your requirements. 真正的答案取决于您的要求。 There is no "A is better than B" in the real world. 在现实世界中没有“ A 胜过 B”。 Only: "A is more helpful given requirements x,y,z than B". 仅:“给定要求x,y,z的A比B 更有用 ”。

Therefore you simply have to consider the pros/cons of both approaches in order to decide what is "better" for you. 因此,您只需考虑两种方法的优缺点,即可确定对您而言“更好”的方法。

Advantages of using a constant: 使用常量的优点:

  • compile time safety 编译时间安全
  • compiler support in the first place 首先支持编译器
  • simplicity: there is just a constant. 简单:只有一个常数。 Properties need to come from files, they are all flat strings, they can even be missing . 属性需要来自文件,它们都是扁平字符串,甚至可能会丢失

Disadvantages of constants: 常量的缺点:

  • a bugfix requires you to provide re-compiled classfiles to your customers 一个错误修正需要您向客户提供重新编译的类文件
  • in order to apply the bugfix, either the JVM running your code needs to be stopped; 为了应用该错误修复程序,需要停止运行您的代码的JVM。 or at least your container (like a WAR in Tomcat) needs to be re-deployed. 或者至少需要重新部署您的容器(例如Tomcat中的WAR)。

Properties are just "the other way round". 属性只是“相反”。

In other words: if you want to, you can write a lot of complicated code that allows you to "patch" a running application by enabling it to re-read property information. 换句话说:如果您愿意,您可以编写许多复杂的代码,使您能够通过重新读取属性信息来“修补”正在运行的应用程序。 By doing so, you enable your customer to patch a running application by providing a new property file and triggering some "re-read properties" hook inside the application. 这样,您就可以通过提供新的属性文件并触发应用程序内部的“重新读取属性”钩子来使客户修补正在运行的应用程序。 But make no mistake: implementing a correct, reliable way of doing that is hard . 但是请不要误会: 很难实现正确,可靠的方法。

But unless the above feature is of real value to you, you are most likely better of using plain compile-time constants. 但是,除非上述功能对您具有真正的价值,否则您很可能最好使用纯编译时常量。 You see, "deploying an update" is about giving files to the customer. 您会看到,“部署更新”是关于将文件提供给客户。 It doesn't really matter that much of those files are class files or property files (when we are not talking about "hotfix" requirements). 这些文件中的大部分是类文件还是属性文件(当我们不谈论“修补程序”要求时)并不重要。

I have tried both the ways - File and a public static final class and both work. 我尝试了两种方式-文件和公共静态最终课程,并且都可以工作。 Some points to note though: 但是需要注意以下几点:

  • Declaring in a file would be specifically advantageous if your program needs to be tested/run by various parties who would like to change these constants. 如果您的程序需要由希望更改这些常量的各方面进行测试/运行,则在文件中进行声明特别有利。 In this case, these would be called properties of App/program. 在这种情况下,这些将被称为应用程序/程序的属性。 Spring follows this approach for config. Spring遵循这种配置方法。
  • Declaring them in a class would warrant re-building the App again and again but if these constant don't change or are not required to be accessed by multiple parties, you can very easily pick the static final class approach. 在一个类中声明它们将保证一次又一次地重建App,但是如果这些常量不变或不需要多方访问,则可以很容易地选择静态的最终类方法。 Android declares constants dynamically generated in R.java file as an example. 以Android声明在R.java文件中动态生成的常量为例。 This approach retains control in your hand by the way. 顺便说一下,这种方法将控制权掌握在您手中。 3rs parties using your code would not be able to change these constants. 3rs各方使用您的代码将无法更改这些常量。 The file approach passes control into others' hands for varying them. 文件方法将控制权移交给其他人以改变它们。

Object Mappers would also prefer you to have Bean properties in config files but in Java Annotation sort of lies in between the two and solves it elegantly. 对象映射器还希望您在配置文件中具有Bean属性,但是在Java Annotation中,这介于两者之间,并且可以优雅地解决它。

There is a third option: system properties. 第三种选择:系统属性。 They can be defined in the command line you use to launch you program, and you can also use a constant to ease access them and provide a default value. 可以在用于启动程序的命令行中定义它们,也可以使用常量来简化对它们的访问并提供默认值。

Example: 例:

public static final String HOSTNAME = System.getProperty("my.host-name", "localhost");

It is not always a good idea to provide a default value though. 但是,提供默认值并不总是一个好主意。

That been said, the method you choose will depend on the answer to the question: is the value part of the program, or is it part of the context in which the program is installed. 话虽如此,您选择的方法将取决于问题的答案:是程序的值部分,还是程序安装上下文的一部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM