I am in a situation where I have an enum which has grown huge and gotten out of control on maintenance. I wanted to delegate responsibility to each class. However, there are certain common ones which qualifies as required in more than one class. I was thinking of defining a parent enum with necessary common ones defined and then extend parent enum by respective class's enums to add class specific entry. Java does not support extending enum. Does anyone know an better alternative?
I appreciate any suggestions provided. Thanks!
You should maybe switch to integers, like lots of JavaSE APIs do.
class Constants
{
public static final int COMMON_CONSTANT_1 = 1;
public static final int COMMON_CONSTANT_2 = 2;
....
static final int END_OF_COMMON_CONSTANTS = 127;
}
class AClass
{
public static final int CONSTANT_NEEDED_BY_ACLASS =
Constants.END_OF_COMMON_CONSTANTS + 1;
public static final int ANOTHER_CONSTANT =
CONSTANT_NEEDED_BY_ACLASS + 1;
....
}
This way any class can use the common constants and extend them with custom ones, without interfering with each other.
If your enumeration has only one property , you can move around in a file.properties , otherwise you may create inner enum class in a class to have everything neater
Related
I know there are several similar topics with similar title but I have actually slightly different questions than other topics.
I have designed such a solution which abstract class implements and interface, and in the constructor it calls default method of interface to initialize a map.
Here is my interface:
public interface ICalculator{
int VALUE_OF_X= 10;
int VALUE_OF_Y= 50;
int VALUE_OF_Z = 70;
Map<String, Integer> CHAR_VAL_MAP = new HashMap<String, Integer>(7);
default void initValueMap(){
CHAR_VAL_MAP.put("X", VALUE_OF_X);
CHAR_VAL_MAP.put("Y", VALUE_OF_Y);
CHAR_VAL_MAP.put("Z", VALUE_OF_Z);
}
public int calculate(final String inStr);
}
And created an abstract class:
public abstract class AbstractCalculator implements ICalculator{
protected AbstractCalculator(){
initValueMap();
}
}
My idea was here to ensure that initValueMap method is called implicitly by the abstract class.
And the concreate class which extend abstract class is:
public class MyCalculator extends AbstractCalculator{
public int calculate(final String romanNumberStr){
// some logic code
}
}
I have basically two question:
1) Is there any design problem or wrong usage of OOP concepts ?
2) In C++. using const for the parameter is good programming behaviour. But in java word, it is not so common. Is it bad to use final in method parameters?
You are over complicating things. Java 9 added some nice of() methods to the Collections utility class. You can use those to create a map filled with values without the need to call an extra init method. Then you pass that map instance to new HashMap() to get that data into a modifiable map instance. And with older java, you can always write a method that creates and returns a prefilled map. There is no need to do creation and filling like you do (in separate pieces of code).
For the record: you understand that all fields of an interface are static by default and thus shared between all code using them?!
Regarding final, there are quite some differences to const from C++. The only thing that a final parameter gives you is checking that prevents you from inadvertently writing to a parameter. It can be useful to have that, but most people simply don't use it because they add such little gain, but make code quite harder to read.
There are a few ways to ensure that calculate is only called after the map is fully initialized. One way is to declare and initialize it in the interface directly:
public interface ICalculator {
int VALUE_OF_X = 10;
int VALUE_OF_Y = 50;
int VALUE_OF_Z = 70;
Map<String, Integer> CHAR_VAL_MAP = initValueMap();
static Map<String, Integer> initValueMap() {
Map<String, Integer> map = new HashMap<String, Integer>(7);
map.put("X", VALUE_OF_X);
map.put("Y", VALUE_OF_Y);
map.put("Z", VALUE_OF_Z);
return map;
}
public int calculate(final String inStr);
}
This may be preferred because static data is being initialized statically, where it is declared (though most of us don't particularly like stuffing interfaces with this kind of code).
If you want to call this initialization code in the abstract class, you can still use a static block:
public abstract class AbstractCalculator implements ICalculator {
static {
ICalculator.initValueMap();
}
}
But the simplest is perhaps to go with Map.of as suggested in GhostCat's answer, unless your Java runtime is older than 9.
I've few common constants which are used by multiple classes.
What's the most effective way to design in this case:
Should I redefine the constants in each class?
Or should I separate such constants in a public class, and use the constants (in separate class) within each class?
Or is there any other better approach?
Note:- I'm looking for best OO technique which would be applicable for this.
Constants should be strictly related to some type, they shouldn't just "exist". A Constants class may seem convenient, but it will soon become unmaintainable, not to mention many consider it an antipattern.
It's hard to suggest improvements without seeing your code, but it seems like you need to rethink your design if you find yourself needing the same constants defined in a few different classes outside of the scope of a type.
Providing a Constant Util class is the cleanest way.
class ConstantUtil {
public static final int MAX_SIZE = 1<<10;
}
The typical folder heirarchy is like this
com.example.util.ConstantUtil
If the contants are dedicated to an api define them there. E.g.
public interface TaskService {
public static final int PRIORITY_LOW = -1;
public static final int PRIORITY_NORMAL = 0;
public static final int PRIORITY_HIGH = 1;
public void schedule(Task task, int priority);
}
If constants are not releated to a single api define a constants interface. E.g. javax.swing.WindowConstants.
Or is there any other better approach? Note:- I'm looking for best OO technique which would be applicable for this.
java
This brings us back to the question how constants are used. Most times they are used to write conditional code. E.g.
public class TaskServiceImpl implements TaskService {
private List<Task> lowPriority = new ArrayList<Task>();
private List<Task> normalPriority = new ArrayList<Task>();
private List<Task> highPriority = new ArrayList<Task>();
public void schedule(Task task, int priority){
if(priority == PRIORITY_HIGH ){
highPriority.add(task);
} else if(priority == PRIORITY_LOW ){
lowPriority.add(task);
} else if(priority == PRIORITY_NORMAL){
normalPriority.add(task);
} else {
....
}
}
}
In this case find out what the purpose of the constants is. In the example above the purpose is to group the tasks or if you think further to order them for execution. Move that logic to an own class. E.g. Introduce a Priority class that might implement Compareable ;)
You can also take a look at my blog about type-switches https://www.link-intersystems.com/blog/2015/12/03/enums-as-type-discriminator-anti-pattern/.
It is about enum misuse, but it also applies to constants.
You can try to create a class which contains all the constants(i.e, the second approach).
For example:
classname : MyConstantsClass.java
public static final String SOME_CONSTANT="value";
and then use it like
MyConstantsClass.SOME_CONSTANT
As some have suggested to use interface to create constants then I don't think that it would be a good choice. As using interface to create constants have certain disadvantages as well:
The usage of an interface does not allow to implement a mechanism for converting the constants to a visible/human readable
representation.
If the constants are an "implementation detail", an interface might not be the natural place for the value (CodeSmells, ListenToTheCode).
Due to Java compiler optimization, complete code recompilation of all classes using the constants is necessary if a constant changes.
Just changing the interface and recompiling it does not work (this
is, however the case with all constants defined as 'static final')
Please refer:
Interfaces For Defining Constants
Interface for constants
Class for constants
Constant class :
interface Constants {
int CONSTANT_ONE = 0;
int CONSTANT_TWO = 1;
int CONSTANT_THREE = 2;
String BASE_PATH = "YourPath";
}
And usage:
if (someValue == Constants.CONSTANT_ONE) {
}
Edit:
In most cases use interface instead of class if there is no need to implement this interface by some class, then it is no need to add this public static final, because by default it is public static final so your code looks more clean.
Design a class like AppUtil.java and and define your constants public static final like below:
public class AppUtil
{
public static final String IMAGE_STATUS="0";
}
and when you want to use variable use . like below:
AppUtil.IMAGE_STATUS
This question has been bothering me forever. I can wait to hear the responses. I see this too often
public interface Istuff
{
public static final int STATE_B = 4;
public static final int STATE_L = 5;
public static final int STATE_U = 6;
}
and also this one
public class MyStuffConstants
{
public static final String STATUS = "STATUS";
public static final String RUNNING = "RUNNING";
}
I would say Enum. as their sole purpose is to represent fixed set of constants.
Simple Example:
enum Season { WINTER, SPRING, SUMMER, FALL }
You should use enum for that. It's too powerful not to use it.
Don't use interfaces for that. It gets very messy as soon as you have many interfaces (which may come from interfaces extending other interfaces) : you need then to precise in what interfaces to pick the constants which nullifies the benefits of defining the constants in an interface.
The clean solution is to have a non instanciable class for that. Of course, when an enumeration is applicable (that is, the values are different possible values in the same semantic field), you should use an enum. But don't use an enum for this kind of constant :
public final static int DEFAULT_WIDTH = 666;
If you can also associate arbitrary data with your enum constants by adding a constructor:
public enum Season {
WINTER(1, 15), SPRING(2, 92), SUMMER(3, 40), FALL(50, 9);
private final int foo;
private final int bar;
Season(int foo, int bar) {
this.foo = foo;
this.bar = bar;
}
public int getFoo() {
return foo;
}
public int getBar() {
return bar;
}
}
For the IStuff example I think enums is kind of awkward if you don't actually need the whole exclusive ordering bit - you'll end up basically creating a class for wrapping an integer.
The MyStuffs example makes sense to make an enum out of, as long as the name of the constant works for you.
It comes down to who will be using the constants - sometimes it makes sense to use constants internally in a class (avoiding magic values). In that case "private static final * *;" works fine.
If you want the constants to be useful as part of an API then sure do constants as in iStuff (btw you can lose the "public static final" bit, which is default when putting them like that in an interface).
Edit: and if you don't have an interface to begin with, and you have constants that clearly belong to a specific, even though the constants need to be public, I don't see the need to create a separate interface just to have somewhere to put the constants. If however the constants will be used in two or more classes/apis and belong in one place more than another, then sure why not put the constants in a separate interface.
I think the concept of constants is too complex to be answered by a general "do this" statement.
I'm trying to figure out the best way to create a class whose sole purpose is to be a container for global static variables. Here's some pseudocode for a simple example of what I mean...
public class Symbols {
public static final String ALPHA = "alpha";
public static final String BETA = "beta";
/* ...and so on for a bunch of these */
}
I don't need constructors or methods. I just need to be able to access these "symbols" from everywhere simply by calling: Symbols.ALPHA;
I DO need the actual value of the String, so I can't use an enum type. What would be the best way to accomplish this?
Well, it's not clear what else you need beyond the code you've already given - other than maybe making the class final and giving it a private constructor.
However, in order to avoid accidentally using an inappropriate value, I suspect you would be better off making this an enum, like this:
public enum Symbol {
ALPHA("alpha"),
BETA("beta");
private final String value;
private Symbol(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
That way:
You can't accidentally use Symbol.ALPHA where you're really just expecting a string
You can't accidentally use a string where you're really expecting a symbol
You can still easily get the string value associated with a symbol
You can switch on the different symbol values if you need to
You can do that using an interface. No need to construct, values are public, static and final, and can obviously be strings. Such an interface would look similar to your class:
public interface Symbols {
public static final String ALPHA = "alpha";
public static final String BETA = "beta";
/* and so on */
}
You can access the fields directly from everywhere in your code (given it's public) as Symbols.ALPHA etc.
Or, you can use an enum even though you want strings - ALPHA.toString() will return "ALPHA" (and if you want a slightly different string, you can override toString())
Are these configuration parameters or simply "constants" which don't change no matter what? For the former, I'd rather create a configuration class and instantiate it with different values for each environment. Then simply use dependency injection to inject these configurations in different classes. If your requirement is the latter or you are not using DI (Spring/Guice), static classes/interfaces are good to go.
How and where should we use a Static modifier for:
1. Field and
2. Method?
For example in java.lang.Math class, the fields methods like abs(), atan(), cos() etc are static, i.e. they can be accessed as: Math.abs()
But why is it a good practice?
Say, I don't keep it static and create an object of the class and access it, which anyways I can, I will just get a warning that, you are trying to access a static method in a non static way (as pointed out by #duffymo, not in case of Math class).
UPDATE 1:
So, utility method, should be static, i.e. whose work is only dependent on the method parameters. So, for example, can the method updateString(String inputQuery, String highlightDoc) should have been a static method in this question?
You can think of a 'static' method or field as if it were declared outside the class definition. In other words
There is only one 'copy' of a static field/method.
Static fields/methods cannot access non-static fields/methods.
There are several instances where you would want to make something static.
The canonical example for a field is to make a static integer field which keeps a count across all instances (objects) of a class. Additionally, singleton objects, for example, also typically employ the static modifier.
Similarly, static methods can be used to perform 'utility' jobs for which all the required dependencies are passed in as parameters to the method - you cannot reference the 'this' keyword inside of a static method.
In C#, you can also have static classes which, as you might guess, contain only static members:
public static class MyContainer
{
private static int _myStatic;
public static void PrintMe(string someString)
{
Console.Out.WriteLine(someString);
_myStatic++;
}
public static int PrintedInstances()
{
return _myStatic;
}
}
Static uses less memory since it exists only once per Classloader.
To have methods static may save some time, beacuse you do not have to create an object first so you can call a function. You can/should use static methods when they stand pretty much on their own (ie. Math.abs(X) - there really is no object the function needs.) Basically its a convenience thing (at least as far as I see it - others might and will disagree :P)
Static fields should really be used with caution. There are quite a few patterns that need static fields... but the basics first:
a static field exists only once. So if you have a simple class (kinda pseudocode):
class Simple {
static int a;
int b;
}
and now you make objects with:
Simple myA = new Simple();
Simple myB = new Simple();
myA.a = 1;
myA.b = 2;
myB.a = 3;
myB.b = 4;
System.out.println(myA.a + myA.b + myB.a + myB.b);
you will get 3234 - because by setting myB.a you actually overwrite myA.a as well because a is static. It exists in one place in memory.
You normally want to avoid this because really weird things might happen. But if you google for example for Factory Pattern you will see that there are actually quite useful uses for this behaviour.
Hope that clears it up a little.
Try taking a look at this post, it also gives some examples of when to and when not to use static and final modifiers.
Most of the posts above are similar, but this post might offer some other insight. When to use Static Modifiers
Usually when the method only depends on the function parameters and not on the internal state of the object it's a static method (with singletone being the only exception). I can't imagine where static fields are really used (they're the same as global variables which should be avoided).
Like in your example the math functions only depend on the parameters.
For a field you should keep it static if you want all instances of a given class to have access to its value. For example if I have
public static int age = 25;
Then any instance of the class can get or set the value of age with all pointing to the same value. If you do make something static you run the risk of having two instances overwriting each others values and possibly causing problems.
The reason to create static methods is mostly for utility function where all the required data for the method is passed in and you do not want to take the over head of creating an instance of the class each time you want to call the method.
You can't instantiate an instance of java.lang.Math; there isn't a public constructor.
Try it:
public class MathTest
{
public static void main(String [] args)
{
Math math = new Math();
System.out.println("math.sqrt(2) = " + math.sqrt(2));
}
}
Here's what you'll get:
C:\Documents and Settings\Michael\My Documents\MathTest.java:5: Math() has private access in java.lang.Math
Math math = new Math();
^
1 error
Tool completed with exit code 1
class StaticModifier
{
{
System.out.println("Within init block");//third
}
public StaticModifier()
{
System.out.println("Within Constructor");//fourth
}
public static void main(String arr[])
{
System.out.println("Within Main:");//second
//StaticModifier obj=new StaticModifier();
}
static
{
System.out.print("Within static block");//first
}
}