Java enums and Objective-C enums - java

I have the following enum in Objective-C:
typedef enum {
APIErrorOne = 1,
APIErrorTwo,
APIErrorThree,
APIErrorFour
} APIErrorCode;
I use the indexes to reference an enum from an xml, for example, xml may have error = 2, which maps to APIErrorTwo
My flow is I get an integer from the xml, and run a switch statement as follows:
int errorCode = 3
switch(errorCode){
case APIErrorOne:
//
break;
[...]
}
Seems Java dislikes this kind of enum in a switch statement:
In Java it seems you can't assign indexes to enum members. How can I get a Java equivalent of the above ?

Java enums have a built-in ordinal, which is 0 for the first enum member, 1 for the second, etc.
But enums are classes in Java so you may also assign them a field:
enum APIErrorCode {
APIErrorOne(1),
APIErrorTwo(27),
APIErrorThree(42),
APIErrorFour(54);
private int code;
private APIErrorCode(int code) {
this.code = code;
}
public int getCode() {
return this.code;
}
}

One question per post is the general rule here.
But evolving the JB Nizer answer.
public enum APIErrorCode {
APIErrorOne(1),
APIErrorTwo(27),
APIErrorThree(42),
APIErrorFour(54);
private final int code;
private APIErrorCode(int code) {
this.code = code;
}
public int getCode() {
return this.code;
}
public static APIErrorCode getAPIErrorCodeByCode(int error) {
if(Util.errorMap.containsKey(error)) {
return Util.errorMap.get(error);
}
//Or create some default code
throw new IllegalStateException("Error code not found, code:" + error);
}
//We need a inner class because enum are initialized even before static block
private static class Util {
private static final Map<Integer,APIErrorCode> errorMap = new HashMap<Integer,APIErrorCode>();
static {
for(APIErrorCode code : APIErrorCode.values()){
errorMap.put(code.getCode(), code);
}
}
}
}
Then in your code you can write
int errorCode = 3
switch(APIErrorCode.getAPIErrorCodeByCode(errorCode){
case APIErrorOne:
//
break;
[...]
}

Related

Get all static variables of a class without reflection

We have an exception Class A with a few fault codes defined as public static final and it is referenced in many files (more than 100) in our source code.
We want all these fault codes in Class B for some processing.
Currently we have implemented a method called getFaultCodes() in Class A to build a list of fault codes and return the same. The problem with this approach is that whenever an fault code is introduced, it has to be added in getFaultCode method as well. This is error prone, as a user may forget to add the new code to the method.
Moving these fault codes under an enum requires changes in many files all over the source code, so we don't want do this.
class ExceptionA {
public static final String faultCode1 = "CODE1";
public static final String faultCode2 = "CODE1";
public static final String faultCode3 = "CODE1";
List<String> getFaultCodes(){
list.add(faultCode1);
......
return list;
}
}
We are thinking about using reflection, but I'm posting in this forum just to check if there is a better solution. Please provide your suggestion to solve this problem.
Maybe you can go through an interface:
public interface FaultCodeProvider
{
String getFaultCode();
}
Then have your enums implement it:
public enum DefaultFaultCodes
implements FaultCodeProvider
{
FAULT1("text for fault 1"),
// etc
;
private final String value;
DefaultFaultCodes(final String value)
{
this.value = value;
}
#Override
public String getFaultCode()
{
return value;
}
}
Collecting them from the enum is then as easy as cycling through the enum's values().
I have modified code code like below:
class ExceptionA {
public enum codes {
CODE1("CODE1"),
CODE2("CODE2"),
CODE3("CODE3"),
private String code;
codes(String code){
this.code = code;
}
public String getCode() {
return this.code;
}
}
public static final String faultCode1 = code.CODE1;
public static final String faultCode2 = code.CODE2;
public static final String faultCode3 = code.CODE3;
}
So that I need not to change the variables occurrences "faultCode" in the source code, I can access the list of fault codes from other class.

Tuple Enum in Java

I'm very new in Java and were wondering and didn't find anything about it.
Can you create enum tuple ?
public enum Status {OPEN : "1", CLOSED: "2", DELETED: "3"}
I will need to access both "OPEN" or "1"
You could always create a custom constructor for your enum..
public enum Status {
OPEN("1"),
CLOSED("2"),
DELETED("3");
private String code;
public Status(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}
Then you can access with Status.OPEN.getCode(). This functions as an effective mapping between an enum type and a code value.
You can do something like this:-
public enum Currency {PENNY(1), NICKLE(5), DIME(10), QUARTER(25)};
But for this to work you need to define a member variable and a constructor because PENNY (1) is actually calling a constructor which accepts int value , see below example.
public enum Currency {
PENNY(1), NICKLE(5), DIME(10), QUARTER(25);
private int value;
private Currency(int value) {
this.value = value;
}
};
Constructor of enum in java must be private any other access modifier will result in compilation error. Now to get the value associated with each coin you can define a public getValue() method inside java enum like any normal java class. Also semi colon in the first line is optional.
private int getValue() { return value; }
and get values like this:-
PENNY.getValue(); //returns int 1
Refrence:
Solution by #christopher cover only first part. Creating ENUM.
You will need one more method that match code with enum value:
public static Status byCode(String code){
for(Status s : Status.values()) {
if (s.code.equals(code)) {
return s;
}
}
throw new IllegalArgumentException("Code does not match");
}
now you can get enum value by name and by code.

using enum in switch/case

I have an entity that has an enum property:
// MyFile.java
public class MyFile {
private DownloadStatus downloadStatus;
// other properties, setters and getters
}
// DownloadStatus.java
public enum DownloadStatus {
NOT_DOWNLOADED(1),
DOWNLOAD_IN_PROGRESS(2),
DOWNLOADED(3);
private int value;
private DownloadStatus(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
I want to save this entity in database and retrieve it. The problem is that I save the int value in database and I get int value! I can not use switch like below:
MyFile file = new MyFile();
int downloadStatus = ...
switch(downloadStatus) {
case NOT_DOWNLOADED:
file.setDownloadStatus(NOT_DOWNLOADED);
break;
// ...
}
What should I do?
You could provide a static method in your enum:
public static DownloadStatus getStatusFromInt(int status) {
//here return the appropriate enum constant
}
Then in your main code:
int downloadStatus = ...;
DowloadStatus status = DowloadStatus.getStatusFromInt(downloadStatus);
switch (status) {
case DowloadStatus.NOT_DOWNLOADED:
//etc.
}
The advantage of this vs. the ordinal approach, is that it will still work if your enum changes to something like:
public enum DownloadStatus {
NOT_DOWNLOADED(1),
DOWNLOAD_IN_PROGRESS(2),
DOWNLOADED(4); /// Ooops, database changed, it is not 3 any more
}
Note that the initial implementation of the getStatusFromInt might use the ordinal property, but that implementation detail is now enclosed in the enum class.
Every Java enum has an ordinal which is automatically assigned, so you don't need to manually specify the int (but be aware that ordinals start from 0, not 1).
Then, to get your enum from the ordinal, you can do:
int downloadStatus = ...
DownloadStatus ds = DownloadStatus.values()[downloadStatus];
... then you can do your switch using the enum ...
switch (ds)
{
case NOT_DOWNLOADED:
...
}

Better way to map from String constants to int constants in Java

I have a load of images of musical symbols which I need to do some processing on and for each one I need to get the integer code corresponding to its file name. There are 23 possible file name strings and 23 integer code and there are many images with the same name under different directories.
The solution I have so far is given (abbreviated) below. I have just defined a load of int and String constants and then written a method which is just a huge chain of if statements to do the translation.
What would be a better way to achieve the same effect? The way I've done it seems really awful! I thought about using some kind of Map, but I wasn't sure of the best way to do so.
public class Symbol {
public static final int TREBLE_CLEF = 0;
public static final int BASS_CLEF = 1;
public static final int SEMIBREVE = 2;
// ...
public static final String S_TREBLE_CLEF = "treble-clef";
public static final String S_BASS_CLEF = "bass-clef";
public static final String S_SEMIBREVE = "semibreve";
// ...
public static int stringCodeToIntCode(String strCode) {
if (strCode == S_TREBLE_CLEF) {
return TREBLE_CLEF;
} else if (strCode == S_BASS_CLEF) {
return BASS_CLEF;
} else if (strCode == S_SEMIBREVE) {
return SEMIBREVE;
} //...
else {
return -1;
}
}
}
I think you are looking for Enum where you can have String constant and its value.
Example:
public enum YourEnumClass{
STRING_CONST (5),
STRING_CONST2 (7),
.....
//constructor
//getValue() method
}
read linked tutorial for more details.
enum StringToInt{
TREBLE_CLEF(0),
......
}
Enum is the way to go.
Another example:
public enum Color {
WHITE(21), BLACK(22), RED(23), YELLOW(24), BLUE(25);
private int code;
private Color(int c) {
code = c;
}
public int getCode() {
return code;
}
how about a hashmap
HashMap<String,Integer> hm=new HashMap<String,Integer();
hm.put("treble-clef",0);
//rest
and get it by using this
int value=hm.get("treble-clef");

enum valueOf IllegalArgumentException: No enum const class

I have used enums in java in the past but for some reason I am getting a strange error right now. the Line of code that it is throwing the error is:
switch(ConfigProperties.valueOf(line[0].toLowerCase()){
...
}
I am getting a
java.lang.IllegalArgumentException: No enum const class
allautomator.ConfigProperties.language
in the example line is an array of Strings.
I am just really confused right now, I do not know what could possibly be wrong.
The enum constants are case sensitive, so make sure you're constants are indeed lower case. Also, I would suggest that you trim() the input as well to make sure no leading / trailing white-space sneak in there:
ConfigProperties.valueOf(line[0].toLowerCase().trim())
For reference, here is a working sample program containing your line:
enum ConfigProperties { prop1, prop2 }
class Test {
public static void main(String[] args) {
String[] line = { "prop1" };
switch (ConfigProperties.valueOf(line[0].toLowerCase())) {
case prop1: System.out.println("Property 1"); break;
case prop2: System.out.println("Property 2"); break;
}
}
}
Output:
Property 1
I am using a similar concept, but having a default value in case of fail
public enum SortType {
PRICE_ASC("price_asc"),
PRICE_DESC("price_desc"),
MODEL_ASC("model_asc"),
MODEL_DESC("model_desc");
private String name;
SortType(String name) {
this.name = name;
}
public String getName() {
return name;
}
static public SortType lookup(String id, SortType defaultValue) {
try {
return SortType.valueOf(id);
} catch (IllegalArgumentException ex) {
return defaultValue;
}
}
}

Categories