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
Related
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.
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.
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());
}
}
Ok my problem isnt really a serious one, im just trying to find a clever way of access/modification of class member variables. Here is the code:
public class Storage{
private int cookies= 0;
private int rolls= 0;
private int candies= 0;
private int lolipops= 0;
private int iceCreams= 0;
public void addCookies(int howMuch){ //this is the dirty way of creating method for
this.cookies = cookies+howMuch; //every member variable
}
public void addValue(String stat, int howMuch){ //i would like to do it only
//by passing the name
//of variable and then cast it as integer
//so that it would relate to my class members
int value = this.(Integer.parseInt(stat)); // <- YES i know its ridiculous
//im just trying to explain what is my aim
value = value + howMuch;
this.(Integer.parseInt(stat)) = value;
}
}
Generally i would like to access a field by passing its name to a method, read value of that member, add to it some value, and then store it. Yes i know that it easily can be done with separate methods, or even with one by using some arraylist and comparisons of member names with parameter passed to method. But i would like to do it "fast" without redundant code writing.
Now i have like 5 members, but what about 15000? My aim is to simplify the whole processing and code writing. So generally is it possible to do such redundant code writing bypass? Since i know that i will always pass appropriate name to method... Unless the rule of thumb is to create method for each variable?
Normally you would use a collection like a Map.
public class Storage{
private final Map<String, Integer> inventory = ...
public void addCount(String key, int count) {
Integer i = inventory.get(key);
if (i == null) i = 0;
inventory.put(key, i + count);
}
I guess that by using reflection you can iterate through the fields/methods of your object and do your computation.
For one specific field:
Field member = myObject.getClass().getField(fieldName);
// If you know the class: Field member = MyClass.class.getField(fieldName);
System.out.println(member.getInt(myObject)); // Get the value
member.setInt(myObject, 4); // Set the value
If you want to something for all the public members:
for(Field member: myObject.getClass().getFields())
// Or you can do: for(Field member: myClass.class.getFields())
{
member.getInt(myObject)); // Get the value
member.setInt(myObject, 4); // Set the value
}
Basically, what you do is that you find the Field object that represents the members of you object, then you can manipulate it.
Most IDEs will generate setters and getters for you. This will do what you want with no bother or effort. If this is insufficient, write a method which uses reflection to set the values.
If you have a class with 15000 members, and by this I assume you mean variables private to a class, then you have other issues to resolve.
I'm trying to create a class that can instantiate arrays at runtime by giving each array a "name" created by the createtempobjectname() method. I'm having trouble making this program run. I would also like to see how I could access specific objects that were created during runtime and accessing those arrays by either changing value or accessing them. This is my mess so far, which compiles but gets a runtime exception.
import java.lang.reflect.Array;
public class arrays
{
private static String temp;
public static int name = 0;
public static Object o;
public static Class c;
public static void main(String... args)
{
assignobjectname();
//getclassname();//this is supposed to get the name of the object and somehow
//allow the arrays to become updated using more code?
}
public static void getclassname()
{
String s = c.getName();
System.out.println(s);
}
public static void assignobjectname()//this creates the object by the name returned
{ //createtempobjectname()
try
{
String object = createtempobjectname();
c = Class.forName(object);
o = Array.newInstance(c, 20);
}
catch (ClassNotFoundException exception)
{
exception.printStackTrace();
}
}
public static String createtempobjectname()
{
name++;
temp = Integer.toString(name);
return temp;
}
}
Create a Map then you can add key/value pairs when the key is your name and the value is your array.
Following up from #Ash's answer, here is some illustrative code. Notice that there is no reflection involved.
Map<String, Object> myMap = new HashMap<String, Object>();
...
Object myObject = ...
myMap.put("albert", myObject); // record something with name "albert"
...
Object someObject = myMap.get("albert"); // get the object named "albert"
// get("albert") would return null if there nothing with name "albert"
EDIT I've edited the example to use the type Object, since that is more closely aligned with what you are trying to do (I think). But you could use any type instead of Object ... just replace the type throughout the example. And you can do the same with an ArrayList; for example:
List<Date> dates = new ArrayList<Date>();
dates.add(new Date());
Date firstDate = dates.get(0);
Notice that no typecasts are required.
I expect you're getting a ClassNotFoundException from this line:
c = Class.forName(object);
The value of object the first time it's called is "1", which is not a valid class name.
Class.forName requires a class name as input, such as "java.lang.Integer". Trying to "name" your array in this way doesn't make sense to me. You need to pick an appropriate Java class name.
If you want to "name" an array instance (after you've created it), you could always store the instance as the value in a Map, using the name as the key.