如何在Java 8编译时确保方法签名;实施;功能接口
Java 8中是否有类似的方法的如何在Java 8编译时确保方法签名;实施;功能接口,java,java-8,functional-interface,Java,Java 8,Functional Interface,Java 8中是否有类似的方法的实现关键字 假设我有一个功能接口: @FunctionalInterface interface LongHasher { int hash(long x); } class LongHashes { static int xorHash(long x) { return (int)(x ^ (x >>> 32)); } static int continuingHash(long x) {
实现
关键字
假设我有一个功能接口:
@FunctionalInterface
interface LongHasher {
int hash(long x);
}
class LongHashes {
static int xorHash(long x) {
return (int)(x ^ (x >>> 32));
}
static int continuingHash(long x) {
return (int)(x + (x >>> 32));
}
static int randomHash(long x) {
return xorHash(x * 0x5DEECE66DL + 0xBL);
}
}
class LongHashes {
private static final LongHasher XOR_HASH = LongHashes::xorHash;
private static final LongHasher CONTINUING_HASH = LongHashes::continuingHash;
private static final LongHasher RANDOM_HASH = LongHashes::randomHash;
static int xorHash(long x) {
return (int)(x ^ (x >>> 32));
}
static int continuingHash(long x) {
return (int)(x + (x >>> 32));
}
static int randomHash(long x) {
return xorHash(x * 0x5DEECE66DL + 0xBL);
}
}
以及一个包含3个静态方法的库“实现”此功能接口:
@FunctionalInterface
interface LongHasher {
int hash(long x);
}
class LongHashes {
static int xorHash(long x) {
return (int)(x ^ (x >>> 32));
}
static int continuingHash(long x) {
return (int)(x + (x >>> 32));
}
static int randomHash(long x) {
return xorHash(x * 0x5DEECE66DL + 0xBL);
}
}
class LongHashes {
private static final LongHasher XOR_HASH = LongHashes::xorHash;
private static final LongHasher CONTINUING_HASH = LongHashes::continuingHash;
private static final LongHasher RANDOM_HASH = LongHashes::randomHash;
static int xorHash(long x) {
return (int)(x ^ (x >>> 32));
}
static int continuingHash(long x) {
return (int)(x + (x >>> 32));
}
static int randomHash(long x) {
return xorHash(x * 0x5DEECE66DL + 0xBL);
}
}
在将来,我希望能够互换使用这3种方法的任何引用作为参数。例如:
static LongHashMap createHashMap(LongHasher hasher) { ... }
...
public static void main(String[] args) {
LongHashMap map = createHashMap(LongHashes::randomHash);
...
}
如何在编译时确保
LongHashes::xorHash
、LongHashes::continueinghash
和LongHashes::randomHash
与LongHasher.hash(long x)
?一种方法是直接从LongHashes
类返回LongHasher
:
class LongHashes {
private static int xorHashImpl(long x) {
return (int)(x ^ (x >>> 32));
}
static LongHasher xorHash() {
return LongHashes::xorHashImpl;
}
}
但这会向
longhashs
类添加一些代码,并将其绑定到LongHasher
接口,这可能并不可取(尽管这基本上就是您所要求的)。您所要求的语法结构并不存在。但是,您可以创建一个静态常量,将方法引用显式分配给接口:
@FunctionalInterface
interface LongHasher {
int hash(long x);
}
class LongHashes {
static int xorHash(long x) {
return (int)(x ^ (x >>> 32));
}
static int continuingHash(long x) {
return (int)(x + (x >>> 32));
}
static int randomHash(long x) {
return xorHash(x * 0x5DEECE66DL + 0xBL);
}
}
class LongHashes {
private static final LongHasher XOR_HASH = LongHashes::xorHash;
private static final LongHasher CONTINUING_HASH = LongHashes::continuingHash;
private static final LongHasher RANDOM_HASH = LongHashes::randomHash;
static int xorHash(long x) {
return (int)(x ^ (x >>> 32));
}
static int continuingHash(long x) {
return (int)(x + (x >>> 32));
}
static int randomHash(long x) {
return xorHash(x * 0x5DEECE66DL + 0xBL);
}
}
这样,如果方法签名或接口以不兼容的方式更改,编译将中断。如果需要,可以将它们声明为public,并使用而不是方法引用
如果您担心这些静态lambda在运行时挂起在内存中,您可以将此声明移动到单独的类(例如,嵌套),该类可编译但从未加载。我过去也希望这样做,但不,您不能这样做。但是你知道。在Java8之前就有Java。改为这样做:
enum LongHashes implements LongHasher {
XOR {
@Override
public int hash(long x) { ... }
},
CONTINUING {
@Override
public int hash(long x) { ... }
},
RANDOM {
@Override
public int hash(long x) { ... }
}
}
然后:
public static void main(String[] args) {
LongHashMap map = createHashMap(LongHashes.RANDOM);
...
}
您可以声明函数对象,而不是方法
class LongHashes {
static final LongHasher xorHash = x -> {
return (int)(x ^ (x >>> 32));
};
... etc
LongHashMap map = createHashMap(LongHashes.randomHash);
或者创建3个实现LongHasher的类。需要LongHasher时,获取或创建实例并传递:
LongHasher longHasher = ... // new RandomLongHasher(), factory, .......
LongHashMap map = createHashMap(longHasher);
在此处以静态方法编写函数:
- 让人难以理解
- 听起来像是重新发明轮子;轮子是接口/类,通过在问题描述中的引号之间使用“接口”来重新发明;-)李>
我们不必在任何地方都使用lambdas。尽管我发现Tagir的答案是一个很好的技巧,但在创建新哈希器时很容易忘记添加私有常量 与往常一样,在处理潜在的重构问题时,我认为测试是答案:
public class LongHashesTest {
@Test
public void xorHash() {
LongHasher xorHash = LongHashes::xorHash;
assertEquals(1768181579, xorHash.hash(34312465426524234l));
}
@Test
public void continuingHash() {
LongHasher continuingHash = LongHashes::continuingHash;
assertEquals(1529080340, continuingHash.hash(74543524355l));
}
@Test
public void randomHash() {
LongHasher randomHash = LongHashes::randomHash;
assertEquals(-1100764221, randomHash.hash(4343245345432154353l));
}
}
这对8年级之前的学生很好。在Java8中,如果您的意思是答案中的代码是否可能,那么直接lambda
XOR=x->…
@Yahor就更简单了。如果您的意思是在enum
中是否可以XOR=x->
,则不可以;但是您不需要enum,只需声明静态字段LongHasher XOR=x->{…}
它看起来很像一个简单的方法。@bayou.io:仅仅因为您可以,并不意味着您必须这样做。我只是想指出,开发人员现在不需要把所有东西都塞进函数中。之前…@Lukas Eder:我只是想指出之前的想法,因为bayou.io的评论听起来像是将lambda表达式与enum
结合起来是不可能的,我想,链接可以避免在注释中进行冗长的讨论。一个(不相关的)旁白:您的哈希函数看起来像一个LongToIntFunction
。(我不确定是否应该引入这样一个(新的)接口,该接口在结构上与现有接口“相同”——但给它起一个名称,表明它将用于什么,可能会有一些好处……)它可以被进一步简化,不是吗:)你不需要xorHashImpl
方法,只需要内联lambda;你不需要xorHash
作为一个方法,只要有一个静态字段就可以了代码>。