Java 方法中的动态返回类型

问题描述 投票:0回答:7

我在这里多次看到类似的问题,但有一个很大的区别。

其他问题中,返回类型由参数决定。我想要/需要做的是通过

byte[]
的解析值确定返回类型。根据我收集的信息,以下方法可能有效:

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;
}

我只是想在搞砸任何事情之前确保这有机会发挥作用。预先感谢。

java dynamic return-type
7个回答
31
投票

我不知道这些人在说什么。你会失去类型安全性,这是一个问题,但你可以使用泛型轻松实现这一点......类似:

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

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

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

后者促进了战略模式的可能性。将字节传递给策略,让它执行并检索输出。你会有字节策略、布尔策略等。

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

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

    protected abstract T execute();
}

然后

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

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

}

您的示例代码是一个糟糕的用例,我不会推荐它。你的方法没有多大意义。


28
投票

可以完成。以下代码将起作用:

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;
    }
}

通过使用泛型作为返回类型,任何 Java 方法都可以动态返回任何对象或原始类型。您可以将泛型命名为任何您想要的名称,在本例中我将其称为“任何”。使用此代码可以避免在调用方法时强制转换返回类型。你可以使用这样的方法:

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

如果没有这个技巧,你能做的最好的事情就是手动转换一个对象:

float f = (float)getParam(data);

Java 动态返回类型可以减少样板代码。


16
投票

你做不到。 Java 返回类型必须是固定的基本类型 或对象类。我很确定你能做的最好的事情就是返回一个包装类型 它具有获取各种可能类型的值的方法,以及一个内部枚举 这表明哪一个是有效的。

--- 编辑 --- 经过 Danieth 的修正!

public <Any> Any getParam(boolean b){
return((Any)((Boolean)(!b)));
}
public <Any> Any getParam(float a) {
 return((Any)((Float)(a+1)));
}
public <Any> Any getParam(Object b) {
 return((Any)b);
}
public void test(){
  boolean foo = getParam(true);
  float bar = getParam(1.0f);
  float mumble = getParam(this); // will get a class cast exception
}

您仍然会因装箱物品和类型检查而受到一些处罚 返回的值,当然如果你的调用与 getParam 的实现实际上做了什么,你会得到一个类 强制转换异常。


3
投票

我的 2 美分,带有 Google HTTP 客户端的示例:

static public <Any> Any getJson(final String url, final Class<Any> parseAs) throws IOException {
        HttpRequestFactory requestFactory
                = HTTP_TRANSPORT.createRequestFactory(
                (HttpRequest request) -> {
                    request.setParser(new JsonObjectParser(JSON_FACTORY));
                });

        HttpRequest request = requestFactory.buildRequest(HttpMethods.GET, new GenericUrl(url), null);

        return request.execute().parseAs(parseAs);
    }

可以这样使用:

HashMap<String, Object> out = HttpUtils.getJson( "https://api.qwant.com", HashMap.class);

1
投票

如果您真的只返回

boolean
float
,那么您能做的最好的就是
Object

如果要返回变量对象,则必须选择具有最不常见超类的返回类型。基元没有超类,但它们将被装箱到对象表示(如

Boolean
Float
)中,它们具有共同的超类
Object


0
投票

也可以像下面的例子那样:

public class Test 
{
  public <T> T dynamicReturnMethod(Class<T> clazz) 
  {
    //your code
    return class.getDeclaredConstructor().newInstance();
  }

//usage
  public static void main(String[] args) 
  {
    Test t = new Test();
    ClassObjectWhichNeedsToBeReturned obj = 
       t.dynamicReturnMethod(ClassObjectWhichNeedsToBeReturned.class)
  }
}

这已经使用 java 11 进行了测试


0
投票

您可以使用对象类并通过检查类型方法“取消装箱”值。

  public Object 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;
        }


    public byte getByte( Object obj ) throws Exception{
      if( obj instanceof Byte ) return (byte)obj ;
      throw new Exception("Not instance of Byte");
    }

     public float getFloat( Object obj ) throws Exception{
      if( obj instanceof Float) return (float)obj ;
      throw new Exception("Not instance of Float");
     }
© www.soinside.com 2019 - 2024. All rights reserved.