1

I have a program with various ID constants like

final int MN=8;
final int PY=58;
final int RB=13;
...

these costants are index of elements in a matrix, for various reasons difficult to explain, will be good If I can do a method that receives two strings for example

Object getElement("MN","PY"){
    ...
}

to acts like

 Object o=mymatrix[MN][PY];

using the passed strings to reference declared fields

Is there any way to do this accessing the fields directly (without puth them in a Map or use switch and if else condition for every field)?

6
  • Is there a pattern the letters and numbers follow? Can you just place them in an enum and refer to their ordinal? For example enum x { AA, BB, CC, DD } then making a call to x.AA.ordinal() would return 0, BB is 1, and so forth. Commented Mar 6, 2014 at 2:36
  • no, the names of fields are random Commented Mar 6, 2014 at 2:41
  • Can you post more of those constants? How many are there? You should place them in a Map at run time as a key/value pair. "MN" or "PY" being the key, 8 or 58 being the values. Commented Mar 6, 2014 at 2:46
  • 1
    It's easy, you can use a find/replace in a text editor to change it to a map. Add all 617 variables to www.pastebin.com and I will format it for you. Commented Mar 6, 2014 at 2:54
  • 1
    Slightly outside the square, but you could even copy/paste the whole lot into a properties file, and just search/replace the spaces to dots and the semicolons to nothing. Then use properties.getProperty("final.int." + fieldName); in your code. Commented Mar 6, 2014 at 3:07

4 Answers 4

2

Here is an illustration of how you can do this using reflection.

public class Matrix {
    private Object[][] values = new Object[100][100];
    private final int MN=8;
    private final int PY=58;
    private final int RB=13;

    public static void main(String[] args){
        Matrix matrix = new Matrix();
        matrix.values[8][58] = "Hello";
        try {
            System.out.println(matrix.getElement("MN","PY"));
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }

    }

    public Object getElement(String rowConstant, String columnConstant) 
    throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
        return values[getConstant(rowConstant)][getConstant(columnConstant)];
    }

    private int getConstant(String constant) 
    throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
        return getClass().getDeclaredField(constant).getInt(this);
    }
}

See how in the main method, I put an object into the array, and then use reflection to retrieve it.

I entirely do not recommend this technique. I've only put this answer here because you specifically asked me for it. I really think you're going about this the wrong way.

If you have a small number of constants, you should be using a HashMap or some similar structure. If you really do have 617 of them, you should be using some kind of data file, or a properties file, or a database. There's no way you want a big long list of constants to be part of your source code.

Sign up to request clarification or add additional context in comments.

Comments

2

I think you can check this link out: Get variable by name from a String

There are four interesting suggestions there, using different approaches: Reflection, Map, Guava and Enum.

-------------- EDITED ANSWER ------------- (With contributions from David Wallace)

Please check the following program out:

import java.lang.reflect.Field;

public class Main
{

    public final static int MN = 0;
    public final static int PY = 1;
    public final static int RB = 2;

    private static int[][] myMatrix = new int[][]
    {
        { 1, 2, 3 },
        { 10, 20, 30 },
        { 100, 200, 300 }
    };

    public static void main( String[] args ) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException
    {
        System.out.println( getElement( "MN", "PY" ) );
        System.out.println( getElement( "PY", "RB" ) );
        System.out.println( getElement( "RB", "RB" ) );


    }

    public static int getElement( String i0, String i1 ) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException
    {
        return myMatrix[ getValueByName( i0 )] [ getValueByName( i1 ) ];
    }
    public static int getValueByName( String varName ) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException
    {

        Field f = Main.class.getField( varName );
        return f.getInt( f );
    }
}

The output is: 2, 30, 300. Does it respond your question?

7 Comments

thanks for answer but I'm looking for a way that don't obbligate me to put every variable in a Map or use switch. Is there no way to access fields directly?
You're welcome. Would you give an example with the code you want, please?
Hi, AndreaF. I just edited my answer to give you a possible solution to the problem you presented.
Better to use getField (as per the comment under my answer) than to iterate through all 617 of them.
Yes. It's much better. I'm editing the code. Thank you David Wallace.
|
1

There are lots of ways to do this, but by far the simplest is to put all your constants in a HashMap and use get whenever you want to refer to one.

6 Comments

thanks for suggewstion but I'm looking for a way that don't obbligate me to put every variable in a Map or use switch. Is there no way to access fields directly?
Well, you could use reflection, but it's rather more complicated and error-prone than just using a map.
I prefer take this risk because otherwise I have to write an huge number of codelines. XD could you give me more details on how to use reflection to do this? Thanks
Oh, you'll have to write much more code to do it with reflection, because there are all sorts of checked exceptions that just make things messy. I still advise using a map - it takes only one more line of code than declaring all the constants anyway, because you'll replace final int MN=8; with constants.put("MN",8); and the only extra line you need is the one where you create the map. I really can't fathom why you wouldn't want to do this. But if you want the longer and more complex reflection-based solution, I'll post it in a little while.
thanks for the advice but I would be really grateful if you let me see the reflection based solution.
|
0

Consider revisiting your original assumptions. Looking up variables by name at runtime is not a great approach, esp. in Java. It's making your task harder than necessary. Also more fragile -- variables may be renamed by processing tools such as Proguard.

Where did all the constant definitions final int MN=8; ... come from in the first place? If they're generated by code, then you'd be better off making it instead generate code that constructs a HashMap, or a data file that you can read into a HashMap. Or if you have to start with those constant definitions, write a little program that reads that source code text and constructs a HashMap.

The final int definitions aren't doing you much good in their current form.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.