我正在寻找一个更漂亮的解决方案。问题在于将泛型和 Lambda 表达式结合起来。
根据 Java 语言规范 这不可能是我想要的方式。
所以我问你:你知道一种更优雅的方法来处理这个问题吗?有什么建议或常见做法吗?
我的“List”类,我在很多函数中都需要
BiPredicate<T, T>
:
package stackoverflow.genericlambdas;
import java.util.ArrayList;
import java.util.function.BiPredicate;
public class MyListImpl<T> {
private final ArrayList<T> mItems = new ArrayList<>();
public void addItem(final T pItem) {
mItems.add(pItem);
}
// assume my library is full of such methods
public int getFirstIndexOf(final BiPredicate<T, T> pIdentifier, final T pItem) {
for (int i = 0; i < mItems.size(); i++) {
final T t = mItems.get(i);
if (pIdentifier.test(t, pItem)) return i;
}
return -1; // not found
}
}
我的“库”类,我想在其中存储模板
BiPredicate<T, T>
s:
package stackoverflow.genericlambdas;
import java.util.Objects;
import java.util.function.BiPredicate;
public class Library {
static public class CLUMSY_IDENTITY_CLASS<T> implements BiPredicate<T, T> {
@Override public boolean test(final T p, final T q) {
return p == q;
}
}
static public class CLUMSY_EQUALITY_CLASS<T> implements BiPredicate<T, T> {
@Override public boolean test(final T p, final T q) {
return Objects.equals(p, q);
}
}
static public final BiPredicate<T, T> IDENTITY = (p, q) -> p == q; // compilation error
static public final BiPredicate<T, T> EQUALITY = (p, q) -> Objects.equals(p, q); // compilation error
}
我的“使用”类,我想在其中使用这些模板:
package stackoverflow.genericlambdas;
import java.util.Objects;
public class GenericLamdasUse {
public static void main(final String[] args) {
final MyListImpl<String> list = new MyListImpl<>();
list.addItem("aa");
list.addItem("bb");
list.addItem("cc");
final String testItem = "cc";
final String testItem2 = "c" + (Math.random() < 2 /* always true */ ? "c" : ""); // this builds a new string that is not == the compile constant String "cc"
final int whatIKnowWorks1 = list.getFirstIndexOf((p, q) -> Objects.equals(p, q), testItem);
final int whatIKnowWorks2 = list.getFirstIndexOf((p, q) -> p == q, testItem);
final int whatIKnowWorks3 = list.getFirstIndexOf(new Library.CLUMSY_IDENTITY_CLASS<>(), testItem); // dont't want the re-instantiation
final int whatIKnowWorks4 = list.getFirstIndexOf(new Library.CLUMSY_EQUALITY_CLASS<>(), testItem); // for ever time i would need that
final Library.CLUMSY_IDENTITY_CLASS<String> clumsy5 = new Library.CLUMSY_IDENTITY_CLASS<>(); // dont't want the re-instantiation
final Library.CLUMSY_EQUALITY_CLASS<String> clumsy6 = new Library.CLUMSY_EQUALITY_CLASS<>();
final int whatIKnowWorks5 = list.getFirstIndexOf(clumsy5, testItem); // for ever time i would need that
final int whatIKnowWorks6 = list.getFirstIndexOf(clumsy6, testItem); // also, the types <String> have to match each time
final int whatIWant1 = list.getFirstIndexOf(Library.EQUALITY, testItem); // I want this, but: compilation error
final int whatIWant2 = list.getFirstIndexOf(Library.IDENTITY, testItem); // I want this, but: compilation error
}
}
您无法通过静态 fields 来执行此操作,因为
T
必须在范围内定义。像这样的事情通常是通过静态方法实现的。
package stackoverflow.genericlambdas;
import java.util.Objects;
import java.util.function.BiPredicate;
public class Library {
public static <T> BiPredicate<T, T> identity() {
return (a, b) -> a == b;
}
public static <T> BiPredicate<T, T> equals()
return Objects::equals;
}
}