I have an enumerator that takes an int and a string as fields. These are accessible via static methods or directly from the enumerator "instance" (not familiar with the proper wording for this). Here is what I mean by that:
public enum CreatureType {
POKE_PIG(1, "Piggley"), POKE_COW(2, "Cowbert");
private int number;
private String name;
CreatureType(int number, String name) {
this.number = number;
this.name = name;
}
public int getNumber() {
return number;
}
public String getName() {
return name;
}
public static String getName(CreatureType type) {
return type.getName();
}
public static int getNumber(CreatureType type) {
return type.getNumber();
}
But now I need to get a CreatureType FROM it's int. So here's my pseudocode I've written that is my best guess at how to do this:
public static CreatureType getCreatureType(int number) {
switch (number) {
case 1:
return CreatureType.POKE_PIG;
case 2:
return CreatureType.POKE_COW;
default:
break;
}
return null;
}
This feels weird though. I don't love this technique, and even though in theory it should work, I feel like there HAS to be a better way of doing this. I don't have these enums stored in a list or set or anything so I can't iterate through them, and I'm just blanking on the proper way to grab this.
Your switch-case solution is more efficient, but the following code is easier to maintain as it does not need adjustment when adding a new enum value:
public static CreatureType getCreatureType(int number) {
for(CreatureType creatureType : CreatureType.values()) {
if(creatureType.number == number) {
return creatureType;
}
}
return null; // No match.
}
Related
I would like to create a Java class that besides having integer types allows to have also some Enums, that is special values, a bit like Double.
Consider the case where you want to memorize an integer 0,1,100, 1000 or a special value like "0000" or "/" or "VAR";
I suppose your class has to contain those types? as in :
public class ExampleClass
{
// Instance Variables
int intTypeVar;
String stringTypeVar;
double doubleTypeVar;
// Constructor Declaration of Class
public ExampleClass (int intTypeVar, String stringTypeVar,
double doubleTypeVar)
{
this.intTypeVar= intTypeVar;
this.stringTypeVar= stringTypeVar;
this.doubleTypeVar= doubleTypeVar;
}
You can make your own exclusive type like this:
public class State {
JUST_AN_INTEGER,
CHEESE,
SOMETHING_ELSE;
}
public final class MyInteger {
private final int value;
private final State state;
private MyInteger(int value) {
this.value = value;
this.state = State.JUST_AN_INTEGER;
}
private MyInteger(State state) {
if (state == null) {
throw new IllegalArgumentException("State must be non-null");
} else if (state == State.JUST_AN_INTEGER) {
throw new IllegalArgumentException(State.JUST_AN_INTEGER + " requires a value!");
}
this.state = state;
}
public int getValue() {
if (state != State.JUST_AN_INTEGER) {
throw new IllegalStateException("MyValue has no value, it is of state " + state");
}
return value;
}
public int getState() {
return this.state;
}
#Override
public int hashCode() {
return this.value ^ this.state.hashCode();
}
#Override
public int equals(Object o) {
if (!(o instanceof MyInteger)) {
return false;
}
MyInteger other = (MyInteger) o;
return other.state == this.state && other.value == this.value;
}
#Override
public String toString() {
if (this.state == State.JUST_AN_INTEGER) {
return String.valueOf(this.value);
}
return this.state.name();
}
}
This MyInteger can either have a normal integer value or be of one of the other states. The constructors ensure that it's only ever constructed in a consistent way (for example you wouldn't want a JUST_AN_INTEGER constructed without an explicit value and equally you wouldn't want a CHEESE state to also contain a value).
You could also implement the Number class, but that would lead to all kinds of confusing behaviour, since it doesn't act like a normal Number in many cases.
How can I return enums like this?
Before I was returing an int with 0 if no, 1 if yes and 2 if other. But this wasn't good way to do. So how should it be done. My code:
class SomeClass{
public enum decizion{
YES, NO, OTHER
}
public static enum yourDecizion(){
//scanner etc
if(x.equals('Y')){
return YES;
}
else if (x.equals('N')){
return NO;
}
else{
return OTHER;
}
}
}
I don't what the "//scanner etc." does, but the methods return type should be decizion:
public static decizion yourDecizion() { ... }
Furthermore, you can add the Y, N, etc. values to the enum constants:
public enum decizion{
YES("Y"), NO("N"), OTHER;
String key;
decizion(String key) { this.key = key; }
//default constructor, used only for the OTHER case,
//because OTHER doesn't need a key to be associated with.
decizion() { }
static decizion getValue(String x) {
if ("Y".equals(x)) { return YES; }
else if ("N".equals(x)) { return NO; }
else if (x == null) { return OTHER; }
else throw new IllegalArgumentException();
}
}
Then, in the method, you can just do:
public static decizion yourDecizion() {
...
String key = ...
return decizion.getValue(key);
}
I think you should do something like these, an enum class. Then you can add as many types you want and the method yourDecizion() will return the enum type depending on the given parameter.
public enum SomeClass {
YES(0),
NO(1),
OTHER(2);
private int code;
private SomeClass(int code) {
this.code = code;
}
public int getCode() {
return code;
}
public static SomeClass yourDecizion(int x) {
SomeClass ret = null;
for (SomeClass type : SomeClass.values()) {
if (type.getCode() == x)
ret = type;
}
return ret;
}
}
Change your code to:
class SomeClass{
public enum decizion {
YES, NO, OTHER
}
public static decizion yourDecizion(){
//scanner etc
if(x.equals('Y')){
return decizion.YES;
}
else if (x.equals('N')){
return decizion.NO;
}
else{
return decizion.OTHER;
}
}
}
Note: The method return type must be decizion instead of enum and decizion should have an upper case name (as all classes should).
You can get the value in below way. Here you have private constructor which will initialize the value you want to set and when the instance method value gets invoked simply return this.key.
public class Application {
enum Day {
MONDAY("Monday"), TUESDAY("Tuesday");
String key;
Day(String str) {
key = str;
}
public String value() {
return this.key;
}
}
public static void main(String[] args) {
System.out.println(Day.MONDAY.value());
}
}
I need to write a Java enumeration LetterGrade that represents letter grades A through F, including plus and minus grades.
Now this is my enumeration code:
public enum Grade {
A(true),
A_PLUS(true),
A_MINUS(true),
B(true),
B_PLUS(true),
B_MINUS(true),
C(true),
D(true),
E(true),
F(false);
final private boolean passed;
private Grade(boolean passed) {
this.passed = passed;
}
public boolean isPassing() {
return this.passed;
}
#Override
public String toString() {
final String name = name();
if (name.contains("PLUS")) {
return name.charAt(0) + "+";
}
else if (name.contains("MINUS")) {
return name.charAt(0) + "-";
}
else {
return name;
}
}
What I am confused about is writing the main program. I think it could be quite straightforward but I have no clue on how to start it.
I don't want the whole code. Just a few lines to give me a head start. The rest I will try to figure out on my own.
I imagine you have a Student class that looks like this:
class Student {
protected Grade grade = null;
public Student(Grade g) {
this.grade = g;
}
}
Then you simply add a method in this class calling the isPassing method from your enum:
public boolean isPassing() {
if (this.grade != null)
return this.grade.isPassing();
return false;
}
This is supposing the passed boolean in Grade are correctly set and are invariant.
I'm trying to get the best way to implement a file with all my static enums, without using any getters and setters, just static info, I achieve this in PHP like in the example below, do you really need getters and setters in java?
final class EnumTrade {
const buy = 1;
const sell = 2;
}
final class EnumGender {
const male = 1;
const female = 2;
}
final class EnumHttpMethod {
const get = 1;
const post = 2;
}
public enum EnumTrade {
BUY, SELL
}
and so on.
Edit: If the number matters, do:
public enum EnumTrade {
BUY(1), SELL(2)
}
in java enum not necessary to have getter and setter these are used for normal POJO or beans
sample enum can be:
public enum EventRecurringType {
YEARLY("1"),
QUARTERLY("2"),
MONTHLY("3"),
WEEKLY("4"),
DAILY("5"),
NONE("0");
private String value;
EventRecurringType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
#Override
public String toString() {
return this.getValue();
}
public static EventRecurringType getEnum(String value) {
if(value == null)
throw new IllegalArgumentException();
for(EventRecurringType v : values())
if(value.equalsIgnoreCase(v.getValue())) return v;
throw new IllegalArgumentException();
}
}
public enum EnumTrade
{
BUY,
SELL,
}
If all you need is the ordinal values of the enums, you can access those directly via EnumTrade.BUY.ordinal
If you want to store other data in the enum, do something like this (expanding as needed):
public enum EnumGender
{
MALE(1),
FEMALE(2);
private final int value;
private EnumGender(String value)
{
this.value = value;
}
public int getValue()
{
return this.value;
}
//In case you need to grab an enum by the value constant
public getEnumGender(int value)
{
switch(value)
{
case 1:
return EnumGender.MALE;
case 2:
default:
return EnumGender.FEMALE;
}
}
}
For sake of completeness and the fact answers pop in while writing i changed my original answer to mention you could store all your enums in one java class.
=> It is way better to have them stored in own files like user Tichodroma suggests
However translating your exmaple code you could build this in Java:
public class MyEnums {
public enum EnumTrade{
BUY, SELL
}
public enum EnumGender{
MALE, FEMALE
}
public enum EnumHttpMethod{
GET, POST
}
}
And then use the different enums from outside like this:
MyEnums.EnumTrade.BUY
public enum MyConst{ BUY(1), SELL(2), MALE(3), FEMALE(4), GET(5), POST(6);
public final int value;
MyConst(int value) {
this.value = value;
}
public int getValue() {
return value;
}
};
or Just go with
public enum MyConst{ BUY(1), SELL(2) }; and same for MALE, FEMALE ....
Given the following java enum:
public enum AgeRange {
A18TO23 {
public String toString() {
return "18 - 23";
}
},
A24TO29 {
public String toString() {
return "24 - 29";
}
},
A30TO35 {
public String toString() {
return "30 - 35";
}
},
}
Is there any way to convert a string value of "18 - 23" to the corresponding enum value i.e. AgeRange.A18TO23 ?
Thanks!
The best and simplest way to do it is like this:
public enum AgeRange {
A18TO23 ("18-23"),
A24TO29 ("24-29"),
A30TO35("30-35");
private String value;
AgeRange(String value){
this.value = value;
}
public String toString(){
return value;
}
public static AgeRange getByValue(String value){
for (final AgeRange element : EnumSet.allOf(AgeRange.class)) {
if (element.toString().equals(value)) {
return element;
}
}
return null;
}
}
Then you just need to invoke the getByValue() method with the String input in it.
You could always create a map from string to value - do so statically so you only need to map it once, assuming that the returned string remains the same over time. There's nothing built-in as far as I'm aware.
According to effective java (2nd ed) item 30, it can be (it is much faster than the loop)
public enum AgeRange {
A18TO23("18-23"),
A24TO29("24-29"),
A30TO35("30-35");
private final String value;
AgeRange(String value){
this.value = value;
}
#Override public String toString(){
return value;
}
private static final Map<String, AgeRange> stringToEnum =
new HashMap<String, AgeRange>();
static {
for (AgeRange r : values()) {
stringToEnum.put(r.toString(), r);
}
}
public static AgeRange getByValue(String value){
return stringToEnum.get(value);
}
}
for (AgeRange ar: EnumSet.allOf(AgeRange)) {
if (ar.toString().equals(inString)) {
myAnswer = ar;
break;
}
}
Or something like that? Just typed in, haven't run through a compiler. Forgive (comment on) typos...
Or use logic like this to build a map once. Avoid iteration at runtime. Good idea, Jon.
The class overrides "toString()" - so, to get the reverse operation, you need to override valueOf() to translate the output of toString() back to the Enum values.
public enum AgeRange {
A18TO23 {
public String toString() {
return "18 - 23";
}
public AgeRange valueOf (Class enumClass, String name) {
return A18T023
}
},
.
.
.
}
Buyer beware - uncompiled and untested...
The mechanism for toString() and valueOf() is a documented part of the API
You could try something like the following?
static AgeRange fromString(String range) {
for (AgeRange ageRange : values()) {
if (range.equals(ageRange.toString())) {
return ageRange;
}
}
return null;
}
Or, as others suggested, using a caching approach:
private static Map<String, AgeRange> map;
private static synchronized void registerAgeRange(AgeRange ageRange) {
if (map == null) {
map = new HashMap<String, AgeRange>();
}
map.put(ageRange.toString(), ageRange);
}
AgeRange() {
registerAgeRange(this);
}
static AgeRange fromString(String range) {
return map.get(range);
}