Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java-如何将方法作为参数传递?_Java_Lambda - Fatal编程技术网

Java-如何将方法作为参数传递?

Java-如何将方法作为参数传递?,java,lambda,Java,Lambda,我有一段反复使用的代码。以下是两个例子: public java.sql.Struct createStruct(String typeName, Object[] attributes) { String searchPath = getSearchPath(); String name = setSearchPathToSchema(typeName); Struct ret = delegate().createStruct(name.toLowerCase(), attrib

我有一段反复使用的代码。以下是两个例子:

public java.sql.Struct createStruct(String typeName, Object[] attributes) {
  String searchPath = getSearchPath();
  String name = setSearchPathToSchema(typeName);
  Struct ret = delegate().createStruct(name.toLowerCase(), attributes);
  setSearchPath(searchPath);
  return ret;
}

public java.sql.Array createArray(String typeName, Object[] elements) {
  String searchPath = getSearchPath();
  String name = setSearchPathToSchema(typeName);
  Array ret = delegate().createArray(name.toLowerCase(), elements);
  setSearchPath(searchPath);
  return ret;
}
您可以看到这两种方法具有一般形式:

public <T> createXXX(String typeName, Object[] objects) {
  String searchPath = getSearchPath();
  String name = setSearchPathToSchema(typeName);
  T ret = delegate().createXXX(name.toLowerCase(), objects);
  setSearchPath(searchPath);
  return ret;
}
我已经阅读了明显重复的问题:

  • 以及关于泛型方法引用的一些问题:

  • 不管出于什么原因,它对我来说都不是胶凝的,所以我冒着问一个问题的风险,这个问题会立即被标记为重复的,希望有人会同情我,帮助我走出困境

    更新2015-02-06

    虽然两者给出了基本相同的答案,但路易斯更迂腐地提供了一种最适合我的模式。。。通过一个关于如何传递方法引用的显式示例

    以下是最终对我有用的东西:

    interface SearchPathCreator<T> {
      T create(String typeName, Object[] objects) throws SQLException;
    }
    
    private <T> T createTypeWithCorrectSearchPath(
                    String typeName,
                    Object[] objects,
                    SearchPathCreator<?> creator) throws SQLException {
      String searchPath = getSearchPath();
      String name = setSearchPathToSchema(typeName);
      //noinspection unchecked
      T ret = (T) creator.create(name.toLowerCase(), objects);
      setSearchPath(searchPath);
      return ret;
    }
    
    接口MyMethodType{
    T方法(字符串名称,对象[]对象);
    }
    私有T createTypeWithCorrectSearchPath(
    字符串类型名,
    对象[]对象,
    MyMethodType(impl){
    字符串searchPath=getSearchPath();
    字符串名称=setSearchPathToSchema(typeName);
    T ret=impl.method(名称、对象);
    设置搜索路径(搜索路径);
    返回ret;
    }
    createTypeWithCorrectSearchPath(类型名称、对象、委托()::createStruct);
    

    关键在于a)创建自己的接口类型,尽管我认为您可以使用
    BiFunction
    ,b)将方法引用与

    一起使用,您可以通过传递仅用于执行该函数的对象来解决此问题。这里有一个小例子给你一个想法。 为函数类型创建一个接口。您需要像我在这里做的那样使用泛型:

    public interface Creator<A>{
        A create(String name, Object[] attributes);
    }
    
    公共接口创建者{
    创建(字符串名称、对象[]属性);
    }
    
    然后定义采用您刚才指定类型函数的方法:

    public <A> A create(String typeName, Object[] attributes, Creator<A> creator){
        String searchPath = getSearchPath();
        String name = setSearchPathToSchema(typeName);
        A ret = creator.create(name.toLowerCase(), attributes);
        setSearchPath(searchPath);
        return ret;
    }
    
    public A create(字符串类型名、对象[]属性、创建者){
    字符串searchPath=getSearchPath();
    字符串名称=setSearchPathToSchema(typeName);
    A ret=creator.create(name.toLowerCase(),attributes);
    设置搜索路径(搜索路径);
    返回ret;
    }
    
    最方便的方法是匿名类,您可以在其中定义接口实现:

    java.sql.Struct struct = create("foo bar", new Object[]{"att1", "att2"}, new Creator<Struct>() {
        @Override
        public Struct create(String name, Object[] attributes) {
            return //your implementation..
        }
    })
    
    java.sql.Struct Struct=create(“foo-bar”,新对象[]{“att1”,“att2”},新创建者(){
    @凌驾
    公共结构创建(字符串名称,对象[]属性){
    return//your实现。。
    }
    })
    

    如果由于需要访问委托().createXXX(…),因此无法将实现放入匿名类,只需将实现接口的类的定义放入可访问方法的范围内即可。

    Louis的答案正确;但是,我不清楚在调用create方法时,
    delegate()
    是否可用。如果不可用,则需要一个三参数接口方法

    我不知道什么类型的
    delegate()
    返回,但假设它是
    delegate
    。需要注意的一点是,如果
    Delegate
    有一个实例方法
    createArray(String s,Object[]objects)
    ,则可以使用
    Delegate::createArray
    作为具有三个参数的函数的函数接口的方法引用。第一个参数是
    委托
    。因此:

    interface MyMethodType<T> {
        T method(Delegate delegate, String name, Object[] objects);
    }
    
    调用的第一个参数将成为双参数实例方法操作的实例。也就是说,如果实际参数是
    Delegate::createArray
    ,那么它的调用方式如下

    delegate().createArray(name.toLowerCase(), objects);
    
    与Louis的回答不同,您必须在这里定义自己的接口,因为Java8中没有内置的
    TriFunction

    有关如何使用方法引用的完整说明,请参见。这个特殊的参数列在“如果表单是ReferenceType::[TypeArguments]Identifier”开头的段落中


    编辑:再看一眼这个问题,我发现
    createTypeWithCorrectSearchPath
    是一个私有方法,不是从外部调用的。所以这个答案可能不适用。不过,我把它留在这里,因为在一些类似的情况下,它可能是一个有用的答案。

    @ajb OP的问题似乎表明在“类似于此”的部分下面传入
    delegate()::createStruct
    。我的回答基于这个假设。如果OP没有这个例子,我会将
    Delegate
    移动到接口方法中。这个答案让我走得最远。当我逐字使用此模式时,
    createTypeWithCorrectSearchPath
    中的方法引用
    delegate()::createStruct
    在方法引用中显示
    错误的返回类型:无法将
    java.sql.Struct`转换为
    T
    。我用最终有效的结构更新了我的问题。这看起来…真的很奇怪。在我看来,更可能的情况是,您需要的是显式类型参数,而不是最终得到的未经检查的强制转换。由于此搜索路径内容似乎是关于恢复以前的状态,因此我宁愿使用
    String searchPath=getSearchPath();尝试{return impl.method(setSearchPathToSchema(typeName),objects);}最后{setSearchPath(searchPath);}
    @LouisWasserman我更喜欢显式类型参数,但最终得到的是编译器所需要的。我猜编译器无法确定t在编译时应该是什么(在本例中,它可能是
    结构
    数组
    ),因此需要使用通配符。但这只是我的猜测……虽然这并不是针对我目前的问题,但它非常有用。
    java.sql.Struct struct = create("foo bar", new Object[]{"att1", "att2"}, new Creator<Struct>() {
        @Override
        public Struct create(String name, Object[] attributes) {
            return //your implementation..
        }
    })
    
    interface MyMethodType<T> {
        T method(Delegate delegate, String name, Object[] objects);
    }
    
    impl.method(delegate(), name.toLowerCase(), objects);
    
    delegate().createArray(name.toLowerCase(), objects);