Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Notation - Printed.<String, String>toSysOut().withLabel("source-stream")

Tags:

java

generics

I knew Java well, however, used it some time back . I come across something new such as

Printed.<String, String>toSysOut().withLabel("source-stream")

Esp , highlighted part , it seems <String, String> is return type of toSysOut() . Most of the time , i see such as

Printed.toSysOut().withLabel("source-stream")

What kind of notation is that, where the return type is used along with the reference operator (.)

like image 277
Nag Avatar asked Jan 29 '26 09:01

Nag


1 Answers

Java has something called 'type parameters'. They can, well, parameterize a type using another type. For example:

List<String> iCanOnlyContainStrings = new ArrayList<String>();
iCanOnlyContainStrings.add(5); // does not compile!

Methods can also be parameterized. For example:

public <T> T firstNonNull(T... inputs) {
    for (T input : inputs) if (input != null) return input;
}

This method states that there is some type which we shall call T. We know nothing about it, but this method's argument types AND its return type are all the same type. Thus, you can invoke it as follows:

String a = firstNonNull("b", "c");

and this just compiles. Had you written:

public Object firstNonNull(Object... inputs) {
    for (Object input : inputs) if (input != null) return input;
}

Then you would need to cast the return value of the firstNonNull method: (String) firstNonNull(...).

Normally java will infer the type you wanted here. But if you want to be explicit about it, you can do that, and that is the syntax you see here:

public class Example {
    public static <T> T firstNonNull(T... inputs) {
        for (T input : inputs) if (input != null) return input;
    }

    public static void invokeExample() {
        Serializable s = Example.<Serializable>firstNonNull(null, null);
    }
}

You must have the '.' to be explicit, which sometimes means you have to resort to writing this.foo() or YourType.foo() just so you have a dot.

Another way to write the code you have up there is something like:

Printer<String, String> printer = Printed.toSysOut();

Now java's inference will correctly infer the type vars on the method 'toSysOut' are intended to be String and String. This syntax is most commonly observed in these chained builder type scenarios, because java won't look ahead endlessly to infer. FOr example, this does not work:

List<String> names = ImmutableList.builder().add("Hello").add("World").build();

because the builder() method is parameterized, and java is not going to inspect all your add methods just to know what you probably wanted (nor look ahead to the build() method, then warp back to the variable declaration). Thus, you see this a ton:

List<String> names = ImmutableList.<String>builder().add(...).build();
like image 75
rzwitserloot Avatar answered Jan 31 '26 21:01

rzwitserloot



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!