4

Is there any way to implement this sort of code in Java?

int foo = 3;
String data = "foo";
System.out.println(StringToReference(data));

and print 3?

Edit: Specifically, I'd like to parse a String or char and return an int representing a KeyEvent. For example, I'd like to be able to do this:

for(char c : "hello")
    new Robot().keyPress(StringToReference("KeyEvent.VK_"+c));
Jared Nielsen
  • 3,669
  • 9
  • 25
  • 36

6 Answers6

6

Without knowing exactly what you are trying to accomplish, this is the closest I think you could get:

Map<String, Integer> map = new HashMap<String, Integer>();

map.put("foo", 3);

System.out.println(map.get("foo"));
Sean Bright
  • 118,630
  • 17
  • 138
  • 146
2

In general, in Java you can't reference variables by name (as strings, in runtime; what Perl calls "soft references"). But in some cases (fields, not local variables), you can get a similar behaviour with reflection.

For your intent, you can do this:

public static int getKeyEventVK(char c) throws 
                      IllegalArgumentException, SecurityException, 
                      IllegalAccessException, NoSuchFieldException {
    return KeyEvent.class.getField("VK_" + 
               String.valueOf(c).toUpperCase()).getInt(null);

}

public static void main(String[] args) throws Exception{
    System.out.println(getKeyEventVK('h'));
    System.out.println(KeyEvent.VK_H);
}       

But bear in mind that a typed string can trigger more than one VK_* event (eg. shift). And both H and h correspond to VK_H, so this will not exactly mimic the events triggered by typing the string hello (not to mention non-alphanumeric characters, dead keys, backspaces, etc etc)

leonbloy
  • 73,180
  • 20
  • 142
  • 190
1

Here's how to do this with reflection:

char c = "C";
Robot rob = new Robot();
Field field = KeyEvent.class.getDeclaredField("VK_"+c);         
int i = field.getInt(null);
rob.keyPress(i);
ashatch
  • 310
  • 1
  • 10
1

I see what you are trying to do. None of the other answers is correct.

You want to obtain the "correct" KeyEvent constant for a given character, and you want to do so without having to write some kind of lookup table that would be a zillion lines long.

Indeed, reflection will help you out here. It will be reasonably slow. But it will do the job. Whether the job actually needs doing is another question. :-)

The function in question you want is probably something like this:

/**
 * If possible, returns an {@code int} equal to one of the {@code public
 * static final int} constants present in the {@link KeyEvent} class
 * whose names start with {@code VK_}.
 *
 * <p>This implementation does no error handling whatsoever and has not
 * been tested or compiled.</p>
 * 
 * <p>This method is placed explicitly in the public domain.</p>
 *
 * @param c the character to use while searching for a field; no attempt
 * will be made by this implementation to validate it in any way
 *
 * @return a {@link KeyEvent} constant whose name starts with {@code VK_}
 *
 * @exception Exception for any of a number of possible reasons
 */
public int getKeyEventConstant(final char c) throws Exception {
  final Field field = KeyEvent.class.getField(String.format("VK_%S", Character.valueOf(c)));
  assert field != null;
  return field.getInt(null);
}

Then, you could feed it like the following, although you will have all sorts of problems if the supplied String contains characters the function I described above is not edited to deal with exceptions properly:

public  toKeyEventCodes(final String s) {
  int[] returnValue = null;
  if (s != null && !s.isEmpty()) {
    final Collection<Integer> codes = new ArrayList<Integer>(s.length());
    final char[] chars = s.toCharArray();
    assert chars != null;
    assert chars.length > 0;
    for (final char c : chars) {
      if (!Character.isWhitespace(c)) { // TODO: weed out other obvious dumb chars
        codes.add(Integer.valueOf(getKeyEventConstant(c)));
      }
    }
    returnValue = codes.toArray(new int[codes.size()]);
  }
  if (returnValue == null) {
    returnValue = new int[0];
  }
  return returnValue;
}

All of this code is untested. Good luck. I'm guessing that you still have something overly complicated going on but hopefully this will get you pointed in the right direction.

Laird Nelson
  • 15,321
  • 19
  • 73
  • 127
  • @leonbloy answered this at the same time I did; our answers are substantially similar; good luck! – Laird Nelson May 23 '13 at 19:58
  • Fair. But I don't quite agree with your `assert`s; those cases should be (at most) exceptions (see eg comments of this answer http://stackoverflow.com/a/2758262/277304 or this http://stackoverflow.com/questions/1276308/exception-vs-assertion) – leonbloy May 23 '13 at 20:24
  • `String#toCharArray()` is documented to never return `null`. So an `assert` is appropriate here (we are reifying the documentation). Additionally, we already checked `s.isEmpty()`. So it is impossible that the `char` array will have a length less than or equal to `0`. I stand by the assertions. – Laird Nelson May 23 '13 at 21:04
  • (Oh, and the `assert field != null` is also correct because if the field is not found a `NoSuchFieldException` will be thrown.) – Laird Nelson May 23 '13 at 21:15
  • Ah, it's ok then, my bad. – leonbloy May 23 '13 at 21:18
  • No worries! Now, you'd never use `assert` statements for argument checking, for example. – Laird Nelson May 23 '13 at 21:46
0

You can use the following code:

int foo = 3;
String data = Integer.toString(foo);

This will allow the int to be stored in a String file. I suppose you could pass it into your method and return whatever you want from it.

Although the above code will work, I'm not sure when you would use it.

Andrew Martin
  • 5,619
  • 10
  • 54
  • 92
-1

You can use java reflection.

Reflection for field

       Class<?> c = Class.forName("YOUR_CLASS_NAME");
       Field f = c.getField("FOO");
       System.out.println(f.getInt());
nidhin
  • 6,661
  • 6
  • 32
  • 50