如何在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) {

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) {
        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
作为一个方法,只要有一个静态字段就可以了