How to access constants from a java class through other variable? - java

I have java class which has all constants as given below:
public final class CategoryIDs {
public static final String Extraction_of_natural_gas = "1111";
public static final String Mining_of_hard_coal = "2222";
public static final String Mining_of_iron_ores = "3333";
public static final String Mining_of_lignite = "4444";
}
Now I want to access these constants in some other class through a variable which holds name of the variable.
For example:
String temp = "Extraction_of_natural_gas";
Using this temp variable I want to access constants from above class. But I can't do CategoryIDs.temp as it isn't allowed. So what is the best way to achieve this?

You can use reflection to extract it:
String value = (String) CategoryIDs.class.getField(temp).get(null);
The null argument passed to get signifies this is a static field, and no instance is required in order to get its value.
Note that this technique is very error prone. The code above doesn't contain any error checking or exception handling in order to make it easier to read, but a real application should probably contain them.

If you really, really need to do this with your current structure, you could use reflection.
However, you may well find that an enum would be a better fit. Something like:
public enum CategoryID {
EXTRACTION_OF_NATURAL_GAS("Extraction_of_natural_gas", 1111),
MINING_OF_HARD_COAL("Mining_of_hard_coal", 2222),
MINING_OF_IRON_ORES("Mining_of_iron_ores", 3333),
MINING_OF_LIGNITE("Mining_of_lignite", 4444);
private static final Map<String, CategoryID> keyMap;
static {
keyMap = new HashMap<>();
for (CategoryID category : CategoryID.values()) {
keyMap.put(category.getKey(), category);
}
}
private final String key;
private final int value;
public int getValue() {
return value;
}
public String getKey() {
return key;
}
private CategoryID(String key, int value) {
this.key = key;
this.value = value;
}
public static CategoryID fromKey(String key) {
return keyMap.get(key);
}
}
Benefits of this approach:
You separate the name in the code (which is now more conventional for Java) from the key you'd provide in the data. That means you can use whatever keys you'd like in the data, including ones with spaces in etc. They no longer need to be valid identifiers.
You still get compile-time safety when you refer to the enum values from code.
You get better safety as you'll never accidentally use a string instead of a category ID, which you could easily have done using your constants.

I think you are looking for introspection. This is the "read only" part of reflection, in which you can retrieve the value of an object.
The code would be as follows, pieced for ease of understanding:
Object value = null;
String constName = "Bar";
Field constant = Foo.class.getField( constName );
if ( constant != null ) {
value = constant.get( null );
}
if ( value != null ) {
System.out.println( value );
} else {
System.out.println( "Constant " + constName + " was not found." );
}
Interestingly, you can access the value from the Field object calling get(), and you pass null because the constant is static, and thus you don't have an instance to extract the value from.
You can find the whole code here: http://ideone.com/v4fcvH
Hope this helps.

Related

Enum with customized values and Default value

