I want to write a client server app which communicates via rpc. The code works quite well with functions with no parameters. However, when I try to call a function with a single parameter (more are not supported), it gives me an "NoSuchMethodException".
Here are the important parts:
The Function I want to call:
(rpcserver.CarPark.in)
public boolean in(int num) {
if(!closed) {
if (num <= (maxLots - curLots)) {
curLots += num;
return true;
}
}
return false;
}
public boolean in() {
if(!closed) {
if (curLots < maxLots) {
curLots += 1;
return true;
}
}
return false;
}
Here is the code that calls the functions:
(I use procedure[0] for the function name and [1] for the parameter.
if(procedure.length == 1) {
try {
Method method = CarPark.class.getDeclaredMethod((String)procedure[0]);
return method.invoke(park);
} catch (Exception e) {
throw new Exception("Server couldn't find a fitting procedure.");
}
} else {
// length of 2, more isn't possible
try {
System.out.println((String)procedure[0] + ", " + procedure[1].getClass());
Method method = CarPark.class.getDeclaredMethod((String)procedure[0], procedure[1].getClass());
return method.invoke(park,procedure[1]);
} catch (Exception e) {
throw new Exception("Server couldn't find a fitting procedure." + e);
}
}
Strangely, the function returnes this: java.lang.NoSuchMethodException: rpcserver.CarPark.in(java.lang.Integer)
However, the println command gives me this: in, class java.lang.Integer
So why can I call procedures with no parameters but have problems with parameters?
Thanks
The problem is that the version of CarPark.in you're trying to get takes a primitive integer, and getDeclaredMethod is looking for one that takes a java.lang.Integer, which is not the same thing. If you pass int.class or Integer.TYPE to getDeclaredMethod, you'll see that it'll be able to find the method correctly.
Without seeing your full code isn't a bit hard to suggest a solution that works for you, but just keep in mind the distinction between primitives types and their boxed equivalents, and be wary of autoboxing.
Related
This question already has answers here:
Java Compiler Error: Missing Return Statement
(2 answers)
Closed 4 years ago.
I'm using the code below in a Triangle class to allow the user to set the first, second, or third point of a declared Triangle.
public Point get(String p) throws IllegalArgumentException {
IllegalArgumentException e = new IllegalArgumentException();
try {
if (p == "first") { return first; }
else if (p == "second") { return second; }
else if (p == "third") { return third; }
else { throw e; }
}
catch (e) {
System.out.println("Error: " + e);
}
}
The compiler is telling me:
Triangle.java:41: error: missing return statement
}
^
But I thought the point of the catch statement was to be able to catch an error and return a string describing the error, without having to worry about matching the function's return type.
Because you're missing a return statement.
The method declares that it returns something, so it must return something (or throw an exception). The compiler can't guarantee that any of the return statements in the try block will be reached if an exception is thrown before any of them execute. So the catch block also needs to return something (or throw an exception, or return something after the try/catch construct entirely).
Edit: Looking again, you're also potentially missing a return in the try block. (If you don't have one after the entire try/catch structure.) What if none of the conditions in the if/else structure are satisfied? Nothing is returned. Which is invalid.
Basically, all logical paths must result in a valid exit of the method. You've missed two such paths.
You're not returning anything in your function on several paths.
But I thought the point of the catch statement was to be able to catch an error and return a string describing the error, without having to worry about matching the function's return type.
That's not at all what a try-catch does, and moreover your function is declared to return a Point not a String.
try-catch simply "catches" a Throwable (Error or Exception) and allows you to run some code when it is thrown instead of simply terminating the application with an Uncaught Exception/Error.
You need to return some value from your function after the try-catch there is no way to return a string, nor is there a language construct in place that behaves like you've explained your understanding of try-catch.
Also your code cna't actually throw an IllegalArgumentException so your catch block will never get called. In this case, it sounds like what you want is instead something like this
public Point get(String p) throws IllegalArgumentException {
if (p == null) { throw new IllegalArgumentException(); }
if (p.equals("first")) { return first; }
else if (p.equals("second")) { return second; }
else if (p.equals("third")) { return third; }
else { throw new IllegalArgumentException(); }
}
The code could then be called like so
Point p;
try {
p = get("notFirst");
} catch (IllegalArgumentException ex) {
//oh no, we gave a bad argument, and the method told us nicely.
}
You are missing two parts:
1. A return statement in try block for else condition
2. Catch block doesn't lead to a return statement or a throw statement
I don't know if type of first, second, third variables are string or Point, but you should return with Point, because your function is :
public Point get(String p) {
...
}
You have three if statements. What happens when the input doesn't satisfy any of those? Your method doesn't have a return statement for that case.
I am using Method.Invoke in java to dynamically call methods in another class. The only issue is that if the methods have paramaters i need to start that in the class.getDeclaredMethod("method", something.class) or else it wont see those methods. The issue with this that i don't know when calling the methods what the parameters will be. How do I get around this?
Also I have done this in C# and its easy and does not require me to state the parameters but this is in Java.
Here is the code that does the Invoke:
public void DoCommand(String msg){
System.out.println(msg);
String[] temp = msg.split(" ");
String command = temp[0];
Class c = commander.getClass();
try {
Object obj = c.newInstance();
try {
System.out.println("'" + command + "'");
Method method = c.getDeclaredMethod(command);
Object[] pars = new Object[temp.length];
for(int i = 0; i < pars.length; i++){
pars[i] = temp[i + 1];
}
if((String)pars[pars.length - 1] == null){
pars[pars.length - 1] = socket;
}
Parameter[] paramaters = method.getParameters();
Object[] endParameters = AltimitConverter.ConvertParameters(pars, paramaters);
try {
method.invoke(obj, endParameters);
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {}
}catch (NoSuchMethodException e){
System.out.println(e.toString());
}
}catch (Exception e){
System.out.println(e.toString());
}
}
So how do I call different methods with different parameters without stating the parameters when getting the method.
This is the C# version that does work:
private static void DoCommand(string msg, Socket soc){
string[] temp = msg.Split (' ');
string command = temp [0];
Type type = commandObject.GetType ();
MethodBase commandFunction = type.GetMethod (command);
if (commandFunction != null) {
object[] pars = new object[temp.Length - 1];
for (int i = 0; i < pars.Length; i++) {
pars [i] = temp [i + 1];
}
if ((string)pars [pars.Length - 1] == "") {
pars [pars.Length - 1] = soc;
}
ParameterInfo[] paramaters = commandFunction.GetParameters ();
object[] endParamaters = AltimitConverter.ConvertParams (pars, paramaters);
if (commandFunction != null) {
try {
commandFunction.Invoke (commandObject, endParamaters);
} catch (Exception e) {
Debug.Log (e);
}
} else {
Debug.Log ("commandFunction is null");
}
}
}
Instances of java.lang.reflect.Method reflect specific methods. Each one is associated with a specific class, has a specific parameter list, and has a specific return type. When method overloading is in play, each of the overloaded methods will be reflected by a distinct Method object; these are not interchangeable.
If you need to account for selecting among overloaded methods, then you can do so only with reference to the number and types of the intended arguments. If you have to rely on the arguments themselves to determine matching parameter types, then you're looking at duplicating Java's method-resolution logic, which is complex.
In the event that you need only worry about looking up a non-overloaded method declared by the subject class itself (i.e. not inherited) then you can invoke getDeclaredMethods() on the Class object and scan the resulting array of Method objects for one with the correct name.
You can go a little way into overloaded methods while preserving your sanity if different overloads are distinguished by different numbers of parameters, or maybe if there are specific limits on the parameter type patterns you need to account for, but at that point you really should be asking yourself whether there's a better way. This kind of design absolutely begs for trouble.
I figured out a solution. I created a function to take the intended parameters which are strings and convert them to a data type depending on if it looks like a float, Integer, or string. then i send that into another method that gets all methods in a class and get the ones with the method name i am trying to call and then gets the one with the data types i had in the object[] returned from the first method. and then i use the method i got and the converted data types to call the method.
I can't seem to find anything on google for this and I'm not sure it's possible. What I want to do, is pass a line of Java code as an argument to a method. Google only turns up results for passing cmd line arguments to methods, but I want to pass an actual line of code.
Basically I want to pass methodA to methodB except methodA isn't a method, but a line of code. Below is a full example of passing a method to a method using reflection.
public class Relation<T> {
protected Set<Pair<T,T>> pairs = null;
public Relation() {
this.pairs = new LinkedHashSet<Pair<T,T>>();
}
/* Next 2 methods are methods for sending methods to methods useing java.lang.reflect.Method */
public Method getMethod(String name) {
try { return Relation.class.getDeclaredMethod(name);
} catch (Exception e) {}
return null;
}
public boolean execute(Method method, Object... params) {
try { return (Boolean) method.invoke(this, params);
} catch (Exception e) {}
return false;
}
/* The method I reuse several times so I just put methods inside of it */
public boolean pairsTFIterator(Method method) {
for(Pair<T,T> x : pairs) {
boolean bool = false;
for(Pair<T,T> y : pairs) {
if(execute(method, x,y))
bool = true; break;
}
if(!bool) return false;
}
return true;
}
/* To be replaced by the line of code*/
public static <T> boolean isSymmetricPairs(Pair<T,T> a, Pair<T,T> b) {
return a.getFirst().equals(b.getSecond()) && a.getSecond().equals(b.getFirst()) ? true :false;
}
/* Method that calls others */
public boolean isSymmetric() {
return pairsTFIterator(getMethod("isSymmetricPairs"));
}
}
The above works fine and all, but I want to take it a step further and just forego methods like the "isSymmetricPairs" method by just putting that methods logic line directly in the "pairsTFIterator", like so:
public boolean isReflexive() {
return baseSetTFIterator(
a.getFirst().equals(b.getSecond()) && a.getSecond().equals(b.getFirst()) ? true :false
);
}
I'm pretty sure this is impossible, but if there is someway to do it, that would be great.
It sounds like what you are looking for are "first-class functions". Some languages treat functions just like a variable, in the sense that you can assign them to variables and pass them as arguments to other functions. Java 8 will be introducing the concept of lambda expressions which will support this type of functionality.
Also there are other JVM languages that provide this already, including Scala and Groovy to name two of the more popular ones.
Just to give you a flavor of what it looks like, in Groovy you can execute arbitrary functions on each element of a collection by calling the each() method and passing it a closure (a function essentially).
def list = [1, 2, 3, 4]
def printer = { x -> println x } // defines a closure that takes one arg and prints it
list.each(printer) // prints out the elements
def sum = 0
def summer = { x -> sum += x } // defines a closure that takes one arg and adds it to the sum variable
list.each(summer)
println sum // should be 1 + 2 + 3 + 4
Put you code in an anonymos inner class may satisfy your requirement:
interface PairFilter<T>{
boolean filter(Pair<T, T> a, Pair<T,T> b);
}
And in you iterator method:
public boolean pairsTFIterator(PairFilter filter) {
for(Pair<T,T> x : pairs) {
boolean bool = false;
for(Pair<T,T> y : pairs) {
if(filter.filter(x,y))
bool = true; break;
}
if(!bool) return false;
}
return true;
}
then call it:
pairsTFIterator(new PairFilter<T>(){
public boolean filter(Pair<T, T> a, Pair<T,T> b){
return a.getFirst().equals(b.getSecond()) && a.getSecond().equals(b.getFirst()) ? true :false;
}
});
My problem is, that I want to return an Object from the ArrayList "blocks".
My code doesn't work - error says This method must return a result of type block
public block getBlockUnderneath (int x, int y){
for(int i = 0; i<blocks.size(); i++){
if (blocks.get(i).x == x) {
return blocks.get(i);
}
}
}
You have two issues:
If blocks.size()==0 your method returns nothing
If none of the blocks in blocks have block.x==x your method returns nothing.
In Java a method must return a value of it is declared to do so.
The easiest solution to your issue is to return null at the end of the method:
public block getBlockUnderneath (int x, int y){
for(final block b : blocks){
if (b.x == x) {
return b;
}
}
return null;
}
Notice this uses an enhanced-for-loop, this is the recommended way to loop over Collections (or anything that implements Iterable<T>) in Java.
A better approach might be to throw an exception if no item is found:
public block getBlockUnderneath (int x, int y){
for(final block b : blocks){
if (b.x == x) {
return b;
}
}
throw new NoSuchElementException();
}
In either case you would need to handle the corner case in code that calls this method.
P.S. please stick to Java naming conventions. Classes should be in PascalCase - so you block class should be called Block.
Just for fun, in Java 8:
public block getBlockUnderneath(int x, int y) {
return blocks.stream().filter((b) -> b.x == x).findFirst().get();
}
The problem with your method is that there exists a scenario in which the return block is not executed. In that case, when a method is not declared to be void, you must declare the exit point for it.
You can exit using return or throw an exception. The choice depends on what your program should do if the requested value could not be found.
public block getBlockUnderneath (int x, int y){
for(int i = 0; i<blocks.size(); i++){
if (blocks.get(i).x == x) {
return blocks.get(i);
}
}
return null; //or throw NoSuchElementException or IllegalStateException
}
What's more you can improve you code by using a for-each loop. This solution may give you better performance and also code security as it uses an iterator rather than accessing item by index which is not necessarily efficient.
In this case you access the same item twice.
if (blocks.get(i).x == x) {
return blocks.get(i);
}
Full example
public Block findBlock(int x} { //The class name is Block
for(Block block : blocks) {
if(block.x == x {
return block;
}
}
return null;
}
Be also aware of that returning null may cause problems and thus is considered bad practice. You can avoid null, thanks to checked exceptions, default values or using Null object
There is a native implementation of this common coding pattern in Java 8. Using the Optional<T> class from the Guava library can solve this problem for versions of Java < 8.
public Optional<Block> findBlock(int x} { //The class name is Block
for(Block block : blocks) {
if(block.x == x {
return Optional.of(block);
}
}
return Optional.empty();
}
Usage
public void someActionWithBlocK() {
Optional<Block> block = findBlock(5);
if(block.isPresent()) {
//some action with block
}
}
You could never loop.
If you have a return statement inside of a loop, then the compiler doesn't take the bonafide guarantee that the loop will execute and that you will return. To get around that, you must also return after your loop.
Or, better yet, have one variable to return, like such:
block ret = null;
for(block b : blocks) {
if(b.x == x) { // I'm going to go over this in a mo
ret = b;
break;
}
}
return ret;
I am parsing XML files and I have several methods similar to:
public static Integer getInteger(Object integer) {
if (integer == null) {
return 0;
}
try {
return Integer.parseInt(integer.toString(), 10);
} catch (Exception ex) {
return 0;
}
}
So basically, you pass an object in with the assumption of converting it to an Integer (I also have versions for Float, etc).
This seems to work well but being a Java newbie, I was wondering how you would improve it. I am especially interesting in the boxing/unboxing aspect (at least, from a C# developer's perspective).
Thanks
EDIT
Sorry, I wasn't clear to what goes into the method. Yes, it's for an XML file now so it's always a string. But the string could be empty or maybe even null. I guess I wanted to always return a 0 if there was an error of any kind.
You shouldn't generally catch Exception. Catching NumberFormatException would be more appropriate here.
Any reason for converting to Integer instead of int? Why not let the caller perform the boxing conversion if they need it?
You don't say whether integer is an instance of Integer or not. If it is you can just cast it:
Integer i = (Integer) integer;
having checked for null and instanceof first.
If it is not an instance of Integer then what you're doing seems reasonable, although you only need to catch a NumberFormatException.
You should use instanceof operator, then make safe casting (so if Object integer is instanceof Integer, cast it).
Then you don't have to catch Exception (which in this case is unchecked NumberFormatException)
public static Integer getInteger(Object integer) {
if (integer == null) {
return 0;
}
if (integer instanceof Integer) {
return (Integer)integer;
}
return 0;
}
EDIT
If data is coming from XML, then it will of course never be Integer :) Then parsing from String is required still, so see other answers.
As Jon hinted, returning int (the primitive data type) instead of Integer (the wrapper class) would probably be better (assuming you never want to return null).
Also, adding this code could be a shortcut, when the input is often an Integer object or other Number subclass (I'm calling the input input because it's too confusing otherwise):
if (input instanceof Number) {
return ((Number) integer).intValue();
}
Returning Integer makes sense if you want to signal, that a value is empty. You're testing that already but you shouldn't return 0, unless you have a very clear and somewhat special requirement to do so. No value is not equal to 0.
Also, you can add more special cases besides null, like check for empty string:
public static Integer getInteger(Object integer) {
if (integer == null) {
return 0;
}
try {
String s = integer.toString();
if (s.isEmpty())
return 0;
return Integer.parseInt(s, 10);
} catch (Exception ex) {
return 0;
}
}
On the other side, you can cut all special cases, and go with only:
public static Integer getInteger(Object integer) {
try {
return Integer.parseInt(integer.toString(), 10);
} catch (Exception ex) {
return 0;
}
}
In the end, performance gains (or losses) depends on what portion of your input data is null, empty, unparsable integers, or "normal" integer strings.