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