简体   繁体   中英

Difference between static Interface method generic singleton factory?

In Effective Java Item 27, Bloch advocates the use of a generic singleton factory "to create an object that is immutable but applicable to many different types". His example is:

interface UnaryFunction<T> {
    T apply(T t);
}

public class Example {
    private static UnaryFunction<Object> IDENTITY_FUNCTION = (k -> k);

    // [snip] detailed explanation of why this is safe...
    @SuppressWarnings("unchecked")
    public static <T> UnaryFunction<T> identityFunction() {
        return (UnaryFunction) IDENTITY_FUNCTION;
    }

    public static void main(String... args) {
        String[] strings = { "jute", "hemp", "nylon" };
        UnaryFunction<String> sameString = identityFunction();
        for (String s : strings) {
            System.out.println(sameString.apply(s));
        }
    }
}

Here's how OpenJDK implements the identity function:

@FunctionalInterface
interface UnaryOperator<T> extends Function<T, T> {
    static <T> UnaryOperator<T> identity() {
        return t -> t;
    }
}

Given that Java 8 supports static methods on interfaces, is there still a use case for the generic singleton factory?

Default methods in interfaces and generic singleton factory are independent of each other.

While generic singleton factory is an implementation technique that allows you to reuse the same object in different contexts by applying our knowledge of Java internals (specifically, our knowledge of type erasure) default methods in interfaces are there to let you share implementations "horizontally".

You could combine the two techniques by using generic singleton factory inside the default method implementation:

@FunctionalInterface
interface UnaryOperator<T> extends Function<T, T> {
    static UnaryOperator<Object> IDENTITY_FUNCTION = (k -> k);
    static <T> UnaryOperator<T> identity() {
        return (UnaryOperator)IDENTITY_FUNCTION;
    }
}

Demo.

So the answer your question is "No, static interface methods do not replace generic singleton factory".

Given that Java 8 supports static methods on interfaces, is there still a use case for the generic singleton factory?

The UnaryOperator example you present is not guaranteed to provide a singleton. It is permitted, but not required, to do so.

Moreover, if the code you presented did assuredly provide a singleton, then it would simply be an implementation of the generic singleton factory pattern as a static interface method. It might then prove a particularly convenient implementation, but it's not a different alterrnative.

And even if you considered the static interface method approach a different alternative, it still only covers the cases that the interface author or maintainer thought of. If you want a different one then it still makes sense to use the conventional form of the generic singleton factory, say:

public class Example {
    private final static UnaryFunction<Object> LOG_FUNCTION =
            (k -> { System.out.println(k); return k; });

    @SuppressWarnings("unchecked")
    public static <T> UnaryFunction<T> logFunction() {
        return (UnaryFunction) LOG_FUNCTION;
    }

    public static void main(String... args) {
        String[] strings = { "jute", "hemp", "nylon" };
        UnaryFunction<String> logIt = logFunction();
        for (String s : strings) {
            logIt(s);
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM