如何在Java 8编译时确保方法签名“实现”功能接口

时间:2015-05-12 16:35:05

标签: java java-8 functional-interface

Java 8中是否存在方法的align=right 关键字的任何类似物?

假设我有一个功能界面:

text-align:right

一个包含3种静态方法的库“实现”这个功能界面:

implements

将来我希望能够互换地使用这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); } } static LongHashMap createHashMap(LongHasher hasher) { ... } ... public static void main(String[] args) { LongHashMap map = createHashMap(LongHashes::randomHash); ... } LongHashes::xorHashLongHashes::continuingHash具有相同的签名?

6 个答案:

答案 0 :(得分:9)

过去我也曾希望这样做,但不,你不能这样做。但是你知道。在Java 8之前有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);
    ...
}

答案 1 :(得分:8)

你没有要求的语法结构。但是,您可以在显式将方法引用分配给接口时创建静态常量:

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将在运行时挂在内存中,你可以将这个声明移动到单独的类(例如,嵌套),它编译但从不加载。

答案 2 :(得分:3)

您可以声明函数对象,而不是方法。

class LongHashes {

    static final LongHasher xorHash = x -> {
        return (int)(x ^ (x >>> 32));
    };

    ... etc


    LongHashMap map = createHashMap(LongHashes.randomHash);

答案 3 :(得分:1)

一种方法是直接从LongHasher类返回LongHashes

class LongHashes {
  private static int xorHashImpl(long x) {
    return (int)(x ^ (x >>> 32));
  }
  static LongHasher xorHash() {
    return LongHashes::xorHashImpl;
  }
}

但是这会为你的LongHashes类添加一些代码,并将其与LongHasher接口联系起来,这可能是不可取的(尽管这基本上就是你所要求的)。

答案 4 :(得分:1)

或者只创建3个实现LongHasher的类。当您需要LongHasher时,获取或创建一个实例并传递它:

LongHasher longHasher = ... // new RandomLongHasher(), factory, .......
LongHashMap map = createHashMap(longHasher);

在此处将函数编写为静态方法:

  • 让人难以理解
  • 听起来像重新发明轮子;轮子是接口/类,重新发明通过在问题描述中使用引号之间的“接口”暗示; - )

我们并没有被迫在任何地方使用lambdas。

答案 5 :(得分:0)

虽然我发现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));
    }
}