如何处理多级Java Supplier调用?

时间:2016-09-09 23:35:25

标签: java lambda

我正在处理一些自动生成的旧Java代码,它具有相同的方法名称和返回类型,但不实现任何接口。我想找到一些处理通话的常用方法。

例如,我有一组java类,A1,A2,都包含一个方法," getData()",getData方法将返回一组另一个类实例,如B1, B2。然后在B1,B2中,他们都有类似" getName"的方法。

我需要调用A.getData()。getName()。除了使用Java反射之外,还有什么方法可以处理这些场景吗?

class A1 {
  B1 b;
  B1 getData() {
      return b;
  }
}

class B1 {
  String getName() {
      return "myname in B1";
  }
}

如果B1,B2实现了一些具有getName方法的接口(例如NameInterface),我可以使用如下的供应商:

A1 a1 = ...
A2 a2 = ...  
doGetName(a1::getData);
doGetName(a2::getData);

void doGetName(Supplier<NameInterface> func) {
    func.get().getName();
}

但不幸的是,B1,B2也是自动生成的遗留代码,我无法为它们分配接口。

我可以将B1,B2定义为供应商吗?如果有可能,如何定义它?

感谢。

2 个答案:

答案 0 :(得分:2)

如果我可以声明您的方法(getDatagetNamepublic,以下内容适用于我。我没有使用任何供应商。

/**
 * Requires that {@code a} has a public method getData that returns an object with a public getName method
 * 
 * @param a
 * @return a.getData().getName(); or null if the methods don’t exist
 */
public static String doGetName(Object a) {
    try {
        Class<?> aClass = a.getClass();
        Method getDataMethod = aClass.getMethod("getData");
        Object b = getDataMethod.invoke(a);
        Class<?> bClass = b.getClass();
        Method getNameMethod = bClass.getMethod("getName");
        Object name = getNameMethod.invoke(b);
        return name.toString();
    } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
        System.out.println(e);
        return null;
    }
}

请致电

    System.out.println(doGetName(new A1()));

请根据您的需要进行修改。

如果您的方法不公开,则可以使用getDeclaredMethod()代替getMethod()

答案 1 :(得分:1)

我能看到的唯一选择是编辑A类以直接返回包装数据的名称。

class A1 {
  B1 b;
  B1 getData() {
      return b;
  }
  String getDataName() {
      //Adding a null check here is probably smart, unless you know b != null
      return getData().getName();
  }
}

因为(您已暗示)每个A类具有不同(但具体)的包装数据,您可以访问getName()特定类型的B方法A }。您仍然需要将该方法复制粘贴到每个B1中,因为B2A等没有常见的超类型,但它不是结束世界,比不得不求助于反思要好得多。

从那里我们可以为interface DataWrapper { Object getData(); //Could change the return type to a common ancestor if //the legacy code is ever refactored String getDataName(); } 添加一个通用界面:

A

并且有一个抽象类abstract class A implements DataWrapper { //Other A stuff } class A1 extends A {...} class A2 extends A {...} 实现,但将实现留给它的子类:

A

或者只是将这些方法放入abstract class A { Object getData(); //Could change the return type to a common ancestor if //the legacy code is ever refactored String getDataName(); //Other stuff. } class A1 extends A {...} class A2 extends A {...} 本身:

A a = ...
String name = a.getDataName();

根本不需要界面。

然后获取包装数据的名称没有问题。

    <div class="wrapper" id="wrapper"></div>
<script type="application/javascript">
    var x, i, y;
    for(i = 0; i <= 10; i++){
        y = i;
        x = "<button class=btn_class"+y+"id=btn"+y+"onclick(alert(this.id);>Ukor</button>";
        $("#wrapper").append(x);
    }

    $("button").on("click", function(){
        alert(this.id);
    });
</script>