Reflection - Getting different results from HashMap - LinkedHashMap - java

I'll keep it brief, I have a Dog class like the following:
public class Dog
{
public void Foo()
{
System.out.println("Right Call");
}
public void Boo()
{
System.out.println("Wrong Call");
}
}
and a main method like following:
HashMap<String, Method> map = new HashMap<String, Method>();
Dog d = new Dog();
Method[] method = d.getClass().getMethods();
map.put("foo", method[0]);
Method a = map.get("foo");
try {
a.invoke(d, null);
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
e.printStackTrace();
}
Whenever I run it again, it just arbitrarily gives Right Call or Wrong Call outputs.
I need to be sure that every time I place the "foo" key, It must to be calling the Foo() method, instead of Boo().
Apparently, It doesn't ease my "method call" problem. How can I overcome this issue? I must be calling the right method every time. I'm quite new to this reflections stuff, is there anything that I shouldn't be doing, or something that I'm doing wrong? Or is there a better way to implement this method calling?
EDIT: I've also tried LinkedHashMap, however, the result is the same.
Thank you.

From the javadoc of Class.getMethods():
The elements in the array returned are not sorted and are not in any particular order.
Yet, your code assumes that the element at index 0 is the method Foo(). Don't make this assumption. Find the method which has the name Foo.
That said, Reflection is probably not the right tool for the job you're trying to do. You should explain, at a higher level, what you're trying to do and why you think using reflection is a good idea. Usually, it's not.

This has nothing to do with putting the method in a map, as far as I can tell - you can remove the map part entirely and still face the same issue:
Dog d = new Dog();
Method methods = d.getClass().getMethods();
Method a = methods[0];
try {
a.invoke(d, null);
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
e.printStackTrace();
}
Fundamentally, you're seeing the fact that getMethods() doesn't return the methods from a class in an order you should rely on. If you want to specifically call your Foo method (which should be foo to follow Java naming conventions), you should probably be using Class.getMethod("foo") to get the method by name.

Result of getMethods() is not sorted, so there is no guarantee that method[0] is Foo() (not Boo()). You need to check it before put to map as a value for "foo" key.

