I have read the question Difference of Enum between java and C++? but I'm still confused.
I would like the following to return the related String:
public enum Checker {
EMPTY ("Empty"),
RED ("Red"),
YELLOW ("Yellow");
}
From what I have read, this should be possible. Just would like you to shed some light on it on how to implement it.
Short Answer
You need a constructor, a field and a getter.
Constructors
Enum types can have constructors, provided that their access level is either private or default (package-private). You can not directly call these constructors, except in the enum declaration itself. Similar to classes, when you define an enum constant without parameters, you actually call the default constructor generated by the compiler. E.g.
public enum King {
ELVIS
}
is equivalent to
public enum King {
ELVIS() // the compiler will happily accept this
}
And just like in classes, if you define an explicit constructor, the compiler will not insert a default constructor, so this will not compile:
public enum King {
ELVIS, // error, default constructor is not defined
MICHAEL_JACKSON(true)
;
private boolean kingOfPop;
King(boolean kingOfPop){this.kingOfPop = kingOfPop;}
}
This is a pretty good reference on enums that also explains the constructor issues.
Fields and Accessors
Enums are constants and are immutable as such. They can however define fields, that can have state. This is an awful practice, because developers will expect enums and their associated values to be constants, but you can still define a non-final field in an enum with getters and setters.
This is legal java code:
public enum Color {
RED("FF0000"),
GREEN("00FF00"),
BLUE("0000FF");
private String code;
public String getCode(){return code;}
public void setCode(String code){this.code = code;}
private Color(String code){this.code = code;}
}
But it enables evil code like this:
String oldBlue = Color.BLUE.getCode();
Color.BLUE.setCode(Color.RED.getCode());
Color.RED.setCode(oldBlue);
So in 99.99 % of cases: if you have fields in your enums, you should make them final and provide getters only. If the fields are not immutable themselves, provide defensive copies:
public enum Band {
THE_BEATLES("John","Paul","George","Ringo");
private final List<String> members;
public List<String> getMembers(){
// defensive copy, because the original list is mutable
return new ArrayList<String>(members);
}
private Band(String... members){
this.members=Arrays.asList(members);
}
}
Solution
In your case it's very simple: you just need a single field of type string (immutable), so initializing it in the constructor and providing a getter is perfectly ok:
public enum Checker {
EMPTY ("Empty"),
RED ("Red"),
YELLOW ("Yellow");
private final String value;
private Checker(final String value) {
this.value = value;
}
public String getValue() { return value; }
}
If the pattern holds, this works as well and eliminates the repetition:
public enum Checker {
EMPTY,
RED,
YELLOW;
public String getDescription(){
String name = name();
return ""+Character.toUpperCase(name.charAt(0))
+name.substring(1).toLowerCase();
}
}
Related
I have read the question Difference of Enum between java and C++? but I'm still confused.
I would like the following to return the related String:
public enum Checker {
EMPTY ("Empty"),
RED ("Red"),
YELLOW ("Yellow");
}
From what I have read, this should be possible. Just would like you to shed some light on it on how to implement it.
Short Answer
You need a constructor, a field and a getter.
Constructors
Enum types can have constructors, provided that their access level is either private or default (package-private). You can not directly call these constructors, except in the enum declaration itself. Similar to classes, when you define an enum constant without parameters, you actually call the default constructor generated by the compiler. E.g.
public enum King {
ELVIS
}
is equivalent to
public enum King {
ELVIS() // the compiler will happily accept this
}
And just like in classes, if you define an explicit constructor, the compiler will not insert a default constructor, so this will not compile:
public enum King {
ELVIS, // error, default constructor is not defined
MICHAEL_JACKSON(true)
;
private boolean kingOfPop;
King(boolean kingOfPop){this.kingOfPop = kingOfPop;}
}
This is a pretty good reference on enums that also explains the constructor issues.
Fields and Accessors
Enums are constants and are immutable as such. They can however define fields, that can have state. This is an awful practice, because developers will expect enums and their associated values to be constants, but you can still define a non-final field in an enum with getters and setters.
This is legal java code:
public enum Color {
RED("FF0000"),
GREEN("00FF00"),
BLUE("0000FF");
private String code;
public String getCode(){return code;}
public void setCode(String code){this.code = code;}
private Color(String code){this.code = code;}
}
But it enables evil code like this:
String oldBlue = Color.BLUE.getCode();
Color.BLUE.setCode(Color.RED.getCode());
Color.RED.setCode(oldBlue);
So in 99.99 % of cases: if you have fields in your enums, you should make them final and provide getters only. If the fields are not immutable themselves, provide defensive copies:
public enum Band {
THE_BEATLES("John","Paul","George","Ringo");
private final List<String> members;
public List<String> getMembers(){
// defensive copy, because the original list is mutable
return new ArrayList<String>(members);
}
private Band(String... members){
this.members=Arrays.asList(members);
}
}
Solution
In your case it's very simple: you just need a single field of type string (immutable), so initializing it in the constructor and providing a getter is perfectly ok:
public enum Checker {
EMPTY ("Empty"),
RED ("Red"),
YELLOW ("Yellow");
private final String value;
private Checker(final String value) {
this.value = value;
}
public String getValue() { return value; }
}
If the pattern holds, this works as well and eliminates the repetition:
public enum Checker {
EMPTY,
RED,
YELLOW;
public String getDescription(){
String name = name();
return ""+Character.toUpperCase(name.charAt(0))
+name.substring(1).toLowerCase();
}
}
I have this model of an object called expenseType:
public class ExpenseType {
private String gridText;
public enum type {
FOOD(Constants.EXPENSE_TYPE_FOOD, R.drawable.food_blue, R.drawable.food),
FLOWERS(Constants.EXPENSE_TYPE_FLOWERS, R.drawable.flowers_blue, R.drawable.flowers),
GROCERIES(Constants.EXPENSE_TYPE_GROCERIES, R.drawable.groceries_blue, R.drawable.groceries),
HOLIDAY(Constants.EXPENSE_TYPE_HOLIDAY, R.drawable.holiday_blue, R.drawable.holiday),
PHARMACY(Constants.EXPENSE_TYPE_PHARMACY, R.drawable.pharmacy_blue, R.drawable.pharmacy),
BILLS(Constants.EXPENSE_TYPE_BILLS, R.drawable.bills_blue, R.drawable.bills),
CLOTHES(Constants.EXPENSE_TYPE_CLOTHES, R.drawable.clothes_blue, R.drawable.clothes),
TRANSPORT(Constants.EXPENSE_TYPE_TRANSPORT, R.drawable.transport_blue, R.drawable.transport),
ITEMS(Constants.EXPENSE_TYPE_ITEMS, R.drawable.items_blue, R.drawable.items),
OTHERS(Constants.EXPENSE_TYPE_OTHERS, R.drawable.others_blue, R.drawable.others);
private String expenseKey;
private int drawableBlue, drawableWhite;
type(String expenseKey, #DrawableRes int drawableBlue, #DrawableRes int drawableWhite) {
this.expenseKey = expenseKey;
this.drawableBlue = drawableBlue;
this.drawableWhite = drawableWhite;
}
public String getKey() {
return expenseKey;
}
public int getDrawableBlue() {
return drawableBlue;
}
public int getDrawableWhite() {
return drawableWhite;
}
}
public ExpenseType(String gridText) {
this.gridText = gridText;
}
public String getGridText() {
return gridText;
}
public void setGridText(String gridText) {
this.gridText = gridText;
}
}
The string gridText gets written inside a database, but I do not want to add the drawable values to the database as well, so I created that enum that has the drawable variation. Now, inside a recycle view adapter, how can I access the getDrawableBlue() from the enum so I can set an icon correspondent to my expenseType?
I have this code in the adapter:
private void checkSelect(ExpenseType expenseType) {
if(positionSelected == getAdapterPosition()){
gridIcon.setImageResource(????????);
return;
}
How can I access that getter instead of the ???????? so I can get my drawable value stored in that enum?
This looks like a glitch in your class design.
Your enum type is a nested class in your ExpenseType class.
(Note: as it's an enum, it's implicitly a static nested type).
In order for you to be able to invoke the accessors of a type, you will need to reference its specific type somehow.
One way to do so would be to have a type as instance field of ExpenseType, pretty much like the String gridText.
You would then need to bind a specific type type to your ExpenseType instance (I know, this gets semantically confusing but I didn't name your variables :).
In other words, each instance of ExpenseType has its own type field assigned with one type of... errr.. type.
So instance 1 of ExpenseType has a FOOD value for its type, instance 2 of ExpenseType has a FLOWERS value for its type, etc.
You could then add a getter and reference the drawableBlue int in checkSelect by invoking:
// assuming field type can't be null
expenseType.getType().getDrawableBlue()
expenseType seems to be of the class type ExpenseType but the enum you're refering to is the inner enum type (which should be renamed btw). Thus you'd need to either provide a field for type in ExpenseType and a getter for that and then call something like expenseType.getType().getDrawableBlue() or refactor your code (depends on what ExpenseType is meant to represent).
As for the renaming: the class ExpenseType has a field gridText which might indicate that it actually represents a cell. If that's the case I'd suggest doing something like this:
public class ExpenseGridCell {
private String gridText;
private ExpenseType type; //that would be your enum tyoe
public ExpenseType getType() {
return type;
}
}
//I'll move the enum to a separate class which makes it easier to use elsewhere (the outer class would be a "namespace" only anyway)
public enum ExpenseType {
FOOD(Constants.EXPENSE_TYPE_FOOD,R.drawable.food_blue, R.drawable.food),
...;
}
If gridText isn't a cell's text but the same for every type then you might want to merge the inner enum type into ExpenseType, i.e. something like this:
public enum ExpenseType {
FOOD(Constants.EXPENSE_TYPE_FOOD, "Some grid text for food", R.drawable.food_blue, R.drawable.food),
...;
private String gridText;
private String expenseKey;
private int drawableBlue, drawableWhite;
//appropriate constructor and getters
}
Some background on the project: I am attempting to craft a space/sci-fi combat sim game with tabletop rpg style dice mechanics cranked up to 11 on the complexity scale, but still being transparent about the die rolls going on under the hood. I'm currently using the Star Wars Saga Edition combat rules as a basis.
Currently I'm trying to figure out a way to assign traits to vehicle.(possibly stored as a class for each vehicle) Each trait is an enum so that it can store multiple pieces of information. Here is the code I have for size categories:
public enum VehicleSize {
LARGE(1,"Speeder bike",5),HUGE(2,"Small Fighter",10),GARGANTUAN(5,"Tank, Medium Fighter",20),COLOSSAL(10,"Imperial Walker, Light Freighter",50),
COLLOSSALfrigate(10,"Corvette, Frigate",100),COLLOSSALcruiser(10,"Imperial-class Star Destroyer, Cruiser",200),
COLLOSSALstation(10,"The Death Star, Space Station",500);
private final int refMod;
private final int threshMod;
private final String desc;
VehicleSize(int reflexModifier,String example,int thresholdModifier)
{
refMod = reflexModifier;
desc = example;
threshMod = thresholdModifier;
}
public int getRefMod() {
return refMod;
}
public String getDesc() {
return desc;
}
public int getThreshMod() {
return threshMod;
}
}
My question is such: How do create vehicle profiles in such a way that I can assign this and similar enums as traits?
For practically all purposes, a field whose type is an enum class is no different than a field of any other object type, like Integer or String.
Create a private field, add a getter and setter, or if the field is final (likely in your case, because a vehicle instance can't change its type), add it as a constructor parameter and remo e the setter.
public class Vehicle {
private final VehicleSize vehicleSize;
// other fields
public Vehicle(VehicleSize vehicleSize) {
this.vehicleSize = vehicleSize;
}
public VehicleSize getVehicleSize() {
return vehicleSize;
}
// rest of class
}
There is nothing mysterious about an enum, other than the number of different instances of it are known at compile time (and a few more things, but nothing scary).
To add this into a class, you can use it like any user defined type.
public class MyClass {
private MyEnum myEnum;
}
Please have a look at Synthetic Arguments. Enum constructors have two additional synthetic arguments.
Please look at the section:
Another example: Java enum classes
As you can see, it saves quite some code, but also adds synthetic fields, methods and constructor parameters. If you had defined your own constructor, with its own set of parameters.
Can there be a situation where a enum constructor does not have any synthetic arguments.
Apologies for not providing enough detail.
Having read the article, I would say the answer is no. The article explains that a typical enum such as:
enum Colours {
RED, BLUE;
}
Becomes:
final class Colours extends java.lang.Enum {
public final static Colours RED = new Colours("RED", 0);
public final static Colours BLUE = new Colours("BLUE", 1);
private final static values = new Colours[]{ RED, BLUE };
private Colours(String name, int sequence){
super(name, sequence);
}
public static Colours[] values(){
return values;
}
public static Colours valueOf(String name){
return (Colours)java.lang.Enum.valueOf(Colours.class, name);
}
}
where the arguments to the Colours constructor are considered synthetic (i.e. they've been produced by the compiler to make sure "stuff works"). So it seems the synthetic arguments are unavoidable as they're a necessary part of translating an enum into a real class.
The only possibility is if the enum has no values - does Java still create the synthetic fields? Intuitively, the answer is yes. This is backed up by the article in the OK, but why should I care? section. Here the author shows that an empty enum still has a parameter count of two, when viewed with reflection.
Check the source code of the Concurrent class of TimeUnit. It's an enum with its own methods.
You can have work with enums like if they were class themselves.
http://fuseyism.com/classpath/doc/java/util/concurrent/TimeUnit-source.html
Here is an example of mine:
public enum ExampleEnum {
ENUM_1 ( "ENUM_1", 1, Color.GREEN ) {
#Override
public void doMethingWeird( String stringToEnum ) {
//Implementation goes here;
}
},
ENUM_2 ( "ENUM_2", 2, Color.BLACK ) {
#Override
public void doMethingWeird( String stringToEnum ) {
//Implementation goes here;
}
},
ENUM_3 ( "ENUM_3", 3, Color.WHITE ){
#Override
public void doMethingWeird( String stringToEnum ) {
//Implementation goes here;
}
}; //Don't forget the semicolon ';' after the enums, to separate them from the methods;
//You can have static constants;
private static final Object object = new Object();
private final String enumName;
private final int enumNumber;
private final Color enumColor; //why not?
//CONSTRUCTOR IT MUST BE PRIVATE
private Effect( String enumName, int enumNumber, Color enumColor ){
this.enumName = enumName;
this.enumNumber = enumNumber;
this.enumColor = enumColor;
}
//you can have abstract methods and implement them on the enums.
public abstract void public void doMethingWeird( String stringToEnum );
public String getEnumName() {
return enuName;
}
public int getEnumNumber() {
return enumNumber;
}
public Color getEnumColor() {
return enumColor;
}
}
I hope I have helped.
I was running into the same problem, having an enum with tree constructors and parameters. Doing reflection and getting the constructors parameters, you get a String and an int extra as the first 2 parameters. I was wondering where they were coming from. After debugging I found out that the Enum class has a protected constructor, which is using the first 2 parameters.
I did a test by adding a constructor without parameters, and the 2 extra parameters are added too.
Code from Enum.java with the constructor:
/**
* Sole constructor. Programmers cannot invoke this constructor.
* It is for use by code emitted by the compiler in response to
* enum type declarations.
*
* #param name - The name of this enum constant, which is the identifier
* used to declare it.
* #param ordinal - The ordinal of this enumeration constant (its position
* in the enum declaration, where the initial constant is assigned
* an ordinal of zero).
*/
protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}
To detect this situation, you can use the isEnum() method of the reflected constructor, and skip the 2 parameters.
Constructor<?> constructor;
private boolean isEnum() {
return constructor.getDeclaringClass().isEnum();
}
I'm attempting to translate some C++ code into Java. I'm looking for the best way to emulate this type of C++ paradigm in Java -- I think enums are probably the answer but I'm open to anything
C++ code:
typedef UInt32 Type;
enum { UNKNOWN, QUIT, SYSTEM, TIMER, LAST }
...
Type newType = UNKNOWN;
Type nextType = LAST + 1;
...
// "Register" the new type
newType = nextType;
nextType++;
...
switch (newType) {
case UNKNOWN:
case QUIT:
...
case LAST:
// Ignore unset or predefined types
default:
// Some type other than the predefined. Do something special
Essentially I'm looking for a way to "expand" the values of a Java enumeration.
enum Type { UNKNOWN, QUIT, SYSTEM, TIMER, LAST }
doesn't quit cut it.
I like the idea of making a new object for strong typing.
Again, I'm looking for the best pattern to use here. I could easily float by with a few public static final int UNKNOWN, etc
One advantage of Java enums is, that they are essentially objects like all others. In particular, you can have methods on the constants, and make your enum implement interfaces:
interface Useful {
void doStuff();
}
enum Foo implements Useful {
DEFAULT {
public void doStuff() {
...
}
},
MAGIC {
public void doStuff() {
...
}
}
}
So, instead of taking arguments of the enum type, your methods could accept any implementation of the interface, and in particular, provide the default stuff by having the enum constants implement whatever is necessary.
They can also have members:
enum Explicit {
FIRST(0), SECOND(1), THIRD(2);
private final int value;
private Explicit(int v) {
this.value = v;
}
}
Note, that constants have an internal numeric value (reflecting the position of the constant among its peers) which is accessible using the ordinal method:
assert Explicit.FIRST.ordinal() == 0;
But relying on this is a little bit dangerous. If you are going to (say) persist enum constants in a database, then the following change would break the code:
enum Explicit {
FIRST(0), NEWELT(-1), SECOND(1), THIRD(2);
private final int value;
private Explicit(int v) {
this.value = v;
}
}
when using ordinal values. For this reason, the serialization machinery uses the constant's name instead of its position when serializing enum values.
So:
Type.X + 1
would be
Enum.values()[Enum.X.ordinal() + 1]
and the switch could be modelled using interfaces implemented by the enum itself (you can use enums in switch statements in Java, but often, making the enum implement the necessary code yields more maintainable code)
If each value of Type is just an int, then I'd probably go for a bunch of static final ints in a class.
Just for the record, something like this works more or less type-safely. I can't determine if the complexity is warranted without knowing more about the problem.
public class abstract Type
{
public static final Type UNKNOWN = registerStd("UNKNOWN");
...
public static final Type TIMER = registerStd("TIMER");
// use this to keep track of all the types
private static final List<Type> REGISTERED = ...
//This will do your switch statement for you, implemented by
// anonymous subclasses
public abstract void dispatch(Type onMe);
// here's how you make the standard ones
private static Type registerStd(String name)
{
Type heresOne = new Type(name)
{
// note, it's a no-op
public void dispatch(DoStuffer algorithm) {}
};
REGISTERED.add(heresOne);
return heresOne;
}
//here's how you make the non-standard ones
public static Type registerNew(String name)
{
Type heresOne = new Type(name)
{
public void dispatch(DoStuffer algorithm) {algorithm.execute(this)}
};
REGISTERED.add(heresOne);
return heresOne;
}
}
public interface DoStuffer
{
public void execute(Type onMe);
}
//Then your code becomes
Type newType = Type.registerNew("NewType");
newType.dispatch
(
new DoStuffer()
{
public void algorithm(Type forMe) { ... }
}
);
Maybe this is a little esoteric. But it does allow for "easy dispatch" at the caller site and an extensible enum, in some sense.