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
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().
I'd be extremely grateful if anyone could point out what I'm doing wrong.
I have an interface IDoubleSource, which I implement in a Person class. There is a LinearRegression class with a method that takes an IDoubleSource argument, but I will pass in the Person class.
As part of the IDoubleSource interface, an enum called Variables and a method called getDoubleValue(Enum) must be defined. Below, I show how I have done this in Person, and that the enum types are used to specify switch cases in the getDoubleValue() method.
The problems:
1) In LinearRegression, there is a method computeScore((MultiKeyCoefficient)Map, IDoubleSource), where the last argument is an interface. I cannot seem to access the Variables enum of the instance of the implementation of IDoubleSource within the computeScore method, despite having the interface imported into the LinearRegression class. It just doesn't register that an IDoubleSource has an enum called Variables (though I can call the getDoubleValue() method fine). Is there anything I'm obviously doing wrong, that prevents me accessing the enum Variables?
2) The getDoubleValue(Enum) method in Person class is designed to return a double value that depends on the value of the enum Variable passed to it. By looping through the keys (which are of String type) of a (MultiKeyCoefficient)Map in the LinearRegression class, I would like to use the keys to specify the enum values that I want as an argument to getDoubleValue(Enum) in the LinearRegression class (I would like getDoubleValue() to return several different values based on the Enum values it receives in the loop). However, I cannot use the (String) key in place of the expected enum as I get a ClassCastException java.lang.String cannot be cast to java.lang.Enum. How can I use the keys of the map to specify the Enums?
I'm not very familiar with using Enum types in Java, which may be a large part of my problem.
Now the code details:
I implement the following interface:
IDOUBLESOURCE INTERFACE
public interface IDoubleSource {
public enum Variables {
Default;
}
/**
* Return the double value corresponding to the given variableID
* #param variableID A unique identifier for a variable.
* #return The current double value of the required variable.
*/
public double getDoubleValue(Enum<?> variableID);
}
by creating the class:
PERSON CLASS
public class Person implements IDoubleSource {
public enum Variables {
nChildren,
durationInCouple,
ageDiff;
}
public Person() {
...
}
public double getDoubleValue(Enum<?> variableID) {
switch ((Variables) variableID) {
case nChildren:
return getNChildren();
case durationInCouple:
return (double)getDurationInCouple();
case ageDiff:
return getAgeDiff();
default:
throw new IllegalArgumentException("Unsupported variable");
}
In another package, I have a Class:
LINEARREGRESSION CLASS
public class LinearRegression
private MultiKeyCoefficientMap map = null;
public LinearRegression(MultiKeyCoefficientMap map) {
this.map = map;
}
....
public double score(IDoubleSource iDblSrc) {
return computeScore(map, iDblSrc);
}
public static double computeScore(MultiKeyCoefficientMap coeffMap, IDoubleSource iDblSrc) {
try {
final Map<String, Double> varMap = new HashMap<String, Double>();
for (Object multiKey : coeffMap.keySet())
{
final String key = (String) ((MultiKey) multiKey).getKey(0);
Enum<?> keyEnum = (Enum<?>) key; //Throws class cast exception
double value = iDblSrc.getDoubleValue(keyEnum);
varMap.put(key, value);
}
return computeScore(coeffMap, varMap);
} catch (IllegalArgumentException e) {
System.err.println(e.getMessage());
return 0;
}
}
}
public static double computeScore(MultiKeyCoefficientMap amap, Map<String, Double> values)
{
//Do some stuff
}
I'm very grateful that you've taken the time to read through this code. Please do let me know if you have any idea what I'm doing wrong!
Many Thanks and Best Wishes,
R
The key incorrect assumption you have is that the IDoubleSource.Variables enum is connected in some way to the Person.Variables enum. They're totally unrelated. (They just happen to have the same simple name.)
When a class (like Person) implements an interface (like IDoubleSource), that class is declaring that it will provide implementations of the (non-default) methods in that interface. Any inner classes, inner enums, or inner interfaces within the implemented interface are only relevant if they appear in the signatures of one of the interface methods that must be implemented.
So you could change your interface to:
public interface IDoubleSource {
public enum Variables {
Default;
}
public double getDoubleValue(Variables variableID);
}
... but then the only legal value to pass in to any implementation of getDoubleValue is Default -- implementors of IDoubleSource can't extend the set of allowed enum values.
I think what you really want to do is to declare that implementors of IDoubleSource must declare what type of enum they deal in:
public interface IDoubleSource<T extends Variables & Enum<T>> {
public interface Variables { }
public double getDoubleValue(T variableID);
}
What you're saying here is that an implementor of the getDoubleValue() method must use some enum type as its arg, and that type must also implement the Variables interface. (If there are no meaningful methods to put in that inner inteface, you can drop it for simplicity.)
Then your implementation would look like this:
public class Person implements IDoubleSource<PersonVariables> {
public enum PersonVariables implements Variables {
nChildren,
durationInCouple,
ageDiff;
}
public double getDoubleValue(PersonVariables variableID) {
switch (variableID) { //no cast necessary here!
case nChildren:
// ...
default:
// this is now really impossible
// if the rest of your program has no unsafe casts
throw new IllegalArgumentException("Unsupported variable");
}
}
}
The last trick, then, is to enhance the signature of your computeScore method to ensure that the iDblSrc argument uses the same enum type as those found in the map:
public static <T extends IDoubleSource.Variable & Enum<T>>
double computeScore(MultiKeyCoefficientMap<T,?> coeffMap,
IDoubleSource<T> iDblSrc);
Then the keys in the map won't be Strings at all, but rather instances of the right enum type.
There are multiple problems here:
An enum declared in an interface (or class) implemented (extended) by another class is NOT overridden by the implementing class. So what you have above is two completely different enums, which happen to have the same local name. But one is IDoubleSource.Variables, with one value: IDoubleSource.Variables.Default, and the other is Person.Variables, with three values, one of which is Person.Variables.nChildren
As the OP pointed out, you cannot simply cast a String (which presumably has a value matching the name of some enum) to an enum, and have it resolve to the expected enum value.
Given these two things, and that it seems you want to select different processing for subtype specific types of things, then at worst, you could pass the string key as an argument, and then vary the logic internally. But really, you have come up with a scheme where you need to have knowledge of the subtype in order to request appropriate (supported) processing. This does not allow for the type of decoupling that is intended when using an interface/implementing class(es). You may want to review the objectives here and work out a better design.
I'm trying to find the best way to design the client side storage of "buckets". To explain, the server sends down info like:
{
'buckets': {
'some_cool_bucket' : 'val1',
'another_bucket' : 'name'
}
}
Where the values can be
'some_cool_bucket' : 'val1' | 'val2' | 'val3'
'another_bucket' : 'name' | 'cool' | 'other'
basically all these buckets are enums with all the possible values known to both client and server, though there aren't common constraints, like buckets can have any number of possible values (no size limit), and any naming scheme.
I'm struggling against Java to find a design I am happy with. Forget about parsing JSON, blah blah blah, from a design point of view I want to know I can store this data that meets these requirements:
Each bucket needs to be able to store a default value in case server doesn't send one down
bucket.isBucket(...) should be type safe, ie, if we use an enum here, you shouldn't be able to pass in a bucket that doesn't belong without getting an error.
Easy, simple access. Buckets.some_cool_bucket.is(val1) would be ideal.
Minimal boiler plate in adding a new bucket
Non confusing design
Ignoring these requirements, we could implement this as follows:
enum Bucket {
some_cool_bucket('val1'),
another_bucket('name');
Bucket(String default) {
[...]
}
// Assume this retrieves the stored value sent down from the server.
String getVal() {
[...]
}
boolean is(String val) {
return getVal().equals(val);
}
}
With usage Bucket.some_cool_bucket.is('val1'). Naturally, we would want to extend this by changing the type signature of is() to accept some val enum defined by some_cool_bucket. Since the values a bucket can take are not uniform, we'd have to define this inside the some_cool_bucket enum. But you can't have enums inside enums in Java.
Ok, reset. Let's try this again:
public abstract class BaseBucket<E extends Enum<E>> {
private final Class<E> mClazz;
private final E mDefaultBucket;
public BaseBucket(Class<E> clazz, E defaultBucket) {
mClazz = clazz;
mDefaultBucket = defaultBucket;
}
// Assume this retrieves the stored value sent down from the server, uses
// getName() to match with the data.
protected E getVal() {
[...]
}
protected abstract String getName();
public boolean is(E test) {
return getVal() == test;
}
}
public class SomeCoolBucket extends BaseBucket<Val> {
public SomeCoolBucket() {
super(Val.class, Val.val1);
}
#Override
public String getName() {
return "some_cool_bucket";
}
public enum Val {
val1, val2, val3;
}
}
public Buckets {
public static final SomeCoolBucket some_cool_bucket = new SomeCoolBucket();
}
Ok, this works! Great. It meets all the functional requirements, but it's cumbersome and I hate having to create a new class for each bucket. I find it hard to justify all of the code, though I believe the requirements are sound.
Does anyone have a better solution for this?
What you can do in this case is have the abstract BaseBucket class, but remove the generics bits. The base class can have an instance variable of the Enum type. To do this without generics you can use the Strategy design pattern. Using this you can make all your Enum types implement a common interface. For the sake of an example you can call this IBucketEnum. Therefore, your BaseBucket class will have an instance variable of the IBucketEnum type and will look something like this:
public abstract class BaseBucket{
private IBucketEnum enum;
//other instance vars
public String getName(){
enum.getName();
}
}
From there you can have different versions of the BaseBucket and they will have the implementations and instance variables inherited from the base one, but can be extended with additional things that you need.
Hope this helps.
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'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.