Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to ensure at Java 8 compile time that a method signature "implements" a functional interface

Is there in Java 8 any analogue for implements keyword for methods?

Let's say I have a functional interface:

@FunctionalInterface
interface LongHasher {
    int hash(long x);
}

And a library of 3 static methods "implementing" this functional interface:

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

In the future I want to be able to interchangeably use any of references to these 3 methods as a parameter. For example:

static LongHashMap createHashMap(LongHasher hasher) { ... }
...
public static void main(String[] args) {
    LongHashMap map = createHashMap(LongHashes::randomHash);
    ...
}

How can I ensure at compile time that LongHashes::xorHash, LongHashes::continuingHash and LongHashes::randomHash have the same signature as LongHasher.hash(long x)?

like image 422
Yahor Avatar asked May 12 '15 16:05

Yahor


People also ask

What is the use of functional interface in Java 8 when to use functional interface in Java 8?

If we look into some other programming languages such as C++, JavaScript; they are called functional programming language because we can write functions and use them when required. Some of these languages support Object Oriented Programming as well as Functional Programming.

How many methods are there in the functional interface in Java 8?

An Interface that contains exactly one abstract method is known as functional interface. It can have any number of default, static methods but can contain only one abstract method. It can also declare methods of object class. Functional Interface is also known as Single Abstract Method Interfaces or SAM Interfaces.

Which functional interfaces does Java provide to be implemented by lambda expressions?

Note that lambda expressions can only be used to implement functional interfaces. In the above example also, the lambda expression implements Consumer Functional Interface. A Java program to demonstrate working of lambda expression with two arguments.

How can we avoid implementing all methods interface?

How can we avoid implementing all methods interface in Java? Declare the missing methods abstract in your class. This forces you to declare your class abstract and, as a result, forces you to subclass the class (and implement the missing methods) before you can create any objects.


2 Answers

I had wished for this too, in the past, but no you can't do that. But you know. There was Java before Java 8. Do this instead:

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) { ... }
    }
}

And then:

public static void main(String[] args) {
    LongHashMap map = createHashMap(LongHashes.RANDOM);
    ...
}
like image 89
Lukas Eder Avatar answered Nov 12 '22 15:11

Lukas Eder


There's no such syntax construction you're asking for. However you can create a static constant where you explicitly assign the method reference to your interface:

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

This way your compilation will break if either method signature or interface changes in incompatible way. If you want you may declare them public and use instead of method references.

If you care that these static lambdas will be hanging in memory at runtime, you can move this declaration to the separate class (for example, nested), which compiles but never loaded.

like image 29
Tagir Valeev Avatar answered Nov 12 '22 15:11

Tagir Valeev