Can't access enum values inside Switch Case / Java - java

I can't access my enum variables in my switch-case statement:
public enum Country {
FRANCE(0, "France"), SPAIN(1, "Spain");
private final int code;
private final String name;
Country(int code, String name) {
// TODO Auto-generated constructor stub
this.code = code;
this.name = name;
}
public int getCode() {
return code;
}
public String getName() {
return name;
}
}
In another class there is this code :
public Drawable getFlag(){
Drawable d = null;
switch(country_id){
case Country.FRANCE.getCode():
break;
}
return d;
}
But the problem is that when i type Country, there is only class or this.

The expressions in the case statements must be constant values.
One (commonly used) way to approach your problem is by creating a function that gets the enum from the numeric code:
public enum Country {
...
public static Country getCountry(int countryCode) {
for(Country country : Country.values()) {
if(country.code == countryCode) {
return country;
}
}
throw new IllegalArgumentException();
}
Then you'll be able to do the switch on the enum:
switch(Country.getCountry(country_id)){
case Country.FRANCE:
break;
...
}

case labels in a switch statement need be constants

The case expressions must be compile time constant expressions. Your enum instance's variables are constants, but not compile time constants.
We call a variable, of primitive type or type String, that is final
and initialized with a compile-time constant expression (§15.28) a
constant variable. Whether a variable is a constant variable or not
may have implications with respect to class initialization (§12.4.1),
binary compatibility (§13.1, §13.4.9) and definite assignment (§16).

Related

Can Java enum class set default value

Mycode is
public enum PartsOfSpeech2 {
n("noun"),
wp("标点"),
a("adjective"),
d("conjunction"),
...;
which I want
public enum PartsOfSpeech2 {
n("noun"),
wp("标点"),
a("adjective"),
d("conjunction"),
%("noun");
can I hava a default value which is not in it, can it be set as a default value?
because I have a type is "%", but enum is not support %, so I want a default value to solve it
The default for one who holds a reference to an enum without setting a value would be null (either automatically in case of a class field, or set by the user explicitly).
Unfortunately you cannot override the method valueOf for your own enum, as it is static.
But you can still create your methods:
public enum PartsOfSpeech2 {
n("noun"),
wp("标点"),
a("adjective"),
d("conjunction");
private String value;
PartsOfSpeech2(String value) {
this.value = value;
}
// declare your defaults with constant values
private final static PartsOfSpeech2 defaultValue = n;
private final static String defaultString = "%";
// `of` as a substitute for `valueOf` handling the default value
public static PartsOfSpeech2 of(String value) {
if(value.equals(defaultString)) return defaultValue;
return PartsOfSpeech2.valueOf(value);
}
// `defaultOr` for handling default value for null
public static PartsOfSpeech2 defaultOr(PartsOfSpeech2 value) {
return value != null ? value : defaultValue;
}
#Override
public String toString() { return value; }
}
From JLS 8.9. Enums
An enum type has no instances other than those defined by its enum constants. It is a compile-time error to attempt to explicitly instantiate an enum type (§15.9.1).
So you can't have any instance which is take default value.
You can create default constant and use that using some condition.
public enum PartsOfSpeech2 {
....
DEFAULT("DEFAULT");
}
And use condition to check if your string have constant, Ex "%" have enum or not. if not use default value:
PartsOfSpeech2 result = PartsOfSpeech2.valueOf("%"); //Your String EX: %
PartsOfSpeech2 resultNew = result==null?PartsOfSpeech2.DEFAULT: result;
The way I solved it was the following
public enum YourEnum{
ENUM1("stringToMatchWith"),
ENUM2("stringToMatchWith2"),
DEFAULTENUM("Default");
public final String label;
YourEnum(String label) {
this.label = label;
}
public static YourEnum resolveYourEnum(String stringToMatch) {
return Arrays.stream(YourEnum.values()).filter(aEnum -> aEnum.label.equals(stringToMatch)).findFirst().orElse(YourEnum.DEFAULTENUM);
}
That way you can do YourEnum.resolveYourEnum("aString") and return the specified enum or the default we set

Switch String with Enum variables

I have got an Enum with different values and want to switch a string variable. Now I hit a wall trying to convert the Enum values to Strings, that I can use as case constant.
My best try was to convert the Enum to a String array, but the switch doesn't seem to accept array values as a case constant. (IntelliJ says: "constant expression required")
Enum myEnum = {FOO, BAR}
String input = "foo"
final String[] constant = Arrays.stream(myEnum.values()).map(Enum::name).toArray(String[]::new);
//converts Enum to String[]; made it final, so it is "constant"
switch (input) {
case constant[0]:
System.out.println("foo");
break;
case constant[1]:
System.out.println("bar");
break;
}
Is there an elegant way to make this switch depend on the Enum?
You shouldn't convert it because it isn't needed. Also, your code won't even compile because case is a reserved keyword in Java.
You should take a look at the valueOf method of an Enum.
Your code can look like that:
public enum MyEnum {FOO, BAR}
//method
String input = "foo";
MyEnum niceFound = MyEnum.valueOf(input.toUpperCase());
That will return FOO but can throw an IllegalArgumentException when the given value isn't present as type.
You can do this :
public enum MyEnum {
FOO("foo"),
BAR("bar");
private String value;
public String getValue() {
return value;
}
public static MyEnum getState(String value) {
switch (value) {
case "foo":
return FOO;
case "bar":
return BAR;
}
return null;
}
private MyEnum(String value) {
this.value = value;
}
}
Now, in your class, you can :
MyEnum myEnum = getState("foo"); // returns MyEnum.FOO
Also make sure you handle the case when getState() returns null
A solution with Java 8+ streams would be to create a method inside your enum :
public static Optional<MyEnum> getByValue(final String value) {
return Arrays.stream(MyEnum.values())
.filter(myEnum -> myEnum.value.equals(value))
.findFirst();
}
This returns optional in case there is no enum value for your String parameter. But you can change it according to your needs.
Use MyEnum.valueOf(value.toUpperCase())
public enum MyEnum {
FOO, BAR;
}
public static void process(String value) {
try {
switch (MyEnum.valueOf(value.toUpperCase())) {
case FOO :
System.out.println("FOO");
break;
case BAR :
System.out.println("BAR");
break;
default :
break;
}
}
catch (IllegalArgumentException e) {
// TODO: handle exception
}
public static void main(String[] a){
process("foo");
}

Constant Map for case selection in switch statement?

Is there a way to define a constant Map for the use in a switch statement? All my trials with static Maps from here, here and others were not successful. Why isn't the Map constant?
For the line case (kws.get(KEYWORD_NAME)): I always get constant string expression required error.
public class Demo {
public static final String KEYWORD_NAME = "Name";
public static final String KEYWORD_TYPE = "Type";
private static final Map<String, String> kws = Collections.unmodifiableMap(
new HashMap<String, String>() {{
put(KEYWORD_NAME, KEYWORD_NAME.toLowerCase());
put(KEYWORD_TYPE, KEYWORD_TYPE.toLowerCase());
}});
public static void parse(String kw){
switch(kw){
case (kws.get(KEYWORD_NAME)):
System.out.println("Test");
break;
default:
System.out.println("Unknown");
}
}
}
No, because the case labels in a switch statement must be either constant expressions or enumerators.
The reference to your Map is final, and your map is unmodifiable. But the latter is enforced at run time. The compiler does not treat the object as a constant.
From the Java Language Specification, 14.11: The switch statement:
SwitchLabel:
case ConstantExpression :
case EnumConstantName :
default :
Constant expressions can be composed only of primitive and String literals, certain operators without side-effects, constant variables, and a few other components that can be computed at compile-time. (A constant variable is a final variable of primitive or String type that's been initialized to a constant expression.) More detail is at 15.28: Constant expressions.
I do not know your use case, but instead of using unmodifiable map you can use parametrized enum:
>> when:
public enum Demo {
NAME("Name"),
TYPE("Type"),
NOT_SUPPORTED("");
private String code;
private static final Map<String, Demo> CODE_VALUE_MAP = new LinkedHashMap<>();
// -- static
static {
for (Demo demo : Demo.values()) {
CODE_VALUE_MAP.put(demo.getCode(), demo );
}
}
public static Demo forCode(#NotNull String code) {
if (code!= null) {
return CODE_VALUE_MAP.getOrDefault(code.toUpperCase(), NOT_SUPPORTED);
}
return NOT_SUPPORTED;
}
}
// -- constructor
Demo(String code) {
this.code= code;
}
// -- public methods
public String getCode() {
return code;
}
}
>>Then:
...
public static void parse(String kw){
Demo demo = Demo.forCode(kw);
switch(demo){
case NAME:
System.out.println("Test");
break;
default:
System.out.println("Unknown");
}
...

Java Enum Constructor Undefined

Why am i getting an error "Constructor is undefined" is it in my eclipse IDE?
is there something wrong with my code?
public enum EnumHSClass {
PALADIN ("Paladin"),ROUGE("ROUGE");
}
If you expect your enums to have parameters, you need to declare a constructor and fields for those parameters.
public enum EnumHSClass {
PALADIN ("Paladin"),ROUGE("ROUGE");
private final String name;
private EnumHSClass(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
You need to provide a constructor in your enum like:
public enum EnumHSClass {
PALADIN("Paladin"), ROUGE("ROUGE");
String value;
EnumHSClass(String value) {
this.value = value;
}
}
Note: The constructor for an enum type must be package-private or
private access. It automatically creates the constants that are
defined at the beginning of the enum body. You cannot invoke an enum
constructor yourself.
Ref : http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html
Enums have constructors too, but only with either private or default visibility:
public enum EnumHSClass {
PALADIN ("Paladin"),ROUGE("ROUGE");
private EnumHSClass(String s) {
// do something with s
}
}
You may want to declare a field and create a getter for it, and set the field in the constructor.
Also note that the name of the enum instance is available for free via the (implicit) name() method that all enums have - maybe you can use that instead.
Your code should look like this:
public enum EnumHSClass {
PALADIN ("Paladin"), ROUGE("ROUGE");
private String name;
private EnumHSClass(String name) {
this.name = name;
}
}
public enum Days {
MONDAY(1), TUESDAY(2);
int val;
Days (int val) {
this.val = val;
}
}

Using Enum as a int value

Am trying to use Enum as Constants for readability as below .
Public enum x { test1 , test2 , test3 }
I want to pass this enum into a method and use it as a int value as shown
private void (int type)
{
switch(int)
{
case enum.X:
// do somthing
break;
}
} ;
Can we use enum here as its more clearer than using a int value .( like switch 1 etc) . Is it possible to use this way.?
Yes, you should be able to use an enum in a switch statement in Java:
public enum SomeEnum { FOO, BAR, BAZ };
// in a class...
private void something(SomeEnum s) {
switch (s) {
case FOO:
// do something
break;
case BAR:
// do something else
break;
}
}
Not sure I understand how int values tie into this, but you can have fields/methods on an enum like in a normal Java class, and can use these to hold int (or any other type) values as on any other POJO.
Here's an example in which we declare a constructor for an enum class, so that you can pass in values for internal variables at the time each instance of the enum is constructed. To help you follow what's going on: First we declare the items in the enum - each declaration invokes the constructor, so we can pass in instance variables here. Then the code for the enum class follows, as with a normal Java class.
public enum AnotherEnum {
ONE(1, "un"), TWO(2, "deux"), THREE(3, "trois"), FIFTY_SEVEN(57, "cinquante-sept");
private final int someInt;
private final String french;
private AnotherEnum(int i, String s) {
this.someInt = i;
this.french = s;
}
public int getSomeInt() {
return this.someInt;
}
public String getFrench() {
return this.french;
}
}
So for example, System.out.println(AnotherEnum.TWO.getSomeInt()) would print 2, and System.out.println(AnotherEnum.FIFTY_SEVEN.getFrench()) would print cinquante-sept.
No, you cannot say:
case Enumerator.ordinal():
But you could say:
switch(EnumObject.values()[intVar]) {
case Enumerator1:
...
}
Another way you can do this by doing a little more work with you enum class.
public enum Foo {
X (1),
Y (2);
private int value;
Foo (int value)
{
this.value = value;
}
}
Now all you need to do is:
switch (int)
{
case Foo.X: doSomething ();break;
case Foo.Y: doSomething ();break;
}

Categories

Resources