How to retrieve the enum name using value. By passing JOHN I need to retrieve the value as single
public enum Status {
JOHN("single"),
ALEX("married"),
MARTHA("not known");
}
Is it possible to have default value as well in-case value does not match?
To do this you need to define a constructor and a String variable. Then you could create a getter method to return the String variable:
public enum Status {
JOHN("single"),
ALEX("married"),
MARTHA("not known");
private String value;
private Status(String str) {
value = str;
}
public String getValue() {
return this.value;
}
}
And then to get the value you can do:
Status.JOHN.getValue()
To get the enum from a String you can use the valueOf() method:
Status.valueOf("JOHN").getValue();
However this will throw an error if the inputted String does not correspond to an enum. You could either wrap it in a try-catch to assign a default to it:
try {
Status.valueOf("JOHN").getValue();
} catch(IllegalArgumentException e) {
//Assign default
}
However a better design might be to put the possibilities into a HashMap and see if the inputted String is in the HashMap:
Map<String, Status> status = new HashMap<>();
status.put("JOHN", Y.JOHN);
if(status.containsKey(input)) {
//Do stuff
} else {
//Assign default
}
Define your enum like
enum Status {
JOHN("single"), ALEX("married"), MARTHA("not known");
private String value;
private Status(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
Now to fetch the value :
System.out.println(Status.JOHN.getValue());
Here define a parameterized constructor for each enum and store this value in a member variable.
A Java enum is an object, just like other objects in most ways. You can give it fields, methods, and constructors.
In this case, you can provide a marriage field and set it in a constructor just like you would for any other object.
Check out the official page on Java enums to see official examples, specifically the example with planets for your case. The Java Tutorials: Enum Types
Note also that you might not want to represent this specific data as an enum. You will be limited to only those 3 specific people by doing so. This is only appropriate if you know that you definitely will have only this specific list of people for the entire lifetime of this code. Otherwise you should just use a normal object.
A better idea might be to have a marriage enum and give your people a field of that type.
public enum MarriageStatus
{
Married,
NotMarried,
Unknown;
}
public class Person
{
String name = "Unknown";
MarriageStatus marriageStatus = MarriageStatus.Unknown;
}

associating int value to enum and getting corresponding int value

I have an enum and I have an integer value associated to each. One of my function accepts that enum. In the function body, I want to fetch the associated int value. How I am doing it right now is it to create a map (with enum as key, and integer code as value) in the static block and use this map to get code corresponding to an enum. Is this the right way of doing it ? Or is there any better established way to achieve the same ?
public enum TAXSLAB {
SLAB_A(1),
SLAB_B(2),
SLAB_C(5);
private static final Map<TAXSLAB, Integer> lookup = new HashMap<TAXSLAB, Integer>();
static {
for(TAXSLAB w : EnumSet.allOf(TAXSLAB.class)) {
lookup.put(w, w.getCode());
}
}
private int code;
private TAXSLAB(int code) {
this.code = code;
}
public int getCode() {
return code;
}
public static int getCode(TAXSLAB tSlab) {
return lookup.get(tSlab);
}
}
Here is the related SO post. But here answer is suggesting to create the map with int value as key as enum as value. So this can not be used to fetch numeric value using enum without iterating through the map
How to get enum's numeric value?
You do not need the map to retrieve code from an enum object, because the call of TAXSLAB.getCode(s) produces the same value as s.getCode():
TAXSLAB s = ...
int c1 = TAXSLAB.getCode(s);
int c2 = s.getCode();
// c1 == c2 here
int code is a field of enum TAXSLAB object, so you can get it directly.
This works for values associated with an enum from within the enum. If you need to associate a value with an enum outside the enum, the most performant way of doing it is by using EnumMap class designed specifically for this purpose.

Accessing string representations of constant field values in java

I am using an imported class with has constant field values set using:
public static final int BLUE = 1;
public static final int GREEN = 2;
etc.
Is there any way of getting a string representation of the constant field value from the int value?
i.e. given the value 2 I want to get a string of GREEN.
P.S. This isn't my class so I can't use ENUMs
I think your friend here would be enums
public enum Color {
BLUE(1), GREEN(2);
}
Now if you try to get Color.BLUE.ordinalValue() it will return 1 and if you say Color.BLUE.name() it will return BLUE.
You can also declare private variables in the enum just like a pojo class and initialize them un the constructor. You can write getter methods to return those variables.
If you can change the class which contains these constants, it would be better to make it an enum with a value() method.
Otherwise, I would suggest building a Map<Integer, String> once using reflection, and then just doing map lookups:
Map<Integer, String> valueToStringMap = new HashMap<>();
for (Field field : Foo.class.getFields()) {
int modifiers = field.getModifiers();
if (field.getType() == Integer.class && Modifier.isPublic(modifiers)
&& Modifier.isStatic(modifiers)) {
valueToStringMap.put((Integer) field.get(null), field.getName());
}
}

Java: Storing properties in an object

I have a class like the following:
public class Prefs {
public static final int PREF_NAME = 0;
public static final int PREF_SURNAME = 1;
public static final int PREF_LOCATION = 2;
String[] defaults = { "unknown", "unknown", "nowhere" }
String[] prefs;
public String getPref(int id) {
return prefs[id];
}
}
So I can use the following syntax:
Prefs p = new Prefs();
p.setDefaults() // irrelevant code not included
p.getPref(Prefs.PREF_LOCATION); // much more readable than getPref(2);
Is this approach correct? Are there any better options to do accomplish this?
EDIT: Please provide a simple example.
I think enum would be exactly what you need and perfect.
Either use enum or ValuedEnum (org.appache.commons), when values do not change.
In ValuedEnum you can provide custom texts, for a value, the standard enum uses the enum field name as text.
if you are using the java enum, consider using the approach where you explicitly assign a value to the enum (by providing an enum constrcutor with paramater "value").
From javarevisited :
public enum Currency {
PENNY(1), NICKLE(5), DIME(10), QUARTER(25);
private int value;
private Currency(int value) {
this.value = value;
}
};
This Valied enum approach is neccessary when you want to make sure that the values never changes (e.g for persitence). java ordinal() can not provide that.
If your list of elements in 'prefs' is going to be dynamic, you may want to consider using a hashtable: -
http://docs.oracle.com/javase/6/docs/api/java/util/Hashtable.html
This would allow you to have a key that would refer to the specific element.
(From the javadoc) This example creates a hashtable of numbers. It uses the names of the numbers as keys:
Hashtable numbers = new Hashtable();
numbers.put("one", new Integer(1));
numbers.put("two", new Integer(2));
numbers.put("three", new Integer(3));
To retrieve a number, use the following code:
Integer n = (Integer)numbers.get("two");
if (n != null) {
System.out.println("two = " + n);
}
Alternatively, you can use an ArrayList if you want random access.
http://docs.oracle.com/javase/6/docs/api/java/util/ArrayList.html

Library to print all public fields of nested Java objects?

I need to print all public fields of nested Java objects. These objects only contain data, no methods. On any level of object tree (except leaf nodes) fields may be Maps, Lists, Sets and arrays. Leaf nodes are primitive types.
Nested field should be printed as a string of the following format:
<fieldName1>.<fieldName2>. ... <fieldNameN>==<value>
where:
<fieldName1> -- root (top level) field name
<fieldNameN> -- N-level field name
<value> -- N-level field value.
Any library out there to solve this task?
The following example is far from being complete - it drafts a solution and shows some pitfalls:
public class Main {
private static Set<Object> visited = new HashSet<Object>();
public String s = "abc";
public int i = 10;
public Main INSTANCE = this;
public static void main (String[] args) throws Exception
{
printFields(new Main(), "");
}
private static void printFields(Object obj, String pre) throws Exception{
Field[] fields = obj.getClass().getFields();
for (Field field:fields) {
String value = "";
String type = field.getType().toString();
// handle primitve values
if (type.equals("int")) {
value += field.getInt(obj);
}
// handle special types, you may add Wrapper classes
else if (type.equals("class java.lang.String")) {
value = field.get(obj).toString();
}
// handle all object that you want to inspect
else {
if (visited.contains(field.get(obj))) {
// necessary to prevent stack overflow
value = "CYCLE DETECTED";
} else {
// recursing deeper
visited.add(field.get(obj));
pre += field.getName() + ".";
printFields(field.get(obj), pre);
}
}
System.out.printf("%s%s = %s%n", pre, field.getName(), value);
}
}
}
We find all we need in the reflection API
We need recursion to walk down the object tree
We need some special handling for primitives
We want some special handling for immutable types (e.g. we don't want to recurse into a String object
We need to take care if we visit an object twice.
Note - the code is pretty ugly, hope, it's enough to give you an idea
No library necessary. This is called Reflection in java. Have a look at the Class documentation using this you can do:
for(Field field : YourClass.class.getFields()){
//Print field info
}
Edit:
You can get the class of a Field by doing getDeclaringClass(). This class can be checked to see if it is a primitive by doing isPrimitive(). If it is you can print the value. If not you can recurse and print the fields for this field.

Categories