14

in an interface, I store constants in this way (I'd like to know what you think of this practice). This is just a dummy example.

interface HttpConstants {
    /** 2XX: generally "OK" */
    public static final int HTTP_OK = 200;
    public static final int HTTP_CREATED = 201;
    public static final int HTTP_ACCEPTED = 202;
    public static final int HTTP_NOT_AUTHORITATIVE = 203;
    public static final int HTTP_NO_CONTENT = 204;
    public static final int HTTP_RESET = 205;
    public static final int HTTP_PARTIAL = 206;

        ...
}

Is there a way I can iterate over all constants declared in this interface ?

BuZz
  • 16,318
  • 31
  • 86
  • 141
  • Opinion: enums _do_ provide a lot of benefits in modern code, highly recommended. BUT not in all cases. Strings are used a lot analogue to "identifier" (e.g. attribute names, properties keys, JSF view IDs, JPA named query names and query placeholders, security roles, ...). Problem: string literals are _very_ easy to mistype, and have no compile time checking. I prefer to declare all such strings as constants, usually in an enum. HOWEVER, when using them as **annotation parameters**, enums aren't allowed and one still has to fall back on `public static final String`s similar to your code. – frIT Jun 25 '14 at 15:32

6 Answers6

21

Using reflection:

Field[] interfaceFields=HttpConstants.class.getFields();
for(Field f:interfaceFields) {
   //do something
}

But anyway, if you can redesign your class, I would recomend you to handle a static enum constants construction. So, suposing your class will contain always an int value for every constant:

enum HttpConstants {

    HTTP_OK(200), HTTP_CREATED(201), HTTP_ACCEPTED(202),
    HTTP_NOT_AUTHORITATIVE(203),HTTP_NO_CONTENT(204), 
    HTTP_RESET(205), HTTP_PARTIAL(206) /* ... */;

    private int value;

    HttpConstants(int aValue) {
        value=aValue;
    }

    public int getValue() {
        return value;
    }
}

Then, to loop on it:

    for(HttpConstants val: HttpConstants.values()) {
        int value=val.getValue();
            //...
    }

Thus, avoiding the access to the reflection API.

Tomas Narros
  • 13,390
  • 2
  • 40
  • 56
6

I would create these constants as an enumeration. Enums in Java can have their own fields and methods, which very convenient for your case. So I would do this the following way:

enum HttpConstant {
    HTTP_OK(200),
    HTTP_CREATED(201),
    HTTP_ACCEPTED(202),
    HTTP_NOT_AUTHORITATIVE(203),
    HTTP_NO_CONTENT(204),
    HTTP_RESET(205),
    HTTP_PARTIAL(206);

    private final int id;

    HttpConstant(int id) {
        this.id = id;
    }

    int getId() {
        return id;
    }
}

Now the iteration is easy:

for (HttpConstant constant : HttpConstant.values()) {
    //Do something with the constant
}

This way it is also easy to add associate some new values with the constants, you just have to add new fields.

Right now you may use reflection:

Field[] interfaceFields = HttpConstants.class.getFields();
for (Field field : interfaceFields) {
    int constant = field.getInt(null);
    //Do something with the field
}

However, it is better to use the approach with enums because with reflection coding errors result in runtime exceptions instead of compile-time errors.

Malcolm
  • 41,014
  • 11
  • 68
  • 91
4
for(Field f : HttpConstants.class.getFields()){
       int constant = f.getInt(null);
}
Esben Skov Pedersen
  • 4,437
  • 2
  • 32
  • 46
3
public enum HttpConstant {
    /** 2XX: generally "OK" */
    HTTP_OK(200).
    HTTP_CREATED(201),
    HTTP_ACCEPTED(202),
    HTTP_NOT_AUTHORITATIVE(203),
    HTTP_NO_CONTENT(204),
    HTTP_RESET(205),
    HTTP_PARTIAL(206);

    private int code;
    private HttpConstant(int code) {
        this.code = code;
    }

    public int getCode() {
        return code;
    }
}

with HttpConstant.values().

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
2

Well usually when i have something like that i make a Map in the interface that has the keys - constant names with values constant - values.

And that's how i can iterate over them.

Bogdan Emil Mariesan
  • 5,529
  • 2
  • 33
  • 57
1

I'd like to know what you think of this practice

Consider using an enum instead of an interface with constants.

enum HttpResultCode {
    HTTP_OK(200),
    HTTP_CREATED(201),
    HTTP_ACCEPTED(202),
    HTTP_NOT_AUTHORITATIVE(203),
    HTTP_NO_CONTENT(204),
    HTTP_RESET(205),
    HTTP_PARTIAL(206);

    private final int code;

    private HttpResultCode(int code) {
        this.code = code;
    }

    public int getCode(int code) {
        return code;
    }

    public static HttpResultCode forCode(int code) {
        for (HttpResultCode e : HttpResultCode.values()) {
            if (e.code == code) {
                return e;
            }
        }

        throw new IllegalArgumentException("Invalid code: " + code);
    }
}
Jesper
  • 202,709
  • 46
  • 318
  • 350