Reflection in Android is not working - java

I tried using reflection to use a custom List View for an App with target api level 7. The necessary fileds are only available from api level 9 so I attempted to fix that via reflection.
I need to find the protected Method View.overScrollBy( int,int,int,int,int,int,int,int,boolean). When i call
View.getDeclaredMethods()
and iterate over the Method[] array i find it, but when I try
View.class.getDeclaredMethod(String name, Class...< ? > paramTypes)
I get a NoSuchMethodException. I compared the hard coded Method Name and parameterType values with the values extracted from the method (found via iteration) and they are identical...
private boolean initCompatibility()
{
Method[] methods = View.class.getDeclaredMethods();
try {
// The name of the Method i am looking for;
String OVERSCROLL_S = "overScrollBy";
for (Method meth : methods) {
if (meth.getName().equals(OVERSCROLL_S)) {
mListView_overScrollBy = meth;
break;
// method found
}
}
// Params for getDeclaredMethod(…)
String methodName = "overScrollBy";
Class[] methodParams = { Integer.TYPE, Integer.TYPE, Integer.TYPE,
Integer.TYPE, Integer.TYPE, Integer.TYPE, Integer.TYPE,
Integer.TYPE, Boolean.TYPE };
// works
Method test = View.class.getDeclaredMethod(methodName,methodParams);
// fails
View.class.getDeclaredMethod(mListView_overScrollBy.getName(),
mListView_overScrollBy.getParameterTypes());
/*
* I also tried this way around and again the first worked and the second
* failed, so the input arguments are not the problem...
* View.class.getDeclaredMethod( mListView_overScrollBy.getName(),
* mListView_overScrollBy.getParameterTypes() );
* Method test = View.class.getDeclaredMethod(methodName,methodParams);
*/
return true;
} catch (SecurityException e) {
e.printStackTrace();
return false;
} catch (NoSuchMethodException e) {
e.printStackTrace();
return false;
}
}
I do not understand why the call always works the first time and the does not the second time. Interestingly it also fails when i call only once for View.class.getDeclaredMethod(String name, Class...< ? > paramTypes) and it does not make any difference whether i use the hard coded input values or the one extracted from the method I am looking for...
Does anybody know what the problem is? Thanks

This is very interesting, but it is not Android-specific, I think.
I wrote this small test in plain Java:
public class ReflectionTest {
public static void main(String[] args){
Method[] m = ReflectionTest.class.getDeclaredMethods();
for (Method method : m) {
System.out.println(method.getName());
}
try {
Method m1 = ReflectionTest.class.getDeclaredMethod("d0", int.class, boolean.class);
if(m1 != null){
System.out.println("m1 found!");
}
} catch (Exception e) {
e.printStackTrace();
}
try {
Method m2 = ReflectionTest.class.getDeclaredMethod("d0", Integer.TYPE, Boolean.TYPE);
if(m2 != null){
System.out.println("m2 found!");
}
} catch (Exception e) {
e.printStackTrace();
}
try {
Class<?>[] carr = m[1].getParameterTypes();
Method m3 = ReflectionTest.class.getDeclaredMethod("d0", carr);
if(m3 != null){
System.out.println("m3 found!");
}
} catch (Exception e){
e.printStackTrace();
}
}
public void d0(int a, boolean b){
}
}
In eclipse, if I debug it, the three m1,m2 and m3 are printed. However, if I run it, a NoSuchMethodException is thrown when trying to get m3.
UPDATES:
Tested running with jre 7 under linux, and all three m1,m2 and m3 were printed. Perhaps is a problem with jre6? Or is eclipse run configuration?
Changed carr declaration to use method 0 instead of 1: Class<?>[] carr = m[0].getParameterTypes(); as Gray suggested. Now it runs ok but throws exception in debug mode. This means different method order for the returned array m.
Update #2 confirmed, I've included a for loop to print the method names. In run mode the order of the method array is reversed compared to debug mode.

Related

How to call a method from a given string in Java