You could off course also use the following reflection:
Dog d = new Dog();
map.put("foo", d.getClass().getMethod("Foo");
Method m = map.get("foo");
m.invoke()
This code is obviously missing all the try catch and some other stuff, but it does show you the important bit. You should never rely on the order in the getMethods(). Instead, if you know what the method is called, always use the getMethod call to get it by name. This way, you're sure to get the correct method.

I think the Map has caused a bit of a red herring.
Dog d = new Dog();
try {
d.getClass.getMethod("Foo").invoke(d, null);
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
Not one hundred percent sure on this, but I believe that you will also need to catch NoSuchMethodException.
I will say, unless you are just trying to learn about the reflection api, I would think twice before using reflection. In most cases, it is not the right tool for the job.

Related

How to use Method Reference operator to get the reference of method

I want to reference an annotation value in one class from another class. Like here -
class A {
private static final String STATIC_STRING = B.class.getMethod("myMethod").getAnnotation(SomeAnnotation.class).name();
}
The problem here is that I cannot use this syntax because it requires getMethod to be wrapped in a try-catch which is not possible. Although I can use a static block to create this variable and just gulp the exception in catch block, I don't want to do that because if in future the method name is changed, compiler won't throw an error in the static block.
I was wondering if I could do something like
private static final String STATIC_STRING = (B::myMethod).getAnnotation(SomeAnnotation.class).name();
Note: neither B nor SomeAnnotation is my source, they come from another library.
I have 2 questions here
Is there a better way to get value from annotation, preferably without using any external library like Google Reflections or similar?
How can I use :: to get instance of java.lang.reflect.Method? Is it possible altogether? If yes, is vice-versa also possible, i.e. create supplier or mapper from Method's object?
For your first question, have you considered using a getter?
private static String getSomeAnnotationName() {
try {
return B.class.getMethod("myMethod").getAnnotation(SomeAnnotation.class).name();
} catch (NoSuchMethodException e) {
return null;
}
}
For your second question, I don't think getting a Method from :: is possible. This is because methods got from :: represent implementations of functional interfaces, not really methods. However, the reverse is possible. You can create a lambda like this:
Consumer<SomeType> consumer = x -> {
try {
yourMethod.invoke(someObject, x)
} catch (...) {
// again you have to ignore the exceptions here, unfortunately
}
};

What to return when generic methods returns 'nothing' but null can't be returned?

Suppose I have a library method like this (very abbreviated):
public static <V> Optional<V> doSomethingWith(Callable<V> callable) {
try {
return Optional.of(callable.call());
} catch (Exception ex) {
// Do something with ex
return Optional.empty();
}
}
And I want to something that doesn't return a value, like:
Library.</*What1*/>doSomethingWith(() -> {
foo();
return /*what2*/;
});
My first instinct for a generic method that doesn't return a value is making the type Void and returning null, however because the result gets wrapped in an Optional this would throw an exception.
What are reasonable placeholders for /*What1*/ and /*what2*/ that don't look totally random like Integer and 0?
[edit]
I'm trying to avoid Optional.ofNullable because empty is used here to indicate that callable.call() did not complete normally.
If you need a type hint for a generic parameter that will never be used you can use Void, the JDK does this too in some cases, e.g. when converting Runnable into CompletableFuture<T> it uses Void for T.
If you use Optional.ofNullable then you can just return null for what2, which is the only valid value for Void.
[edit] I'm trying to avoid Optional.ofNullable because empty is used here to indicate that callable.call() did not complete normally.
Then you're using the wrong tool for the job. CompletionStage or CompletableFuture has the right semantics.
I usually use Boolean.TRUE to mark success, but you could return Void.class as well. Both are cheap in the sense that not every return creates a new object to be discarded. Though Class<Void> is not just Void it may serve the purpose of labelling something as void just as well.
As already mentioned you could also create your own Result-class/-enum.
Or you could of course return Optional.<Void>nothing(), too. This would result in some Optional<Optional<Void>>, but also do the trick.
If you think all of the above is ugly, I fear that the API probably isn't to well tailored to your needs. Raise an issue/pull request or look for something else.
You could also create your own type similar to Void
public class Result {
public static final Result OK = new Result();
private Result(){}
}
and then return Result.OK.
You can also enhance this type to represent also errors, if you need.
But maybe using java Void is preferable if you don't need anything special.
Use Void for the return type, which is the logical choice for "nothing", but actually return an instance of Void.
Although the javadoc for Void says it's:
...an uninstantiable placeholder class...
You can nevertheless instantiate it:
try {
Constructor<Void> c = Void.class.getDeclaredConstructor();
c.setAccessible(true);
return c.newInstance();
} catch (Exception perfunctory) {
return null; // won't happen
}

Invisible Objects in java

The following code is part of a larger application:
public static void METHOD_NAME(Object setName, int setLength){
tryLoop:
for( ; ; ){
try{
setName = new Stack(setLength);
break tryLoop;
}catch (InstantiationException e){
System.err.println(e.getMessage());
SET_NUM(1);
continue tryLoop;
}
}
}
Whenever I try to use the stack object that was initialized within the try block, it cannot be found unless the reference to it is within the try block. Why is this and how can I avoid it in the future?
I suspect you're under the impression that this:
setName = new Stack(setLength);
will have some impact on the argument passed in by the caller. It won't. Java is strictly pass-by-value, whether that value is a primitive type value or a reference.
In other words, if you do this:
Object foo = null;
METHOD_NAME(foo, 5);
then foo will still be null afterwards.
I suggest you return the value from your method instead. For example:
public static Stack METHOD_NAME(Object setName, int setLength){
while(true) {
try {
return new Stack(setLength);
} catch (InstantiationException e){
System.err.println(e.getMessage());
SET_NUM(1);
}
}
}
Note the return instead of breaking to a label, and while(true) which I find more readable than for (; ;).
Well, that method is ... pretty unorthodox Java code, to say at least.
Additionally it doesn't seem to have any meaningful result whatsoever. It sets its own parameter to a new value (entirely ignoring the original one) and never returns anything or modifies any object that it gets passed.
So unless the construction of a Stack object has some effect that is visible from the outside, this methods doesn't do anything useful (in the "no-exception" case).
Declare a method scode variable before your try block and assign setName to it. Then assign new Stack() to that variable in your try block and return it at the end of your method.
Modifying the value of a parameter is usually bad practice anyways.
No idea what you're using a label for -- continue; will work fine. Other things are a bit suspect here too. The scope for a variable declared inside a try block is just the try block. Setting 'setName' will do nothing as Java passes an object, and changing the reference to point to a new object will not affect the passed object. As for not being able to use setName in the current bit of code, you can avoid it by taking it outside of the block, or doing everything you need to inside the try block :) You can also return it to allow the caller to use it. Why are you trying to catch InstantiationException? You'd be better off checking that setLength is a valid size and let uncaught exceptions validate the integrity of Java itself.
Java does not support pass-by-reference, so the assignment to setName does not pass any value back to the caller.
The obvious rewrite of your code is as follows:
public static Object METHOD_NAME(int setLength) {
while (true) {
try {
return new Stack(setLength);
} catch (InstantiationException e){
System.err.println(e.getMessage());
SET_NUM(1);
}
}
}

Get instanced object by String

Is it possible to get a Object that is instanced in the Code by a String at Runtime?
Somthing like that:
public String xyz = "aaaa_bbb";
getObject("xyz").some function of String (e.g.: .split("_"))
Thanks
Here's an example
If it's a class field, you can get it by name like this.
import java.lang.reflect.Method;
public class Test {
public String stringInstance = "first;second";
public void Foo() {
try {
Object instance = getClass().getDeclaredField("stringInstance").get(this);
Method m = instance.getClass().getMethod("split", String.class);
Object returnValue = m.invoke(instance, ";");
if(returnValue instanceof String[])
{
for(String s : (String[])returnValue )
{
System.out.println(s);
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String a[]){
new Test().Foo();
}
}
If it's a local method variable you are trying to invoke on, then you might be able to get at to the variable in from the current method from the call stack Thread.currentThread().getStackTrace() maybe.
It is hard to make out what you are asking, but you can fetch field values by name using reflection. Something like this:
Class c = this.getClass(); // or Someclass.class
Field f = c.getDeclaredField("xyz");
String value = (String) f.get(this);
... = value.split("_");
(I've left out a lot of exception handling ...)
But as a comment points out, if you are really trying to implement an associative array, there are better ways of doing this in Java; e.g. using a Map class.
You might have to rephrase the question.
If you just want to get the "aaaa" and "bbb" strings from the initial string, you can use StringTokenizer
If your String is a member field of your object, you can go take a look at the Field class.
However, I have to warn you that the code that you'll end up with will be by far longer than what you expect here. Indeed, you'll have to do some operations :
Get the Field obejct associated to xyz
Get method from its name and parameters list (using as an example Class#getDeclaredMethod(...))
Invoke the method on this particular instance
Each of these steps will eb a rather obscure line of code, with a bunch of throwed exceptions.
So, if you have an alternative, well, use it !
I have custom components on a jPanel and i would like to work with them without repainting them. I knwo if i use a List or Map that it is possible but i have to change the value in the Map and then repaint the GUI with the infomration in the Map.

java: How can I do dynamic casting of a variable from one type to another?

I would like to do dynamic casting for a Java variable, the casting type is stored in a different variable.
This is the regular casting:
String a = (String) 5;
This is what I want:
String theType = 'String';
String a = (theType) 5;
Is this possible, and if so how? Thanks!
Update
I'm trying to populate a class with a HashMap that I received.
This is the constructor:
public ConnectParams(HashMap<String,Object> obj) {
for (Map.Entry<String, Object> entry : obj.entrySet()) {
try {
Field f = this.getClass().getField(entry.getKey());
f.set(this, entry.getValue()); /* <= CASTING PROBLEM */
} catch (NoSuchFieldException ex) {
log.error("did not find field '" + entry.getKey() + '"');
} catch (IllegalAccessException ex) {
log.error(ex.getMessage());
}
}
}
The problem here is that some of the class' variables are of type Double, and if the number 3 is received it sees it as Integer and I have type problem.
Yes it is possible using Reflection
Object something = "something";
String theType = "java.lang.String";
Class<?> theClass = Class.forName(theType);
Object obj = theClass.cast(something);
but that doesn't make much sense since the resulting object must be saved in a variable of Object type. If you need the variable be of a given class, you can just cast to that class.
If you want to obtain a given class, Number for example:
Object something = new Integer(123);
String theType = "java.lang.Number";
Class<? extends Number> theClass = Class.forName(theType).asSubclass(Number.class);
Number obj = theClass.cast(something);
but there is still no point doing it so, you could just cast to Number.
Casting of an object does NOT change anything; it is just the way the compiler treats it.
The only reason to do something like that is to check if the object is an instance of the given class or of any subclass of it, but that would be better done using instanceof or Class.isInstance().
Update
according your last update the real problem is that you have an Integer in your HashMap that should be assigned to a Double. What you can do in this case, is check the type of the field and use the xxxValue() methods of Number
...
Field f = this.getClass().getField(entry.getKey());
Object value = entry.getValue();
if (Integer.class.isAssignableFrom(f.getType())) {
value = Integer.valueOf(((Number) entry.getValue()).intValue());
} else if (Double.class.isAssignableFrom(f.getType())) {
value = Double.valueOf(((Number) entry.getValue()).doubleValue());
} // other cases as needed (Long, Float, ...)
f.set(this, value);
...
(not sure if I like the idea of having the wrong type in the Map)
You'll need to write sort of ObjectConverter for this. This is doable if you have both the object which you want to convert and you know the target class to which you'd like to convert to. In this particular case you can get the target class by Field#getDeclaringClass().
You can find here an example of such an ObjectConverter. It should give you the base idea. If you want more conversion possibilities, just add more methods to it with the desired argument and return type.
Regarding your update, the only way to solve this in Java is to write code that covers all cases with lots of if and else and instanceof expressions. What you attempt to do looks as if are used to program with dynamic languages. In static languages, what you attempt to do is almost impossible and one would probably choose a totally different approach for what you attempt to do. Static languages are just not as flexible as dynamic ones :)
Good examples of Java best practice are the answer by BalusC (ie ObjectConverter) and the answer by Andreas_D (ie Adapter) below.
That does not make sense, in
String a = (theType) 5;
the type of a is statically bound to be String so it does not make any sense to have a dynamic cast to this static type.
PS: The first line of your example could be written as Class<String> stringClass = String.class; but still, you cannot use stringClass to cast variables.
You can do this using the Class.cast() method, which dynamically casts the supplied parameter to the type of the class instance you have. To get the class instance of a particular field, you use the getType() method on the field in question. I've given an example below, but note that it omits all error handling and shouldn't be used unmodified.
public class Test {
public String var1;
public Integer var2;
}
public class Main {
public static void main(String[] args) throws Exception {
Map<String, Object> map = new HashMap<String, Object>();
map.put("var1", "test");
map.put("var2", 1);
Test t = new Test();
for (Map.Entry<String, Object> entry : map.entrySet()) {
Field f = Test.class.getField(entry.getKey());
f.set(t, f.getType().cast(entry.getValue()));
}
System.out.println(t.var1);
System.out.println(t.var2);
}
}
You can write a simple castMethod like the one below.
private <T> T castObject(Class<T> clazz, Object object) {
return (T) object;
}
In your method you should be using it like
public ConnectParams(HashMap<String,Object> object) {
for (Map.Entry<String, Object> entry : object.entrySet()) {
try {
Field f = this.getClass().getField(entry.getKey());
f.set(this, castObject(entry.getValue().getClass(), entry.getValue()); /* <= CASTING PROBLEM */
} catch (NoSuchFieldException ex) {
log.error("did not find field '" + entry.getKey() + '"');
} catch (IllegalAccessException ex) {
log.error(ex.getMessage());
}
}
}
It works and there's even a common pattern for your approach: the Adapter pattern. But of course, (1) it does not work for casting java primitives to objects and (2) the class has to be adaptable (usually by implementing a custom interface).
With this pattern you could do something like:
Wolf bigBadWolf = new Wolf();
Sheep sheep = (Sheep) bigBadWolf.getAdapter(Sheep.class);
and the getAdapter method in Wolf class:
public Object getAdapter(Class clazz) {
if (clazz.equals(Sheep.class)) {
// return a Sheep implementation
return getWolfDressedAsSheep(this);
}
if (clazz.equals(String.class)) {
// return a String
return this.getName();
}
return null; // not adaptable
}
For you special idea - that is impossible. You can't use a String value for casting.
Your problem is not the lack of "dynamic casting". Casting Integer to Double isn't possible at all. You seem to want to give Java an object of one type, a field of a possibly incompatible type, and have it somehow automatically figure out how to convert between the types.
This kind of thing is anathema to a strongly typed language like Java, and IMO for very good reasons.
What are you actually trying to do? All that use of reflection looks pretty fishy.
Don't do this. Just have a properly parameterized constructor instead. The set and types of the connection parameters are fixed anyway, so there is no point in doing this all dynamically.
For what it is worth, most scripting languages (like Perl) and non-static compile-time languages (like Pick) support automatic run-time dynamic String to (relatively arbitrary) object conversions. This CAN be accomplished in Java as well without losing type-safety and the good stuff statically-typed languages provide WITHOUT the nasty side-effects of some of the other languages that do evil things with dynamic casting. A Perl example that does some questionable math:
print ++($foo = '99'); # prints '100'
print ++($foo = 'a0'); # prints 'a1'
In Java, this is better accomplished (IMHO) by using a method I call "cross-casting".
With cross-casting, reflection is used in a lazy-loaded cache of constructors and methods that are dynamically discovered via the following static method:
Object fromString (String value, Class targetClass)
Unfortunately, no built-in Java methods such as Class.cast() will do this for String to BigDecimal or String to Integer or any other conversion where there is no supporting class hierarchy. For my part, the point is to provide a fully dynamic way to achieve this - for which I don't think the prior reference is the right approach - having to code every conversion. Simply put, the implementation is just to cast-from-string if it is legal/possible.
So the solution is simple reflection looking for public Members of either:
STRING_CLASS_ARRAY = (new Class[] {String.class});
a) Member member = targetClass.getMethod(method.getName(),STRING_CLASS_ARRAY);
b) Member member = targetClass.getConstructor(STRING_CLASS_ARRAY);
You will find that all of the primitives (Integer, Long, etc) and all of the basics (BigInteger, BigDecimal, etc) and even java.regex.Pattern are all covered via this approach. I have used this with significant success on production projects where there are a huge amount of arbitrary String value inputs where some more strict checking was needed. In this approach, if there is no method or when the method is invoked an exception is thrown (because it is an illegal value such as a non-numeric input to a BigDecimal or illegal RegEx for a Pattern), that provides the checking specific to the target class inherent logic.
There are some downsides to this:
1) You need to understand reflection well (this is a little complicated and not for novices).
2) Some of the Java classes and indeed 3rd-party libraries are (surprise) not coded properly. That is, there are methods that take a single string argument as input and return an instance of the target class but it isn't what you think... Consider the Integer class:
static Integer getInteger(String nm)
Determines the integer value of the system property with the specified name.
The above method really has nothing to do with Integers as objects wrapping primitives ints.
Reflection will find this as a possible candidate for creating an Integer from a String incorrectly versus the decode, valueof and constructor Members - which are all suitable for most arbitrary String conversions where you really don't have control over your input data but just want to know if it is possible an Integer.
To remedy the above, looking for methods that throw Exceptions is a good start because invalid input values that create instances of such objects should throw an Exception. Unfortunately, implementations vary as to whether the Exceptions are declared as checked or not. Integer.valueOf(String) throws a checked NumberFormatException for example, but Pattern.compile() exceptions are not found during reflection lookups. Again, not a failing of this dynamic "cross-casting" approach I think so much as a very non-standard implementation for exception declarations in object creation methods.
If anyone would like more details on how the above was implemented, let me know but I think this solution is much more flexible/extensible and with less code without losing the good parts of type-safety. Of course it is always best to "know thy data" but as many of us find, we are sometimes only recipients of unmanaged content and have to do the best we can to use it properly.
Cheers.
So, this is an old post, however I think I can contribute something to it.
You can always do something like this:
package com.dyna.test;
import java.io.File;
import java.lang.reflect.Constructor;
public class DynamicClass{
#SuppressWarnings("unchecked")
public Object castDynamicClass(String className, String value){
Class<?> dynamicClass;
try
{
//We get the actual .class object associated with the specified name
dynamicClass = Class.forName(className);
/* We get the constructor that received only
a String as a parameter, since the value to be used is a String, but we could
easily change this to be "dynamic" as well, getting the Constructor signature from
the same datasource we get the values from */
Constructor<?> cons =
(Constructor<?>) dynamicClass.getConstructor(new Class<?>[]{String.class});
/*We generate our object, without knowing until runtime
what type it will be, and we place it in an Object as
any Java object extends the Object class) */
Object object = (Object) cons.newInstance(new Object[]{value});
return object;
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
public static void main(String[] args)
{
DynamicClass dynaClass = new DynamicClass();
/*
We specify the type of class that should be used to represent
the value "3.0", in this case a Double. Both these parameters
you can get from a file, or a network stream for example. */
System.out.println(dynaClass.castDynamicClass("java.lang.Double", "3.0"));
/*
We specify a different value and type, and it will work as
expected, printing 3.0 in the above case and the test path in the one below, as the Double.toString() and
File.toString() would do. */
System.out.println(dynaClass.castDynamicClass("java.io.File", "C:\\testpath"));
}
Of course, this is not really dynamic casting, as in other languages (Python for example), because java is a statically typed lang. However, this can solve some fringe cases where you actually need to load some data in different ways, depending on some identifier. Also, the part where you get a constructor with a String parameter could be probably made more flexible, by having that parameter passed from the same data source. I.e. from a file, you get the constructor signature you want to use, and the list of values to be used, that way you pair up, say, the first parameter is a String, with the first object, casting it as a String, next object is an Integer, etc, but somehwere along the execution of your program, you get now a File object first, then a Double, etc.
In this way, you can account for those cases, and make a somewhat "dynamic" casting on-the-fly.
Hope this helps anyone as this keeps turning up in Google searches.
Try this for Dynamic Casting. It will work!!!
String something = "1234";
String theType = "java.lang.Integer";
Class<?> theClass = Class.forName(theType);
Constructor<?> cons = theClass.getConstructor(String.class);
Object ob = cons.newInstance(something);
System.out.println(ob.equals(1234));
I recently felt like I had to do this too, but then found another way which possibly makes my code look neater, and uses better OOP.
I have many sibling classes that each implement a certain method doSomething(). In order to access that method, I would have to have an instance of that class first, but I created a superclass for all my sibling classes and now I can access the method from the superclass.
Below I show two ways alternative ways to "dynamic casting".
// Method 1.
mFragment = getFragmentManager().findFragmentByTag(MyHelper.getName(mUnitNum));
switch (mUnitNum) {
case 0:
((MyFragment0) mFragment).sortNames(sortOptionNum);
break;
case 1:
((MyFragment1) mFragment).sortNames(sortOptionNum);
break;
case 2:
((MyFragment2) mFragment).sortNames(sortOptionNum);
break;
}
and my currently used method,
// Method 2.
mSuperFragment = (MySuperFragment) getFragmentManager().findFragmentByTag(MyHelper.getName(mUnitNum));
mSuperFragment.sortNames(sortOptionNum);
Just thought I would post something that I found quite useful and could be possible for someone who experiences similar needs.
The following method was a method I wrote for my JavaFX application to avoid having to cast and also avoid writing if object x instance of object b statements every time the controller was returned.
public <U> Optional<U> getController(Class<U> castKlazz){
try {
return Optional.of(fxmlLoader.<U>getController());
}catch (Exception e){
e.printStackTrace();
}
return Optional.empty();
}
The method declaration for obtaining the controller was
public <T> T getController()
By using type U passed into my method via the class object, it could be forwarded to the method get controller to tell it what type of object to return. An optional object is returned in case the wrong class is supplied and an exception occurs in which case an empty optional will be returned which we can check for.
This is what the final call to the method looked like (if present of the optional object returned takes a Consumer
getController(LoadController.class).ifPresent(controller->controller.onNotifyComplete());

Categories