Java: make constants accessible anywhere - java

I have a Java program that should read configuration parameters from file, Like this:
java -jar myapp.jar --config config.txt ...
Once loaded, these parameters do not change and should be accessible by any class in the program.
Is it possible to make these parameters accessible from any class without explicitly adding them as parameter to constructors and methods? For example, I would like to be able to do this:
public class Main {
public static void main(String[] args){
// This list should be visible by any class
List<String> CONFIGS= readMyConfigsFromFile(args[0]);
...
}
}
public class MyClass(){
public MyClass(){
String thisConf= CONFIGS.get(0); // Do something with this conf param taken from Main.
...
}
}
public class MyOtherClass(){
public MyOtherClass(){
String thisConf= CONFIGS.get(0); // Do something with this conf param taken from Main.
...
}
}
...
Is this possible at all? And is it an advisable set up to do? If not, what is the recommended design to go about it?
(I have read similar questions but I'm still unsure if and how it is possible in the situation I described)

You could use the Singleton pattern.
To model it, I assume you have 2 fields in your configuration: a String and an integer.
public class Config {
private static Config INSTANCE;
private final String field1;
private final int field2;
public Config(String field1, int field2) {
this.field1 = field1;
this.field2 = field2;
}
public String getField1() {
return field1;
}
public int getField2() {
return field2;
}
public static Config getInstance() {
if (INSTANCE == null) {
INSTANCE = loadInstance();
}
return INSTANCE;
}
private static Config loadInstance() {
// read your config from properties
String field1 = ...
int field2 = ...
return new Config(field1, field2);
}
}
And then use Config.getInstance() everywhere you need to get that instance.
Please note that this implementation has a flaw: it may be initialized several times if getInstance() gets called from different theads.
Double-checked locking https://en.wikipedia.org/wiki/Double-checked_locking may be used to overcome this flaw if it is important to you to only initialize once.

This solution, like others, would require a mock object to unit test. But I think it's best as it encapsulates the arguments in an immutable object. This also makes thread-safety a non-issue. Use a HashMap instead of an array to access these by key instead of index if you prefer:
public class Main {
public static void main(String[] args){
new CONFIG(readMyConfigsFromFile(args[0]).toArray());
...
}
public static final class CONFIG {
private final String[] args;
private static final CONFIG instance;
private CONFIG(String[] args) {
this.args = args;
instance = this;
}
public static CONFIG getInstance() {
return CONFIG.instance;
}
public String[] getArgs(){
return Arrays.copy(this.args, this.args.length);
}
public String getArg(int index) {
return args[index];
}
}
To get arguments:
Main.CONFIG.getArgs();

"Is this possible at all?". Yes, it is. You can easily do it with the help of static in java
public class Config {
private static final List<String> config = new ArrayList<String>();
public static void addConfig(String value){
config.add(value);
}
public static List<String> getConfig(){
return config;
}
}
To add values to config you can do
public static void main(String[] args) {
//Read value from file here in some variable say configValue
Config.addConfig(configValue);
}
To access config
public class MyOtherClass(){
public MyOtherClass(){
Config.getConfig().get(0); // Do something with this conf param taken from Main.
...
}
}
Note above code is not thread safe. You can make it thread safe by adding synchronization concepts
Now "And is it an advisable set up to do?". It depends on your requirements. As you mentioned these values does not change runtime then you can use this. But is the requirement we need to enforce that these values "should not change" once initialized then answer will be different and you should use something like Singleton Pattern and modify to make sure you can only read and not write once the object is constructed. Also note that with static methods, like I suggested, testing becomes really hard.

Related

Static field initiation in to unmodifiable set

I have a static field which is initialized by a config property in the static block. My code will run for Fingbugs warning which encounters a warning like mentioned below.
Field is a mutable collection
A mutable collection instance is assigned to a final static field, thus can be changed by malicious code or by accident from another package. Consider wrapping this field into Collections.unmodifiableSet/List/Map/etc. to avoid this vulnerability.
Class A{
private static String uri;
static{
uri= Properties.getpropery("SOME_PROPERTY"); /// Here i am getting the Findbugs warning
}
}
How can I make as Unmodified Set and pass this as String literal in later stages?
I think this is a bug in Findbugs. Try marking the field as private for now, perhaps that helps to solve it. If this does not help fixing it, my gut feeling of it being a bug just got a bit bigger.
As you can tell the exception is somewhat off because it's not a Collection and no changes can be made outside this class because it has the private access modifier and it is a String which are immutable by nature in Java.
Let's take a look at this example;
public class Class1 {
private static String STRING_VALUE = "I'm secure!";
private static List<String> COLLECTION = Arrays.asList("I'm Secure!");
public static void main(String[] args) {
Class2.changeStatic(STRING_VALUE);
System.out.println(STRING_VALUE); // I'm secure!
Class2.changeStatic(COLLECTION);
System.out.println(COLLECTION.get(0)); // I'm unsecure!
}
}
public class Class2 {
public static void changeStatic(String secureString) {
secureString = "I'm unsecure!";
}
public static void changeStatic(List<String> unsecureList) {
unsecureList.set(0, "I'm unsecure!");
}
}
As you can see, there is no way of changing the string value of Class1 outside of the class itself. In the case of a collection this is possible because the elements are held in a mutable container.
Because changing the elements in the Collection is possible outside the class/package they suggest wrapping it in an unmodifiable Collection which do not delegate the modifications to the wrapped list but instead throw an Exception:
public class Class1 {
private static List<String> COLLECTION = Collections.unmodifiableList(Arrays.asList("I'm Secure!"));
public static void main(String[] args) {
Class2.changeStatic(COLLECTION);
}
}
public class Class2 {
public static void changeStatic(List<String> unsecureList) {
unsecureList.set(0, "I'm unsecure!"); // throws a java.lang.UnsupportedOperationException
}
}

Java final class with constant

I must define a class which all it does is hold constants.
public static final String CODE1 = "100";
public static final String CODE2 = "200";
Now I want use these values in other classes. Is it better to use this class as a static class or instantiate it ?
Thanks.
Note : I know enums but in this context, I must use a class.
Just to use the values, you certainly shouldn't instantiate the class. Just because you can access static members as if they were instance members doesn't mean it's a good idea.
If the class really only contains constants - and if you're sure that's a good idea, rather than those constants appearing within classes which are directly related to them - you should make it a final class with a private constructor, so that no-one can pointlessly instantiate it:
public final class Codes {
public static final String CODE1 = "100";
public static final String CODE2 = "200";
// Prevent instantiation
private Codes() {
}
}
Don's answer suggesting using an enum is a very good idea too - it means you can use Code in your API everywhere that you don't need the exact string representation, which prevents you from accidentally using non-code values.
Jons answer is correct, although I want to show you a solution with an enum.
There is a disadvantage in accessing its String value as you have to call Code.CODE1.text() instead of Code.CODE1.
public enum Code {
CODE1("100"), CODE2("200");
private String text;
Codes(String text) {
this.text = text;
}
public String text() {
return text;
}
}
java language spec and JVM spec allow you to do anything you wanted, whether instantiate a class or use final or use other way....
Just use Eclipse and try !
while there is some good practice, Jon Skeet's answer is one good practice.
Java Language is not support global variable
public class ComonFun {
public static final String CODE1 = "100";
public static final String CODE2 = "200";
public static String CODE1(){
return CODE1;
}
public static String CODE2(){
return CODE2;
}
}
implement
public class Main {
public static void main(String[] args) {
System.out.println(ComonFun.CODE1());
System.out.println(ComonFun.CODE2());
}
}
i think that you need simply to declare an interface, you won't need to specify the clause "public static final". and it can be usuable throgh the hall project.
Use them as static, don't go for instantiation.
Even use static import as a benefit.
package coma;
import static coma.ImportStatments.*;
public class UsingClass {
public static void main(String[] args) {
System.out.println(CODE1);
}
}
And the class with final variables would look like this:
package coma;
public class ImportStatments {
public static final String CODE1 = "100";
public static final String CODE2 = "200";
}

How to create configuration class with static variables in java properly?

I created SomeConfig to store there static data. However I try to understand witch options is better (or none of both)
Before I had class SomeConfig written like:
public class SomeConfig {
private static int mValue = 8;
private static String mString = "some String";
public static int getValue() {
return mValue;
}
public static void setValue(int value) {
mValue = value;
}
public static String getTheString() {
return mString;
}
public static void setValue(String theString) {
mString = theString;
}
}
Now I changed it to:
public class SomeConfig {
private static SomeConfig mSomeConfig = new SomeConfig();
private int mValue = 8;
private String mString = "some String";
public static int getValue() {
return mSomeConfig.mValue;
}
public static void setValue(int value) {
mSomeConfig.mValue = value;
}
public static String getTheString() {
return mSomeConfig.mString;
}
public static void setValue(String theString) {
mSomeConfig.mString = theString;
}
}
Generally i changed private variables to non-static but API stays the same.
What is a difference between two options I posted?
Thanks,
If you want only one instance of your SomeConfig to exist in your application then you might want to make it a Singleton class. Refer to this link : link
Your second option seems to be the closest to being a Singleton, you just need to make your Default constructor Private to ensure that no other class can create another instance of SomeConfig.
As per my understanding static variables are class variable and those are not require any object for calling or assigning value .The values for those static variables are remains same over the class.Once you assign a value, all object can access that value.
Hope it will help you.
Generally, I think it's a good practice to avoid static variables and methods, unless there is a real need (I guess common use of static is "utility" type method, or constants etc). If you do not want to instantiate the class multiple times or want to ensure single instance of the configuration, I think implementing it as a singleton would be a better way to go here.
I wouldn't recommend using any of the two for configuration purposes.
The difference between these two are just that one uses an instance to hold the values, the other uses static variables.
You might look into having a configuration class that utilises a ResourceBundle to load the values from a .properties file during initialisation.

Determine which subclass to choose by accessing static variables from the Class object

I am trying to implement an interface in Java to use different types of databases for one application.
My though was to create an abstract class with the common interface and two static variables which are then overwritten by the subclasses. I then wanted to add a Class[] List with the classes of all available subclasses to the abstract class as well as a couple of functions that allow the determination of the correct class to be used.
The goal is to first get a list of all available database types and let the user choose one. Afterwards another function should translate the name (which could be localized) to the IDENTIFIER which is specified in the subclass. Finally a third function allows the instantiation of an object by giving such an IDENTIFIER.
My abstract class would look something like this:
public abstract class DataBase {
public static final IDENTIFIER = "";
public static final NAME = "";
private static final Class[] dbTypes = new Class[]{PostgreSQL.class, MySQL.class};
public static String[] getNameList() {
String[] names = new String[dbTypes.length];
for(int i = 0; i < dbTypes.length; i++){
names[i] = dbTypes[i].NAME; //Cannot access the static variable this way.
}
return names;
}
public static String getIdentifierForName(String name) {
for(int i = 0; i < dbTypes.length; i++){
if(name.equals(dbTypes[i].NAME){
return dbTypes[i].IDENTIFIER;
}
}
return "";
}
public static DataBase getInstanceOf(String identifier) {
for(int i = 0; i < dbTypes.length; i++){
if(identifier.equals(dbTypes[i].IDENTIFIER) {
return dbTypes[i].newInstance();
}
}
return null;
}
}
The Child classes would look something like this:
public class MySQL extends DataBase {
public static final IDENTIFIER = "ab.cde.MySQL";
public static final NAME = "MySQL";
...
}
public class PostgreSQL extends DataBase{
public static final IDENTIFIER = "ab.cde.PostgreSQL";
public static final NAME = "PostgreSQL";
...
}
My problem now is, that I cannot access the static variables from the Class object. Obviously the dbTypes list does not contain any typed classes. I tried changing the type of the Array to Class<? extends DataBase>, but I get an error Cannot create a generic array of Class<? extends DataBase> I also tried checking the classes with isAssignableFrom() and then casting the class, but I was still not able to access the static variables.
For now I have two solutions which are working:
Hardcode all existing subclasses into each function if(PostgreSQL.NAME.equals(name)){...}etc.
However, if I add new subclasses, I only want to have to add them at one point in my implementation.
Instead of using a Class[] array, I can use an array of DataBase[] with instances of each class. However, I would think this is bad practice to instantiate each available DataBase subclass, even though I only need one in the end.
Since I have never done such a thing before I might also be approaching the problem completely wrong. Maybe I am missing the correct way in which something like this is usually done?
Thank you for your help.
There are no "abstract properties" in Java. You have to create two astract methods in the DataBase class, like this:
public abstract class DataBase {
// No "abstract propeties"
public abstract String getDBName();
public abstract String getDBIdentifier();
// etc etc...
}
and then, in each subclass:
public class MySQL extends DataBase {
public static final IDENTIFIER = "ab.cde.MySQL";
public static final NAME = "MySQL";
#Override
public String getDBName() {
return NAME;
}
#Override
public String getDBIdentifier() {
return IDENTIFIER;
}
// etc etc...
}
When using the classes, you can just cast to DataBase (not MySQL or PostgreSQL) and call the two abstract methods.
Therefore, in order to solve your "pick a database class" problem, I would create a configuration file that contains the names of the databases and the corresponding class, and instantiate it with reflection (newInstance()) as needed.
As an alternative, you can use reflection to access the static variables like Nikita's answers suggested, or you can just use the name of the class as the identifier of the database it supports, like this (not tested):
public abstract class DataBase {
private static final Class[] dbTypes = new Class[]{PostgreSQL.class, MySQL.class};
public static Class getDBClass(String type) {
for (Class c : dbTypes) {
if (c.getSimpleName().toLowerCase().equals(type.toLowerCase())) {
return c;
}
}
return null;
}
public static Set<String> getSupportedDB() { // <-- you populate a dropdown menu with this
Set<String> supported = new HashSet<String>();
for (Class c : dbTypes) {
supported.add(c.getSimpleName());
}
return supported;
}
// etc etc...
}
However, I don't like this solution and I would not use it.
You can use reflection to get values for each class:
public static String[] getNameList(){
String[] names = new String[dbTypes.length];
for(int i=0; i<dbTypes.length; i++){
Field f = dbTypes[i].getField("NAME");
names[i] = f.get(null);
}
return names;
}
But it might be slow.
Also I'd suggest to create separate enum DBRegistry that will contain names, identifiers and classes:
public enum DBRegistry {
MYSQL("ab.cde.MySQL", "MySQL", MySQL.class),
POSTGRESQL("ab.cde.PostgreSQL", "PostgreSQL", PostgreSQL.class);
private String name;
private String identifier;
private Class<?> dbClass;
private DBRegistry(String identifier, String name, Class<?> dbClass) {
this.identifier = identifier;
this.name = name;
this.dbClass = dbClass;
}
// Getters...
}
You can iterate on all items in registry using DBRegistry.values
Not tested, but I would suggest something like this. You could register databases by calling DataBase.registerDataBase(new DataBase(...))); which may be invoked from the main file.
public class DataBase {
private final static List<DataBase> INSTANCES = new ArrayList<DataBase>();
private final String identifier;
private final String name;
private final Class<?> dbType;
public DataBase(String identifier, String name, Class<?> dbType) {
this.identifier=identifier.toString();
this.name=name.toString();
this.dbType=dbType;
}
String getIdentifier() {return identifier;}
String getName() {return identifier;}
Class<?> getDbType() {return dbtype;}
public synchronized static void registerDatabase(DataBase database) {
database.getClass();
INSTANCES.add(database);
//may check if already registered and either fail or replace it
}
public synchronized static List<DataBase> getNameList() {
return new ArrayList<DataBase>(INSTANCES);
}
public synchronized static List<String> getNameList() {
List<String> names = new ArrayList<String>(INSTANCES.size());
for (Database db:INSTANCES) names.add(db.getName());
return names;
}
public synchronized static String getIdentifierForName(String name) {
for(DataBase db:INSTANCES){
if(name.equals(db.getName())) return db;
}
return null;
}
public synchronized static DataBase getInstanceOf(String identifier) {
for(DataBase db:INSTANCES){
if(identifier.equals(db.getIdentifier())) return db;
}
return null;
}
}
}
I would advise to keep it simple, never more than necessary to utilize in the actual application. It is easier to extend things than to re-factor code to accomodate for additional complexity. Most of the stuff you mention are merely artefacts of your problem solving, not the actual requirements of your application per se. And it so happens, that a modern object-oriented language has everything you need, and you can implement a good design without reflection and without resorting to static properties and string identifiers.
Remember to rely on the compiler rather than runtime for whatever you know in advance - anything that is known not to change from one application run to another, does not need reflection, because it does not involve runtime variables! I would go for interfaces, classes implementing them, and more importantly the Factory pattern to abstract using these classes:
interface Database
{
void query(String sqlString);
}
class MySQLDatabase implements Database
{
public void query(String sqlString)
{
}
}
class PostgreSQLDatabase implements Database
{
public void query(String sqlString)
{
}
}
class DatabaseFactory
{
Database connectDatabase()
{
/// F.e. return new MySQLDatabase();
}
}
The whole "database abstraction layer" has been done to death already anyway, giving birth to DBA, ODBC and other software stacks that solve your problem. You should let yourself be inspired by these, unless you are sure your particular way of solving this yields advantages that can be proven. If you want to go about this in a professional way, of course. If you want to educate yourself, by all means, use reflection, strings in place of more specific objects, and tight-coupling instead of aggressive modularity.

Reusing class after calling static methods

Suppose I have a class with several static void methods, for example:
class MyClass {
public static void doJob() {
// ...
}
public static void doSmthElse() {
// ...
}
}
how can I modify it to call my static methods like this:
MyClass.doJob().doSmthElse().doJob();
instead of
MyClass.doJob();
MyClass.doSmthElse();
MyClass.doJob();
I know how to do it with non-static methods (just return this), but how to do it with static fields?
Well, you could do this:
// Horrible, don't do it!
class MyClass {
public static MyClass doJob() {
// ...
return null;
}
public static MyClass doSmthElse() {
// ...
return null;
}
}
At that point your code will compile, as Java allows access to static methods "via" references. The fact that you're returning null is irrelevant, because the compiler will only look at the compile-time type of the expression MyClass.doJob() in order to work out which doSmthElse() method to call; the static method will then be called without examining the return value at all.
But please don't do this - it's a really nasty code smell, as your code looks like it's doing one thing when it's actually doing another.
Options:
Just live with your more verbose calls
Extract the static methods into a class where it makes sense for them to be instance methods (this may well improve testability etc as well)
Import the methods statically
Create a larger method in MyClass which calls the three methods one after another.
You can make this class singleton and do
return getInstance();
in every method
You can create a dummy instance of you class and return this. You will use static members of class, but return a reference to regular instance (just for fun, just for code style). But I wouldn't like to use this approach.
class MyClass {
private static int data = 0;
private static MyClass link = null;
public static void doJob() {
// do job with static data such as "data"
return checkMe();
}
public static void doSmthElse() {
// do someting else with static data such as "data"
return checkMe();
}
private MyClass static void checkMe() {
if (link == null) link = new MyClass();
return link;
}
}
It is immpossible because there is no object you can return.

Categories