I am trying to reduce my code from using a bunch of if statements from getting a specified command and calling a method for it.
Instead, I want to try something that would take that command and call a method name with it
Something like this:
"get" + commandString + "Count"()
Instead of:
if (command == "something") {
callSomeMethod();
}
if (command == "somethingelse") {
callSomeOtherMethod();
}
...
Is there a way to call a method from a specified string? Or a better way to approach this problem.
This is the use-case for a switch case statement.
switch(command){
case "command1": command1(); break;
case "command2": command2(); break;
Using a string javascript style is fortunately impossible in Java. The comments links to answers how to use reflection to accomplish something similar. This is rarely a good solution.
we can use
java.lang.reflect.Method
Something like
java.lang.reflect.Method method;
try {
method = obj.getClass().getMethod(methodName, param1.class, param2.class, ..);
} catch (SecurityException e) { ... }
catch (NoSuchMethodException e) { ... }
The parameters identify the very specific method you need (if there are several overloaded available, if the method has no arguments, only give methodName).
And your possible solution can be like -
package com.test.pkg;
public class MethodClass {
public int getFishCount() {
return 5;
}
public int getRiceCount() {
return 100;
}
public int getVegetableCount() {
return 50;
}
}
package com.test.pkg;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) {
MethodClass classObj = new MethodClass();
Method method;
String commandString = "Fish";
try {
String methodName = "get" + commandString + "Count";
method = classObj.getClass().getMethod(methodName);
System.out.println(method.invoke(classObj)); //equivalent to System.out.println(testObj.getFishCount());
} catch (SecurityException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
Ref: How do I invoke a Java method when given the method name as a string?

Java: Use the same code with two different versions of a dependent class

Consider a Java class Foo that uses a library Bar. Foo should be distributed as a binary .class file and use the version of Bar that is already existing on a clients classpath.
There are two different versions of Bar that only differ in its method signatures. Foo should be compatible with both of them.
Example code:
public class Foo {
public static void main(String[] args){
Bar.librarycall("hello from foo");
//or
Bar.librarycall("hello from foo",1);
}
}
//v1
public class Bar {
public static void librarycall(String argument){
System.out.println("Bar1: " + argument);
}
}
//v2
public class Bar {
public static void librarycall(String argument,int i){
for(int j = 0; j < i; j++)
System.out.println("Bar2: " + argument);
}
}
I want to avoid reflection if possible. How would you propose to create a class Foo that is compatible with both versions of Bar?
[Edit]
This problem originates in a project I am working on. Bar corresponds to an external library I am using but cannot be modified for the code to work (I don't have the source code and the license doesn't allow modifications).
A refelective solution.
Class<?> c;
try {
c = Class.forName("Bar");
Method meths[] = c.getMethods();
Method v1method = null;
Method v2method = null;
for(Method m:meths) {
if(!m.getName().equals("librarycall")) continue;
if(!Modifier.isStatic(m.getModifiers())) {
System.out.println("Should be static");
continue;
}
Class<?> params[] = m.getParameterTypes();
if(params.length == 1 && params[0].equals(String.class) )
v1method = m;
if(params.length == 2 && params[0].equals(String.class) && params[1].equals(Integer.TYPE) )
v2method = m;
}
if(v2method!=null) {
v2method.invoke(null,"V2",5);
}
else if(v1method!=null) {
v1method.invoke(null,"V1");
}
else
System.out.println("No method found");
} catch (ClassNotFoundException e) {
System.out.println(e);
} catch (IllegalArgumentException e) {
System.out.println(e);
} catch (IllegalAccessException e) {
System.out.println(e);
} catch (InvocationTargetException e) {
System.out.println(e);
}
You could use c = Bar.class; or if you already have an instance bar of Bar c = bar.getClass(). The invoke syntax is for static methods if its non static you need v1method.invoke(bar,"V1");.
Reflection does seem like the simplest way. The alternative would be to try calling the second version and catch a NoSuchMethodException.
public class Foo {
public static void main(String[] args){
try {
Bar.librarycall("hello from foo",1);
catch(NoSuchMethodException e) {
Bar.librarycall("hello from foo");
}
}
This is ugly, and slower, use Reflection its what its there for.
It sounds like this one task that is handled by the strategy pattern.
I'm assuming that:
You cannot change any of the versions of the Bar class files
You have the ability to write new Foo files
For some reason, you really want to avoid using Reflection
The two Bar files have the same package name
You may need to distribute two versions of the Foo class, as mentioned by JB Nizet in the comment to your question.

How to check if class has variable and declare it in other class

I am trying to check if another class has a member variable called "list" in it, and I want a boolean to tell me if that class has it or not.
If the class has "list", the boolean returns true and everything is good. But if the class DOESN'T have "list" in it, it doesn't return false but it causes an error:
public static void main(String[]args) throws NoSuchFieldException, SecurityException{
boolean has = Person.class.getDeclaredField("list")!=null;
System.out.println(has);
}
The error:
Exception in thread "main" java.lang.NoSuchFieldException: list
at java.lang.Class.getDeclaredField(Unknown Source)
at test.main(test.java:21)
Line 21 is where I declared the boolean has.
So I have 2 questions:
How do I return false if there ISNT "list" in class Person?
If the varible exists, how can I make it into an object?
As an answer to the first question, if there isn't such a list, the NoSuchFieldException is thrown, so catch that exception then and return or set a boolean to false in that case.
How do I return false if there ISNT "list" in class Person?
Class.getDeclaredFields() throws a NoSuchFieldExeption if the field does not exist, so you need to catch the NoSuchFieldException:
public static void main(String[]args) {
boolean has = false;
try {
Person.class.getDeclaredField("list");
has = true;
} catch (NoSuchFieldException nsfe) {
// intentionally ignored
}
System.out.println(has);
}
It is usually a bad idea to simply ignore a thrown exception (the catch block should at least contain something like nsfe.printStackTrace()), but in this case it should be fine.
If the varible exists, how can I make it into an object?
I am not 100% sure what you mean by this, but you can get a reference to the desired attribute through the return value of getDeclaredField(), which is a java.lang.reflect.Field - in that case, I would avoid the boolean and restructure the code slightly, e.g.:
// #param Person object which has a "list" member
public void printListField(Object p) throws IllegalArgumentException, IllegalAccessException {
Field listField = null;
try {
listField = Person.class.getDeclaredField("list");
} catch (NoSuchFieldException nsfe) {
// intentionally ignored
}
if (listField != null) {
Object l = listField.get(p);
System.out.println("list is " + l);
} else {
System.out.println("No list member available!");
}
}
Note that you need a reference to an actual object of class Person in order to retrieve a reference to an instance variable.
public static void main(String[]args) throws NoSuchFieldException, SecurityException{
try {
boolean has = Person.class.getDeclaredField("list")!=null;
} catch(NoSuchFieldException e) {
has=false;
}
System.out.println(has);
}
So why not the below ?
try {
has = Person.class.getDeclaredField("list")!=null;
}
catch (NoSuchFieldException e) {
has = false;
}
Although I can't help thinking your design is flawed such that you have to perform this check (if you're inheriting legacy code you may have little choice, perhaps)
According to java-doc:
* #exception NoSuchFieldException if a field with the specified name is
* not found.
So if you want to check that field exists you should intercept exception:
boolean has;
try {
Person.class.getDeclaredField("list");
has = true;
} catch (NoSuchFieldException e) {
has = false;
}
You can get all fields by reflection,then check each field from the field array.
The method getDeclaredField will throw an exception(NoSuchFieldException) if the field does not exist. So you have to put a try/catch block around this method. And if you catch a NoSuchFieldException, then set has to false.
public static void main (String [] args) {
boolean has = false;
try {
Field f = Person.class.getDeclaredField("list");
has = true;
} catch (NoSuchFieldException e) {
has = false;
}
System.out.println(has);
}
See the java documentation at the following link:
http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getDeclaredField(java.lang.String)

can i store function names in final hashmap for execution?

I'm building an admin controller that work like a terminal emulator in Flex 4.5.
The server side is Red5 on a tomcat server using Java programming language.
When a user enter a command in his textinput, the command is sent to the red5, in red5 I check if the command exists and return a proper output or an error if the command or parameters don't match.
so for now i use if (command.equals("..") {} else if (command.equals(...
Is there a way to store the function name or a reference to the function that should be executed in each command and to execute it?
example:
// creating the hasmap
HashMap<String,Object> myfunc = new HashMap<String,Object>();
// adding function reference
myfunc.put("help",executeHelp);
or....
myfunc.put("help", "executeHelp"); // writing the name of the function
and then
void receiveCommand(String command, Object params[]( {
myfunc.get(command).<somehow execute the referrened function or string name ? >
}
any ideas?
thank you!
You could use reflection, but I suggest a easier way.
You can create an abstract class or interface with an abstract method execute. Example:
interface Command {
void execute(Object params[]);
}
class Help implements Command {
void execute(Object params[]) {
// do the stuff
}
}
Now your hashmap can be:
// creating the hasmap
HashMap<String,Command> myfunc = new HashMap<String,Command>();
// adding function reference
myfunc.put("help", new Help());
And then:
void receiveCommand(String command, Object params[]) {
myfunc.get(command).execute(params);
}
You can execute a function by name as follows:
java.lang.reflect.Method method;
try {
method = obj.getClass().getMethod(methodName, param1.class, param2.class, ..);
} catch (SecurityException e) {
// ...
} catch (NoSuchMethodException e) {
// ...
}
In the above snippet, param1.class, param2.class are the class types of the arguments of the method to execute.
Then:
try {
method.invoke(obj, arg1, arg2,...);
}
catch (IllegalArgumentException e) { }
catch (IllegalAccessException e) { }
catch (InvocationTargetException e) { }
There is lots more information about this here: http://java.sun.com/docs/books/tutorial/reflect/index.html
You can define an interface for your functions
interface Function {
public Object invoke(Object[] arguments);
}
and then public your code via this interface
public class Function1 implements Function {
public Object invoke(Object[] arguments) {
...
}
}
and store in the map
map.put("helpCommand", new Function1());
or store a reference using an anonymous class
Function theFunction = new Function() {
public Object invoke(Object[] arguments) {
return theRealMethod(arguments[0], String.valueOf(arguments[1]));
}
}
In the second example I showed how to use the anonymous class as an adaptor if the method you want to call has a different signature than your interface.

Better way to write this Java code? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
public void handleParsedCommand(String[] commandArr) {
if(commandArr[0].equalsIgnoreCase("message")) {
int target = Integer.parseInt(commandArr[1]);
String message = commandArr[2];
MachatServer.sendMessage(target, this.conId, message);
} else if(commandArr[0].equalsIgnoreCase("quit")) {
// Tell the server to disconnect us.
MachatServer.disconnect(conId);
} else if(commandArr[0].equalsIgnoreCase("confirmconnect")) {
// Blah blah and so on for another 10 types of command
} else {
try {
out.write("Unknown: " + commandArr[0] + "\n");
} catch (IOException e) {
System.out.println("Failed output warning of unknown command.");
}
}
}
I have this part of my server code for handling the types of messages. Each message contains the type in commandArr[0] and the parameters in the rest of commandArr[]. However, this current code, while working seems very unelegant. Is there a better way to handle it? (To the best of my knowledge, String values can't be used in switch statements, and even then, a switch statement would only be a small improvement.
I'd refactor this using the Command Design Pattern.
Basically each of your commands, message, quit, confirmconnect and a default will have a class implementation and will implement the Command Interface.
/*the Command interface*/
public interface ICommand {
void execute(String[] commandArr);
}
public class Message implements ICommand {
void execute(String[] commandArr) {
int target = Integer.parseInt(commandArr[1]);
String message = commandArr[2];
MachatServer.sendMessage(target, this.conId, message);
}
}
//same type of class for other commands
public class CommandManager {
public ICommand getCommand(String commandName) {
//store all the commands in a hashtable.
//Pull them out by name as requested.
}
//Esko's suggestion from comments
public static void executeImmediately(String[] commandArr) {
getCommand(commandArr[0]).execute(commandArr);
}
}
public void handleParsedCommand(String[] commandArr) {
ICommand command = CommandManager.getCommand(commandArr[0]);
command.execute(commandArr);
//or Esko
CommandManager.executeImmediately(commandArr);
}
Here are two variants using enums that (nearly) provide the same behavior in a much more readable way:
1) Enums for a type-safe switch:
enum CommandType {
MESSAGE,
QUIT,
CONFIRMCONNECT
}
public void handleParsedCommand(String[] commandArr) {
CommandType cmd = null;
try {
cmd = CommandType.valueOf(commandArr[0].toUpperCase());
} catch (IllegalArgumentException e) {
// this kind of error handling, seems a bit strange, by the way.
try {
out.write("Unknown: " + commandArr[0] + "\n");
} catch (IOException e) {
System.out.println("Failed output warning of unknown command.");
}
return;
}
switch(cmd) {
case MESSAGE:
int target = Integer.parseInt(commandArr[1]);
String message = commandArr[2];
MachatServer.sendMessage(target, this.conId, message);
case QUIT:
// Tell the server to disconnect us.
MachatServer.disconnect(conId);
case CONFIRMCONNECT:
// Blah blah and so on for another 10 types of command
}
}
}
The main benefits are that the code is more readable, but you avoid creating new methods or classes for each of the cases, which is not allows what you want if the handling code has only one or two lines.
2) Another enum-based variant, that is in fact a Command pattern, but which out much bloat code:
enum CommandType {
MESSAGE {
void execute(CommandProcessor cp, String[] params) {
int target = Integer.parseInt(params[1]);
String message = params[2];
MachatServer.sendMessage(target, cp.conId, message);
}
},
QUIT {
void execute(CommandProcessor cp, params param) {
MachatServer.disconnect(cp.conId);
}
},
CONFIRMCONNECT {
void execute(CommandProcessor cp, params param) {
// Blah blah and so on for another 10 types of command
}
};
abstract void execute(CommandProcessor cp, String[] param);
}
public void handleParsedCommand(String[] commandArr) {
CommandType cmd = null;
try {
cmd = CommandType.valueOf(commandArr[0].toUpperCase());
} catch (IllegalArgumentException e) {
try {
out.write("Unknown: " + commandArr[0] + "\n");
} catch (IOException e) {
System.out.println("Failed output warning of unknown command.");
}
return;
}
cmd.execute(this, commandArr);
}
Yeap, looks like a Command + Prototype pattern to me.
In the command you define what is going to be done, and the prototype is to place an instance of each command in a lookup table and "clone" them to be executed each time.
The refactoring would be like:
Before:
public void handleParsedCommand(String[] commandArr) {
if(commandArr[0].equalsIgnoreCase("message")) {
int target = Integer.parseInt(commandArr[1]);
String message = commandArr[2];
MachatServer.sendMessage(target, this.conId, message);
} else if(commandArr[0].equalsIgnoreCase("quit")) {
// Tell the server to disconnect us.
MachatServer.disconnect(conId);
} else if(commandArr[0].equalsIgnoreCase("confirmconnect")) {
// Blah blah and so on for another 10 types of command
} else {
try {
out.write("Unknown: " + commandArr[0] + "\n");
} catch (IOException e) {
System.out.println("Failed output warning of unknown command.");
}
}
}
After:
public void handleParsedCommand(String[] commandArr) {
Command.getCommand( commandArr ).execute();
}
// Define the command and a lookup table
abstract class Command {
// Factory using prototype
public static Command getCommand( String [] commandArr ) {
// find the handling command
Command commandPrototype = commandMap.get( commandArr[0] );
// if none was found, then use "uknown"
if ( commandPrototype == null ) {
commandPrototype = commandMap.get("unknown");
}
// Create an instance using clone
Command instance = commandPrototype.clone();
instance.args = commanrArr;
return instance;
}
// lookup table ( switch substitute )
private static Map<String,Command> commandsMap = new HashMap()<String,Command>(){{
put("message" , new MessagCommand());
put("quit" , new QuitCommand());
put("confirmconnect", new ConfirmConnectCommand());
...
put("unknow" , new UnknownCommand());
}};
// args of the command
private String [] args;
public void execute();
String [] getArgs(){
return this.args;
}
}
And the provide the specific implementations
class MessageCommand extends Command {
public void execute(){
int target = Integer.parseInt(commandArr[1]);
String message = commandArr[2];
MachatServer.sendMessage(target, this.conId, message);
}
}
class MessageCommand extends Command {
public void execute(){
int target = Integer.parseInt(getArgs()[1]);
String message = getArgs()[2];
MachatServer.sendMessage(target, this.conId, message);
}
}
class QuitCommand extends Command {
public void execute() {
MachatServer.disconnect(conId);
}
}
class ConfirmConnectCommand extends Command {
public void execute() {
/// blah blah blah
}
}
class UnknowCommand extends Command {
public void execute() {
try {
out.write("Unknown: " + commandArr[0] + "\n");
} catch (IOException e) {
System.out.println("Failed output warning of unknown command.");
}
}
}
// ... other 10 implementations here...
Take a look at Commons CLI which is a command-line argument parser.
Here are some examples of its usage.
You can use enums
For starters, I would make a map between the commands and a class which executes each type of command (say an anonymous class that implements a known interface) and then retrieve the right class from the map, and then passes it the rest of the parameters.
If it made sense, you could use an enum here with a static method to retrieve the right one, that way you could switch if and when you needed to (say you had to do the same thing on 5 of the 10 commands).
First of all you are reading the same element of the array every time. This should be the first thing to factor out. equalsIgnoreCase is a bit long, so normalise the case first (don't pick up the default locale!).
It is possible to use enums to hack a switch of Swtings. JDK7 may include a switch on String, IIRC.
I like Bob's answer. Another method would be to use the Spring framework and the IoC functionality. Basically, I've done this before to use Spring (inflates from xml) to create a Map where you have each command object stored with a key. The key would be the same as the text in commandArr[0].
So your xml looks something like
<property name="commands">
<map>
<entry>
<key>
<value>message</value>
</key>
<ref bean="messageCommand" />
</entry>
</map>
</property>
<bean id="messageCommand" ref="org.yourorg.yourproject.MessageCommand" />
And then in your code...
commands.get(commandArr[0]).execute() //or whatever
This allows you to not run any sort of initialization code. All you have to do is inflate the xml. Spring handles populating the map for you. Also, you can define any necessary data members in the classes using a similar syntax. Also, if you need to add functionality, all you have to do is change the xml rather than mucking with and recompiling code. I'm personally a huuuuge fan :)
For more info, check out this article for a brief overview of IoC and then check out this article for the documentation

Categories