Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 7 Diamond Operation in method call

This is kind of a follow up question on the discussion:

Why doesn't the diamond operator work within a addAll() call in Java 7?

From the Java Tutorial,

http://docs.oracle.com/javase/tutorial/java/generics/gentypeinference.html

Note that the diamond often works in method calls; however, for greater clarity, it is suggested that you use the diamond primarily to initialize a variable where it is declared

So, I am a bit confused about the first line. When does diamond work in method calls?

A bit more explanation on how diamond operator works can be found here:

http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#What%20is%20type%20argument%20inference%20for%20constructors?

And from this, I have tried the following, which works fine:

Give that I have:

private static class Box<T>{
    public Box(T t){}
}
static void f(Box<Integer> box){}

a call like the following compiles fine:

f(new Box<>(new Integer(10)));

The type parameter in invoking the constructor in the method call of f() above is inferred from the argument to the constructor (i.e. Integer).

So is this what is meant when the tutorial says

Note that the diamond often works in method calls

If not, can anyone kind enough to provide an example where diamond works in method call?

like image 982
Sa'ad Avatar asked Dec 26 '11 16:12

Sa'ad


People also ask

In which version of Java diamond operator is introduced?

Diamond Operator: Diamond operator was introduced in Java 7 as a new feature. The main purpose of the diamond operator is to simplify the use of generics when creating an object.

What is a diamond operator in Java?

The diamond operator – introduced in Java 1.7 – adds type inference and reduces the verbosity in the assignments – when using generics: List<String> cars = new ArrayList<>(); The Java 1.7 compiler's type inference feature determines the most suitable constructor declaration that matches the invocation.

Which of the following options is the correct name for empty type parameter rectangle square diamond circle?

It's called diamond operator and infers the generic type from the left hand side, if possible.


2 Answers

So is this what is meant when the tutorial says

I think yes though there are a couple of gotchas when it comes to <> operators.

In your case, Box instantiation is a non-issue given that the type can be trivially inferred using the constructor argument. Try changing the constructor to "not" take in an Integer or T and see how the invocation fails.

class BadBox<T> {

    private T t;

    public BadBox(){}    

    public void setT(T t) {
        this.t = t;
    }

    static void f(BadBox<Integer> box){}

    public static void main(final String[] args) {
        f(new BadBox<>());  //fails, should have worked ideally
    }    
}

Similarly, have a look at this class:

class Testi<R> {    
    public void doIt(Set<? extends R> sets) {
    }

    public static void main(final String[] args) {
            // works since type inference is now possible
        new Testi<CharSequence>().doIt(new HashSet<>(Arrays.asList("a")));

            // fails; nothing which can help with type inference
        new Testi<CharSequence>().doIt(new HashSet<>();
    }       
}

Similarly, the problem in your linked question (regarding addAll) can be simply solved by helping out the compiler a bit as follows:

List<String> list = new ArrayList<>();
list.add("A");

// works now! use only if you love diamond operator ;)
list.addAll(new ArrayList<>(Arrays.asList(new String[0])));
// or the old-school way
list.addAll(new ArrayList<String>()));

Diamond operators also seem to break when it comes to implementing anonymous classes as follows:

final String[] strings = { "a", "b", "c" };
Arrays.sort(strings, new Comparator<>() {
    @Override
    public int compare(String o1, String o2) {
        return 0;
    }
});

Fortunately, in this case, the compiler is pretty explicit in mentioning that <> doesn't/won't work with anonymous classes.

like image 116
Sanjay T. Sharma Avatar answered Sep 20 '22 14:09

Sanjay T. Sharma


I don’t think that it is worth thinking about when it works and when not. The compiler will tell you and thus you have to rewrite what’s not working.

There is not a real rationale behind it; it’s more like the developers have put the current limitations of the actual compiler’s implementation at a specific time into the specification and told us: that’s how it has to be.

Java 8 lifts a lot of these limitations without the hell freezing over. E.g.

Arrays.asList("foo", "bar").addAll(new ArrayList<>());

compiles with Java 8 without any error. And, why not?

like image 21
Holger Avatar answered Sep 20 '22 14:09

Holger