Reputation: 422
In my front end html, when no country is selected, country 0 is saved.
In my back end,in my java code I want to have a 0 to for no countries selected.
I get a syntax error on 0 ("");
So when i get a country code of 0
,the enum code will not fail on System.out.println(Country.valueOf("0").getCountry());
Do advise, thanks.
public static void main (String []args) {
System.out.println(Country.valueOf("SG").getCountry());
}
public static enum Country {
MY ("Malaysia"),
SG ("Singapore"),
ID ("Indonesia"),
0 (""); //for null blank
private final String country;
private Country(String levelCode) {
this.country = levelCode;
}
public String getCountry() {
return this.country;
}
}
Upvotes: 2
Views: 2464
Reputation: 593
Why don't you use HasMap (Recommended)?
public final static Map countries = new HashMap<String, String>();
static {
countries.put("MY", "Malaysia");
countries.put("SG", "Singapore");
countries.put("ID", "Indonesia");
countries.put("0", "");
}
Upvotes: 0
Reputation: 86223
While the other answers contain helpful suggestions, I’d like to explain the reason for your error and the limitations of Java enums.
The reason for your syntax error is that in Java (and most other programming languages) an enum constant is an identifier and an identifier has to start with a letter (or underscore, certainly not recommended). 0
is not a letter.
This in turn also means that Country.valueOf("0")
is never going to work no matter what you do (one might have imagined overriding the method in your enum, but that is not possible).
Two suggestions:
Use another name, one that starts with a letter.
NULL_BLANK (""); //for null blank
Use a null
to represent no country.
For a different name I’m thinking COUNTRY_0
, BLANK
or ZERO
. No matter if you use item 1. or 2. above you will have to write your own lookup method as in Joakim Danielson’s answer, for example.
Edit: A possibly nicer solution may be an enum where the constructor accpets both key and country name as arguments:
public static enum Country {
MALAYSIA ("MY", "Malaysia"),
SINGAPORE ("SG", "Singapore"),
INDONESIA ("ID", "Indonesia"),
NULL_BLANK ("0", ""); //for null blank
private static final Map<String, Country> BY_KEY
= Arrays.stream(values()).collect(Collectors.toMap(c -> c.key, c -> c));
public static Country of(String key) {
return BY_KEY.get(key);
}
private final String key;
private final String country;
private Country(String key, String name) {
this.key = key;
this.country = name;
}
public String getCountry() {
return this.country;
}
}
One advantage is it allows for nicer enum constant names, MALAYSIA
instead of MY
, etc. I have provided the of
method for lookup. Use like for example:
System.out.println("MY -> \"" + Country.of("MY").getCountry() + "\"");
System.out.println("0 -> \"" + Country.of("0").getCountry() + "\"");
Output:
MY -> "Malaysia" 0 -> ""
Upvotes: 2
Reputation: 1818
Enum.valueOf
throws an exception when a passed string is not mapped to any enum value of the given enum. Furthermore valueOf
is O(n)
- it has to iterate all elements of an enum to find the matching enum.
Try using an internal Map<String,Country>
instead:
import java.util.Arrays;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
class ScratchStackOverflowQuestion57122100 {
public static enum Country {
MY ("Malaysia"),
SG ("Singapore"),
ID ("Indonesia"),
FALLBACK(null);
private static final Map<String, Country> stringMapping =
Arrays.stream(Country.values())
.collect(Collectors.toMap(Country::getCountry, Function.identity()));
private final String country;
Country(String levelCode) {
this.country = levelCode;
}
public String getCountry() {
return this.country;
}
//caller has to handle non-presence
public static Optional<Country> tryFromString(String input) {
return Optional.ofNullable(stringMapping.get(input));
}
//handle the error internal
public static Country fromString(String input) {
return tryFromString(input).orElse(FALLBACK);
}
}
}
This has the following benefits: if you only add tryFromString
you could let the caller handle the error, you don't have to specify a fallback then - this may fix your 0
issue. The lookup is really fast now and doesn't throw an undesirable exception in the future as unmapped values are always mapped to FALLBACK
in fromString
.
Upvotes: 0
Reputation: 51892
You can create your own valueOf
method and use that instead in your code, since Enum.valueOf is static we can't override it directly so we need another name for our method
public static Country getValue(String code) {
if (code == null || code.isEmpty() || code.equals("0")) {
return NO_COUNTRY;
}
return valueOf(code);
}
I added a NO_COUNTRY to the enum defined like this
NO_COUNTRY("")
Example
public static void main(String[] args) throws Exception {
System.out.printf("[%s]\n", Country.getValue("SG").getCountry());
System.out.printf("[%s]\n", Country.getValue("0").getCountry());
}
yields
[Singapore]
[]
Upvotes: 1
Reputation: 8011
As per your requirement, instead of writing 0 (""); //for null blank
, you can write like this.
ZERO ("NO-COUNTRY");
or
NO_COUNTRY("ZERO");
Upvotes: 0