Hi,
my post is a feedback to the explanation why we need the <> syntax. I do
not express any doubts whether the diamond operator should be in JDK 7 or
not and nor I have them.
And this kind of feedback is not late, I suppose.
Z.
--
Zdenek Tronicek
FIT CTU in Prague
Joe Darcy napsal(a):
> Greetings.
>> This vein of feedback is at least 18 months late:
>http://mail.openjdk.java.net/pipermail/coin-dev/2009-August/002173.html>> I am not going to engage in a debate over whether or not diamond should
> be in JDK 7.
>> -Joe
>> Zdeněk Troníček wrote:
>> My answer is here (I also post it on my blog at
>>http://tronicek.blogspot.com/2011/03/do-we-really-need-in-diamond-operator.html):
>>>> As you may know, one of new features of upcoming Java 7 will be the
>> diamond operator. Purpose of the diamond operator is to simplify
>> instantiation of generic classes. For example, instead of
>> List<Integer> p = new ArrayList<Integer>();
>>>> with the diamond operator we can write only
>> List<Integer> p = new ArrayList<>();
>>>> and let compiler infer the value of type argument. Nice simplification.
>> But do we really need to write <>? Isn't new ArrayList() enough? In this
>> article, I will describe the arguments of the <> proponents and explain
>> why I think that these arguments are not very strong. However, I also
>> describe arguments why we need <>.
>>>> In Java 1.4, we had raw types only:
>> List p = new ArrayList();
>>>> Java 5 introduced generics:
>> List<Integer> p = new ArrayList<Integer>();
>>>> Many types in Java API were generified and even though we can still use
>> generic types as raw types, there is no reason for this in Java 5 or
>> newer. When generics were introduced, raw types were allowed for
>> backward
>> compatibility so that we could gradually and smoothly adopt generics.
>> For
>> example, code in Java 1.4 can be combined with new generic code because
>> raw and generic types are allowed together. This is also expressed in
>> the
>> JLS (4.8 Raw Types):
>>>> "The use of raw types is allowed only as a concession to compatibility
>> of
>> legacy code. The use of raw types in code written after the introduction
>> of genericity into the Java programming language is strongly
>> discouraged.
>> It is possible that future versions of the Java programming language
>> will
>> disallow the use of raw types."
>>>> Now let's go back to the diamond operator and ask again: "Do we really
>> need <>?". The proponents of the <> syntax say that we need <> to
>> preserve
>> backward compatibility. Let's look at an example from the coin-dev
>> conference:
>>>> class Foo<X> {
>> Foo(X x) { }
>> Foo<X> get(X x) { return this; }
>> }
>>>> class Test {
>> void test() {
>> Foo<?> f1 = new Foo(1).get(""); //ok - can pass String where
>> Object
>> is expected
>> Foo<?> f2 = new Foo<>(1).get(""); //fail - cannot pass String
>> where
>> Integer is expected
>> }
>> }
>>>> This shows the difference between new Foo(1) and new Foo<>(1). Clearly,
>> these two are different and if we changed the semantics of new Foo(1),
>> it
>> would break backward compatibility. But wait. Backward compatibility
>> with
>> what? Isn't line
>> Foo<?> f1 = new Foo(1).get("");
>>>> a little suspicious? It uses generic type in the left part and raw type
>> in
>> the right part. Although it is legal, it is probably either omission or
>> malpractice. And its legality is probably only a side effect of "a
>> concession to compatibility of legacy code".
>>>> Let's go further and look at another example from the coin-dev
>> conference.
>> It shows the difference between raw type and parameterized type with the
>> diamond:
>>>> public class X<T> {
>> public X(T t) { }
>> public T get() { return null; }
>>>> public static int f(String s) { return 1; }
>> public static int f(Object o) { return 2; }
>>>> public static void main(String[] args) {
>> System.out.println(f(new X<>("").get()));
>> System.out.println(f(new X("").get()));
>> }
>> }
>>>> Let's play with the code a bit. Let's assume that there was a library
>> with
>> the X class:
>>>> public class X {
>> public X(Object o) { }
>> public Object get() { return null; }
>> }
>>>> and some code that compiled against this library:
>>>> public class Client {
>> static int f(String s) { return 1; }
>> static int f(Object o) { return 2; }
>>>> public static void main(String[] args) {
>> System.out.println(f(new X("").get()));
>> }
>> }
>>>> Then, the library was generified:
>>>> public class X<T> {
>> public X(T t) { }
>> public T get() { return null; }
>> }
>>>> and we compiled the client project against the generified version. Now,
>> if
>> we changed the semantics of new X("") to new X<String>("") (or new
>> X<>("")
>> with the diamond syntax), the code would behave differently. So, the
>> answer to the title question is 'yes'. If we want to stay backward
>> compatible, we need <> and we cannot put new X("") semantically equal to
>> new X<>("").
>>>> Another questions are how long can Java evolve and remain compatible
>> with
>> concessions to compatibility and whether newcomers to Java will
>> appreciate
>> this.
>>>> Z.
>>>>