This is a simple question:
Is it possible to have an enum with a variable value ?
To be clear i would like to create an enum corresponding to an error code returned by a function which is two bytes, so i would like to do something like
public enum ErrorCode {
ERR_NONE ((byte)0x9000), // No error
ERR_PARAM ((byte)0x8200), // Parameter error
ERR_DATA ((byte)0x83XX), // XX could be any value
}
how to return ERR_DATA for all values beginning by 0x83 ?
Is it possible ?
Thanks
CodePudding user response:
Here's an implementation following Dawood ibn Kareem's suggestion in comments above.
Some points:
- This implementation throws an exception if a code matches two enum values. You would need to decide whether you wanted that behaviour, or just return the first match. In that case the ordering of the enum values becomes significant.
- You can add new constructors for common cases, e.g. I have one for a value which matches a single code. You could add one for a value which matches a range of codes.
- You might also want to throw an exception if no
ErrorCode
matches the integer code. This implementation returnsnull
in that case, so you'll get an NPE if the caller doesn't check fornull
, but you won't know what value triggered it.
import java.util.function.Predicate;
public enum ErrorCode {
ERR_NONE (0x9000), // No error
ERR_PARAM (0x8200), // Parameter error
ERR_DATA (n -> (n >= 0x8300 && n <= 0x83FF)), // 0x83XX
ERR_ANOTHER_83 (0x8377);
private final Predicate<Integer> forValue;
ErrorCode(Predicate<Integer> matches) {
this.forValue = matches;
}
ErrorCode(int singleValue) {
this(n -> n == singleValue);
}
public static ErrorCode forInt(int code) {
ErrorCode matchingCode = null;
for (ErrorCode c : ErrorCode.values()) {
if (c.forValue.test(code)) {
if (matchingCode != null) {
throw new RuntimeException("ErrorCodes " matchingCode.name()
" and " c.name() " both match 0x"
Integer.toHexString(code));
} else {
matchingCode = c;
}
}
}
return matchingCode;
}
public static void main(String[] args) {
System.out.println(ErrorCode.forInt(0x8312));
System.out.println(ErrorCode.forInt(0x9000));
System.out.println(ErrorCode.forInt(0x8377));
}
}
CodePudding user response:
Write a method which, given 0x83NN as input, returns ERR_DATA. Done.
ErrorCode errorCode(int n) {
if (n == 0x9000)
return ERR_NONE;
else if (n == 0x8200)
return ERR_PARAM;
else if (n >= 0x8300 && n <= 0x83ff)
return ERR_DATA;
else
throw new IllegalArgumentException();
}
You have to write code to look up the value in any case. There's no intrinsic 'associate this integer value with this enum constant, and provide a lookup for enum constant given an integer value'.
Note that, for this, there's no need to store the numeric value inside each member of the enum. And also note that your constructor calls like ERR_NONE(0x9000) are not valid unless you've defined a suitable constructor. And if you do define a suitable constructor, you'll need to decide on a single value for the argument of ERR_DATA.
CodePudding user response:
I believe it cannot be the case. According to Oracle Doc,
An enum type is a special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it.