根据调用方法更改返回类型

时间:2009-05-28 05:45:53

标签: java generics reflection return-value typing

基本上我想要的是两种具有稍微不同的返回值的公共方法,以调用相同的方法来完成所需的任何工作。它们都返回私有方法的返回值,但私有方法将知道如何根据调用它的公共方法返回正确的值。

示例方法:

public Map<Type1, Type3> doSomething1();
public Map<Type2, Type3> doSomething2();

private Map<Type1/Type2, Type3> doSomething(); 

因此,在上面的示例中,doSomething()返回Type1或Type2作为Map的键类型,具体取决于调用它的公共方法。它可以执行简单的检查,并使用正确类型的对象填充地图。

也许这可以通过一些聪明的Java反射来完成?我不确定。这一切看起来都很狡猾,所以如果有更好的方法可以解决这个问题,我会全力以赴。

7 个答案:

答案 0 :(得分:8)

我强烈建议在这里避免使用反射魔法。一个函数必须在属性上做一件事,而且不能依赖于谁调用它。

更好的方法是将doSomething()重构为更小的函数,创建两个名为doS​​omethingFor1()和doSomethingFor2()的新函数。这两个函数都可以重用旧的doSomething()的重构部分。

现在有doSomething1()调用并使用doSomethingFor1()。

同样,doSomething2()应该使用doSomethingFor2()。

欢呼声,

JRH。

答案 1 :(得分:3)

请注意: 我误解了这个问题,所以这个答案与问题的答案相反。我将把它留作社区维基作为参考,但这不能回答原来的问题。

如果Type1Type2的公共子类型名为SuperType,则说第一种类型为? extends SuperType会有效。

以下是一个使用IntegerDouble作为两种类型的示例,以及它们的共同祖先Number

private Map<Integer, String> doSomethingForInteger() {
  HashMap<Integer, String> map = new HashMap<Integer, String>();
  map.put(10, "Hello");
  return map;
}

private Map<Double, String> doSomethingForDouble() {
  HashMap<Double, String> map = new HashMap<Double, String>();
  map.put(3.14, "Apple");
  return map;
}

public Map<? extends Number, String> doSomething(boolean b) {
  if (b)
    return doSomethingForInteger();
  else
    return doSomethingForDouble();
}

此处,doSomething方法将返回两种类型的HashMap,具体取决于传入的boolean。返回HashMap<Integer, String>HashMap<Double, String>通过doSomething方法。

实际上使用doSomething调用boolean可以这样完成:

Map<? extends Number, String> map1 = doSomething(true);
Map<? extends Number, String> map2 = doSomething(false);

map1将以Hashmap<Integer, String>结束,而map2将获得Hashmap<Double, String>

答案 2 :(得分:1)

如果其他所有方法都失败了,那么让私有方法返回Object并在公共方法中使用强制转换。

答案 3 :(得分:1)

第一个问题是为什么你需要这个确切的结构。

但安全的方法是让它回归

public Map<Object, Type3> doSomething();

如果Type1和Type2没有常见的超类型。如果你有一个共同的超级类型,你可以使用它而不是对象。

最好重构不需要的代码。

答案 4 :(得分:1)

我需要你的问题中缺少一些信息,例如如何实例化type1和type2,因为你不能直接从任意类型参数实例化。现在,我们假设有一些常用数据用于实例化type1和type2。否则,没有充分的理由为两者使用一种方法。在后一种情况下,这意味着一个函数根据类型执行两个单独的操作,这是错误的编程。如果您将拥有直接基于调用方法的逻辑,只需使用两个私有方法并重构常见的东西。

如果仅根据某些数据进行不同的实例化,最简单的方法是声明私有内部接口:

private interface Instantiator<T> {

     T getNew(Data data);        

}

现在,假设您可以实例化您的类型,您实际上可以使用它:

private <T> Map<T,Type3> doSomething(Instantiator<T> instantiator) {...}

作为方法签名,并让公共方法使用适当的Instantiator实现调用它。

答案 5 :(得分:0)

你绝对可以通过使用反射分析堆栈来实现。但我会尽量避免它,并且:

  • 返回基本类型(或对象)并在调用者中正确地投射它,你将不得不这样做
  • 将参数传递给私有方法,指示以何种方式执行操作并返回

答案 6 :(得分:0)

你可以模拟闭包的想法:

interface MappingClosure {
    public void map(Map, MapProvider);
}


class Caller implements MappingClosure {
     public void map(final Map MAP, final MapProvider CALLEE) {
         this.MAP = specialise(MAP);
         // CALLEE USED AS KEY
     }
}


class MapProvider {  
    public Map getMap(final MappingClosure CALLER) {
        return CALLER.map(mapInstance, this);
    }
}

然后修改数据以满足对象的需要与具有需要它的对象的方法不同。