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));
5
  • 3
    No, that is not possible. What are you trying to accomplish? Commented May 23, 2013 at 19:20
  • I'd like to parse a String into an array of KeyEvents. Commented May 23, 2013 at 19:22
  • This is definitely possible; see my answer below. Whether it should be done is another question. :-) Commented May 23, 2013 at 19:57
  • @LairdNelson This seems like the best way to make a Robot write out a long text string. I'm not sure I understand why it shouldn't be done. Commented May 23, 2013 at 20:01
  • @JaredNielsen, you'd be much better off with using docs.oracle.com/javase/7/docs/api/javax/swing/… and going from there somehow. Commented May 23, 2013 at 21:01

6 Answers 6

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"));
Sign up to request clarification or add additional context in comments.

Comments

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)

1 Comment

Thanks! Reflection seems very interesting; I'm going to do some reading on that.
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);

Comments

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.

6 Comments

@leonbloy answered this at the same time I did; our answers are substantially similar; good luck!
Fair. But I don't quite agree with your asserts; those cases should be (at most) exceptions (see eg comments of this answer stackoverflow.com/a/2758262/277304 or this stackoverflow.com/questions/1276308/exception-vs-assertion)
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.
(Oh, and the assert field != null is also correct because if the field is not found a NoSuchFieldException will be thrown.)
Ah, it's ok then, my bad.
|
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.

1 Comment

Any reason for downvote? I'm not 100% sure what OP wants, but if I've made a mistake/assumption please tell.
-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());

6 Comments

Please post a code sample showing how to accomplish this with reflection.
No, you cannot do it with locals :)
@dasblinkenlight Not yet :D
@SeanBright how is it ?
@dasblinkenlight the above code should work
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.