Use Advanced Search to search the entire archive.
Re: Email proposal to the core-libs-dev@openjdk.java.net
- From: Martin Desruisseaux <
>
- To:
- Subject: Re: Email proposal to the
- Date: Tue, 21 Oct 2014 21:34:35 +0900
- Organization: Geomatys
Hello Otávio
Le 21/10/14 19:12, Otávio Gonçalves de Santana a écrit :
>
Martin, in your example can happen ClassCastException, in our case
>
not, because we are using the same interface.
In my example a ClassCastException can happen here:
Integer r = (Integer) multiply(x, y);
An no ClassCastException can happen here (potentially wrongly):
Comparable<Integer> r = (Comparable<Integer>) multiply(x, y); // Unsafe
cast
In your example a ClassCastException can happen here (choose the
alternative you prefer):
Length r = (Length) speed.multiply(time);
Length r = speed.multiply(time).cast(Length.class);
An no ClassCastException can happen here (potentially wrongly):
Quantity<Length> r = (Quantity<Length>) speed.multiply(time); // Unsafe
cast
Where do you see a behavioural difference? And what do you mean by
"because we are using the same interface"? In my example too all classes
extends Comparable, and all arguments and return value are Comparable.
>
I did a brief of the code below, I am just using Generics with diamond
>
resources, available in Java 7 or above. Can you show me how may
>
happen the same thing with this code or the cast could be unsafe?
Yes. Here:
>
public class BigDecimalQuanity<Q extends Quantity<Q>> implements
>
Quantity<Q> {
>
public <T extends Quantity<T>, E extends Quantity<E>> Quantity<E>
>
multiply(Quantity<T> that) {
>
return new BigDecimalQuanity<>();
>
}
>
}
The compiler accepts this code because you are not assigning any unit to
BigDecimalQuantity. If you try to assign a Unit<E> to that
BigDecimalQuantity, you are faced to the following problems:
* The parameterized type of Quantity unit is the same as the
parameterized type of the quantity.
* Consequently, the parameterized type of the unit of the
BigDecimalQuantity you are constructing must be <E>.
* The parameterized type of the Unit computed by that multiply
function is <?> (attempts to "fix" Unit.multiply(Unit) will just
lead to a similar bullet list than this one).
* That multiply method has absolutely no way to know that the Unit<?>
can be safely casted to Unit<E>. The only way to verify that in
current Java would be to have a Class<E> argument.
* Consequently multiply can not proceed, end of the story.
Even if we could check the type inside the multiply method, this is not
the way parameterized types are supposed to work. Except for a few
special-purpose methods like Class.asSubclass(Class) or
Unit.asType(Class), The purpose of parameterized type is to guarantee
that no ClassCastException will be thrown if the error compiled without
errors and without "unsafe cast warnings".
I challenge you to write a complete multiply implementation with your
method signature without "unsafe cast" warning that you can not prove to
be safe. If you succeed, I retire everything I told in this whole
threat, would own you all my apologize, send flowers, ton of chocolate,
wash your car, etc.
The fact that a method is impossible to implement without unprovable
"unsafe cast" warnings is a much, much more serious sign of critical
design flaw than the presence of <?> in a return value.
Martin