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.
Related
Im curious if there exists an abbreviation form for getter/setter methods of objects
SimpleObject oSimple = new SimpleObject();
oSimple.setCounterValue(oSimple.getCounterValue() + 1);
like one for simple datatypes
int counter = 0;
counter += 2;
Info
The getter/setter methods are required.
Addition
If there isn't a language feature thats support the idea, what is the most convenient way to deal with that in context of good and clean code?
You have C# background I can imagine ;-)
It's not possible in Java (apart from not-quite-the-same solutions such as having public properties etc). Same as operator overloading, which could also have solved your issue.
However have a look at http://www.eclipse.org/xtend/ though, it's a JVM language similar to Java that supports operator overloading and some other nifty things.
As geert3 said there is no shortcut to setters/getters in Java without accessing the property directly.
In your case your SimpleObject-class should just have a method increaseCounter() and maybe increaseCounterBy(int add) (or simply add(int a)).
For this case, I create annotation
/**
* Annotation for PropertiesContainer class (that has field without getter and setter)
* This class look like as class with Properties in C#
*
*/
public #interface PropertiesContainer {
}
Add add to any class (annotation shows that isn't error)
#PropertiesContainer // class without getter and setter
public Class SomeObject{
public int counter;
}
And just use:
oSimple.counter++;
If the value doesn't have to be checked for any wrong values / execute code when setting it, you could solve it by just referencing the variable directly:
public Class SomeObject{
public int value;
}
public Class Main{
public static void main(String[] args){
SomeObject o = new SomeObject();
o.value += 1;
}
}
If the example you gave is all you want to do (increment and assign an index for a new object every time you make one) then a common practice is use a static variable as a counter and a local variable for the specific index.
class SomeObject {
static int objectCounter;
private int index;
public SomeObject() {
index = objectCounter++;
// additional constructor code
}
}
If you wish to add a number to a variable, I'd consider making a separate method that does just that rather than trying to rewrite set(), or if it makes sense, make it part of the code for the set().
All:
I am on first day reading team's code(the one wrote this left...):
There is one enum definition confused me so much:
/**
* Enum defines the processing stages and the order
*
*/
public enum ProcessStage {
/*
* Individual stages in the process.
* Order of processing is based on the order of listing.
*/
EXTRACT("Extraction", "EXTRACTED", "EXTRACTION_FAILED"),
ROUTE("Routing", "ROUTED", "ROUTE_FAILED"),
PUBLISH("Publishing", "PUBLISHED", "PUBLISH_FAILED");
private String detailedName;
private String successState;
private String failedState;
private ProcessStage(String detailedName, String successState, String failedState) {
this.detailedName = detailedName;
this.successState = successState;
this.failedState = failedState;
}
public String getSuccessState() {
return successState;
}
public String getFailedState() {
return failedState;
}
/**
* Factory method to provide the ProcessStage from its success or failed state value stored in DB.
* #param state
* #return ProcessStage
*/
public static ProcessStage getProcessStage(String state) {
for(ProcessStage ps: ProcessStage.values()) {
if(ps.getSuccessState().equals(state) || ps.getFailedState().equals(state)) {
return ps;
}
}
return null;
}
public String toString() {
return detailedName;
}
}
I wonder if anyone give me some simple introduction about how to read this(like what kinda syntax it uses)? The most confused part is:
EXTRACT("Extraction", "EXTRACTED", "EXTRACTION_FAILED"),
ROUTE("Routing", "ROUTED", "ROUTE_FAILED"),
PUBLISH("Publishing", "PUBLISHED", "PUBLISH_FAILED");
I do not quite understand what this means and how to use this.
And why there are a lot of methods defined inside it and how to use method with a enum variable?
Thanks
Enum
The enum declaration defines a class (called an enum type). The enum
class body can include methods and other fields. The compiler
automatically adds some special methods when it creates an enum.
enums are special type of class. Instead of creating singleton pattern using regular class or to create constants, like WeekDays, we can use enum in such places. Here
EXTRACT("Extraction", "EXTRACTED", "EXTRACTION_FAILED"),
Here EXTRACT is an enum constant meaning it is an instance of the classProcessStage and also all other enum constants(ROUTE, PUBLISH). All costants of enum are unique objects, meaning they are singleton instance created in the jvm and enum makes sure the instances are unique. You need not to put additional effort to create singleton pattern.
The above code is not only declaration, it is also calling the constructor with three String parameters to create the instance.
private ProcessStage(String detailedName, String successState, String failedState) {
this.detailedName = detailedName;
this.successState = successState;
this.failedState = failedState;
}
why there are a lot of methods defined inside it?
Since it is also a class, it can have methods like any other classes. But the restriction is, it cannot be inherited, because internally enum extens the class Enum<E extends Enum<E>> class.
how to use method with a enum variable?
EXTRACT.getFailedState() //returns "EXTRACTION_FAILED"
Keep in mind, without seeing more of the code, I can't be exactly sure what this particular enum is being used for.
So, Let's say we have a method somewhere, where a process is passed through.
public void doSomething(Process process) {}
Now, let's assume that the purpose of this method is to check the status of the process and then do some logic based upon that result. This would entail doing something like the following
public void doSomething(Process process) {
if(ProcessStage.EXTRACT.equals(process.getStage()) {
//do something here...you will have access to the methods within
//the enum
}
}
Without knowing more, this is all I can give you. I hope this gives you a slightly better understanding of what that enum is doing
I'm working with Spring 4, and I have an enum declared like...
public static enum MY_ENUMS {
A(1, "enum1"),
B(2, "enum2");
private final int key;
private final String name;
MY_ENUMS(int key, String name) {
this.key = key;
this.name = name;
}
public String getName() {
return this.name;
}
public int getIndex() {
return this.key;
}
}
Then, from my component I'm attempting to do something like...
// #Named is the equivalent of #Component for this use case
// Making name public and trying this also does not work:
// #Named(MY_ENUMS.A.name)
#Named(MY_ENUMS.A.getName())
public class ServiceImplA implements IService {
#Override
public Object interfaceMethod() {
// Some code specific to ServiceImplA here....
}
}
This doesn't build and I know WHY this doesn't build. Basically, MY_ENUMS.A.getName() doesn't appear to the compilier as being constant, which would mean it cannot be used here. But the point of enums is that they allow you a method to declare constants in a useful way. So, with that being said, is there a way I can specify my component's name by referring to the value in the enum?
I feel this should be possible given that enums are a special case/implementation of constant values but I can't think of a way to work around Spring (or maybe Java's) expectation that the value of the annotation be a straight up constant.
is there a way I can specify my component's name by referring to the
value in the enum?
No, there is not. If the annotation attribute was expecting an enum, you could just use the enum. But invoking a method does not resolve to a constant expression. You might think that you could make the field public and access it directly
#Named(MY_ENUMS.A.name)
but that won't work either because MY_ENUMS.A.name isn't a constant expression either.
The actual reason theat isn't a constant expression is that an enum constant is basically a variable. There is such a thing as a constant variable, which is a constant expression. For a variable to be a constant variable, it needs to be final and initialized with a constant expression. An enum constant is final but is not initialized with a constant expression. Basically an enum constant is compiled to
public static final YourEnum constant = new YourEnum();
The new YourEnum() expression is not a constant expression. And therefore the constant is not a constant variable and can't be used to resolve a String variable which it may be a constant variable.
Consider I am having the following enum class,
public enum Sample {
READ,
WRITE
}
and in the following class I am trying to test the enum class,
public class SampleTest {
public static void main(String[] args) {
testEnumSample(Sample.READ);
}
public static void testEnumSample(Sample sample) {
System.out.println(sample);
}
}
Here I am specifying Sample.READ then passing it as the parameter to the method testEnumSample.
Instead if we want to instantiate the enum class and pass it as parameter what we need to do?
Here I need to specifying Sample.READ to pass it as parameter. Instead if we want to instantiate the enum class and pass it as parameter what we need to do?
What would "instantiate the enum class" even mean? The point of an enum is that there are a fixed set of values - you can't create more later. If you want to do so, you shouldn't be using an enum.
There are other ways of getting enum values though. For example, you could get the first-declared value:
testEnumSample(Sample.values()[0]);
or perhaps pass in the name and use Sample.valueOf:
testEnumSample("READ");
...
Sample sample = Sample.valueOf(sampleName);
If you explained what you were trying to achieve, it would make it easier to help you.
Internally, enums will be translated to something like this
class Sample extends Enum {
public static final Sample READ = new Sample("READ", 0);
public static final Sample WRITE = new Sample("WRITE", 1);
private Sample(String s, int i)
{
super(s, i);
}
// More methods, e.g. getter
}
They should not and cannot be initialized.
Enums doesn't support public constructors and hence, cannot be instantiated. Enums are for when you have a fixed set of related constants. Exactly one instance will be created for each enum constant.
Check my answer in another post.
There are 2 ways:
Use Enum.valueOf() static function, then cast it into your enum type.
Enum v = Enum.valueOf(TheEnumClass, valueInString);
Use class.getEnumConstants() function to get the list of the enum constants, and loop this list and get.
Plugins[] plugins = Plugins.class.getEnumConstants();
for (Plugins plugin: plugins) {
// use plugin.name() to get name and compare
}
You cannot create a new enum instance. Otherwise it won't be an enum.
You can reference an already existing enum. As in your example
Sample sample = Sample.READ;
The elements within an Enum are objects that are instances of the class.
You no need to create an object of Enum.
Here is a similar issue
Refer this
You cannot instantiate an Enum, thats the whole point of having an Enum.
For example you would use enum when defining properties of some thing which would never change like:
enum TrafficLight {
RED("stop"),
YELLOW("look"),
GREEN("go")
}
private string value;
private TrafficLight(String value) {
this.value = value;
}
public getValue() {
return value;
}
Now if you want to get the value of the enum, you can use valueOf method of enums. The static methods valueOf() and values() are created at compile time and do not appear in source code. They do appear in Javadoc, though;
TrafficLight trafficLight = TrafficLight.valueOf("RED")
String value = trafficLight.getValue();
If you do TrafficLight.valueOf("XYZ"), it will throw an IllegalArgumentException
I'm answering to the first question. You can easily do it like this:
public static void main(String[] args) {
Sample.READ.testEnumSample();
}
public enum Sample {
READ,
WRITE;
public void testEnumSample() {
System.out.println(this);
}
}
Fetch a good book on Java Basics and read it.
Anyways, Enums in java are classes with fixed number of objects and objects are defined by its attributes.
Again, you can read something about it here
I am considering a design in Java where I want a string object but with more 'type-safety' than just being of class String. This because I have a number of 'POJO' objects for Hibernate, representing my database tables. Each of these classes has a large number of public static fields representing the properties of the class, I.e.:
public class PersistantBean {
public static String PROP_FIELD_COLUMN_ONE="columnOne";
public static String PROP_FIELD_COLUMN_TWO="columnTwo";
// [...]
These properties are used when we need to access a property in a generic way, e.g. for code I am currently writing .parseAndSet(PROP_FIELD_PRICE,"£3.00").
I would like to be able to add a stronger type to the PROP_FIELD_... fields so that I could write
public class PersistantBean {
public static PropertyName PROP_FIELD_COLUMN_ONE="columnOne";
public static PropertyName PROP_FIELD_COLUMN_TWO="columnTwo";
// [...]
with minimal changes to other parts of the project,
so that parseAndSet would look like:
public void parseAndSet(PropertyName prop, String priceToParse)
Essentially, I would like PropertyName to be a type that is like String in everyway apart from the compiler would error if I tried to put a String where a PropertyName was expected, is any design pattern like this possible.
(I am shying away from Enums, although now I mention it, Enums may be the way to go.)
For Java 1.5 and above, just use an enum type.
For Java 1.4 and below, use the typesafe enum pattern. E.g.
public class Suit {
private final String name;
public static final Suit CLUBS =new Suit("clubs");
public static final Suit DIAMONDS =new Suit("diamonds");
public static final Suit HEARTS =new Suit("hearts");
public static final Suit SPADES =new Suit("spades");
private Suit(String name){
this.name =name;
}
public String toString(){
return name;
}
}
enum(enumeration) is a better idea, which above mentioned scenario.
eg:
enum PROP_FIELD_COLUMN {
columnOne, columnTwo,etc
}
I'd use an Enum. That way you get compile-time checking.
If your Strings really have a good fairly standard naming convention, like "column" + "One", "Two", etc. as in your example, you could save a lot of work by combining an enum for the prefix with an int for the suffix. So, create a class or utility method that takes an enum for the prefix, e.g. COLUMN, and combines it with an int, say 2, to yield "columnTwo".
An alternative might be be for your code, like parseAndSet, to validate the passed in String against an array or Collection of legal Strings, or maybe a regex, and throw an IllegalArgumentException. You'd get runtime checking and if you have good unit tests this could work.
EDIT ADDED
#sethupathi.t had a nice idea in his answer - In some cases it may be preferable to make the 2nd argument (for which I used an int) also an enum.
As far as I can tell, there are two reasonable ways to do what you want to do.
The first way (and probably best way, if it works for you) is to use an enum, as mentioned in another answer.
The second way, which may be necessary if you do not know all of your PropertyName's at runtime, would be to use a PropertyNameFactory along the lines of:
public class PropertyNameFactory
{
public static PropertyName getPropertyName(String propertyName)
{
// Check validity of the propertyName against what ever rules we
// have defined (maybe valid propertyNames are read from a DB at
// startup, etc).
if (isValid(propertyName))
{
// Ideally get from a cache, but for the sake of the example
// we will create a new one...
return new PropertyName(propertyName);
}
throw new IllegalArgumentException("Invalid property name: " + propertyName);
}
}
This is not ideal in that it does not provide true type safety of your property names, but it does ensure their validity.
I have to second the Enum answers.
However, a more literal answer to your question is that Java provides an interface for String-like objects, java.lang.CharSequence, and many parts of the standard Java libraries have been updated to accept CharSequence where appropriate. This will not however give you the behavior that you want, which is to have your class behave as a subtype of String.