Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic Return Type in Java method

Tags:

I've seen a question similar to this multiple times here, but there is one big difference.

In the other questions, the return type is to be determined by the parameter. What I want/need to do is determine the return type by the parsed value of a byte[]. From what I've gathered, the following could work:

public Comparable getParam(String param, byte[] data) {
    if(param.equals("some boolean variable")
        return data[0] != 0;
    else(param.equals("some float variable") {
        //create a new float, f, from some 4 bytes in data
        return f;
    }
    return null;
}

I just want to make sure that this has a chance of working before I screw anything up. Thanks in advance.

like image 385
Jon Egeland Avatar asked Nov 19 '11 02:11

Jon Egeland


2 Answers

I don't know what these people are talking about. You lose type safety, which is a concern, but you could easily accomplish this with generics...something like:

public <T> T getSomething(...) { }

or

interface Wrapper<T> { T getObject(); }

public <T> Wrapper<T> getSomething(...) { }

The latter promotes the possibility of a strategy pattern. Pass the bytes to the strategy, let it execute and retrieve the output. You would have a Byte strategy, Boolean strategy, etc.

abstract class Strategy<T> {
    final byte[] bytes;

    Strategy(byte[] bytes) { this.bytes = bytes; }

    protected abstract T execute();
}

then

class BooleanStrategy extends Strategy<Boolean> {
    public BooleanStrategy(byte[] bytes) { super(bytes); }

    @Override
    public Boolean execute() {
        return bytes[0] != 0;
    }

}

Your example code is a bad use case though and I wouldn't recommend it. Your method doesn't make much sense.

like image 112
hisdrewness Avatar answered Sep 18 '22 11:09

hisdrewness


This CAN be done. The following code will work:

public byte BOOLEAN = 1;
public byte FLOAT = 2;
public static <Any> Any getParam(byte[] data) {
    if (data[0] == BOOLEAN) {
        return (Any)((Boolean)(boolean)(data[1] != 0));
    } else if (data[0] == FLOAT) {
        return (Any)((Float)(float)data[1]);
    } else {
        return null;
    }
}

By using a generic for the return type any Java method can dynamically return any object or primitive types. You can name the generic whatever you want, and in this case I called it 'Any'. Using this code you avoid casting the return type when the method is called. You would use the method like so:

byte[] data = new byte[] { 1, 5 };
boolean b = getParam(data);
data = new byte[] { 2, 5 };
float f = getParam(data);

The best you can do without this trick is manually casting an Object:

float f = (float)getParam(data);

Java dynamic return types can reduce boilerplate code.

like image 45
Danieth Avatar answered Sep 16 '22 11:09

Danieth