Consider the snippet:
Number[] numbers = {1, 2.3, 4.5f, 6000000000000000000L};
It's perfectly okay to do the above, Number
is an abstract class.
Going ahead,
List<Long> listLong = new ArrayList<Long>(); listLong.add(Long.valueOf(10)); List<Number> listNumbers = listLong; // compiler error - LINE 3 listNumbers.add(Double.valueOf(1.23));
Had Line 3 was designed to be compiled successfully, we would end up with a List
of Number
s, i.e,
for(Number num: listNumbers ){ System.out.println(num); } // 10 // 1.23
which are all numbers.
I came across this in a book,
Generics doesn’t support sub-typing because it will cause issues in achieving type safety. That’s why
List<T>
is not considered as a subtype ofList<S>
whereS
is the super-type ofT
Which type safety would have lost in this specific case as discussed above, were the Line 3 was to be compile successfully?
Java Generic methods and generic classes enable programmers to specify, with a single method declaration, a set of related methods, or with a single class declaration, a set of related types, respectively. Generics also provide compile-time type safety that allows programmers to catch invalid types at compile time.
Java For Testers Whenever you want to restrict the type parameter to subtypes of a particular class you can use the bounded type parameter. If you just specify a type (class) as bounded parameter, only sub types of that particular class are accepted by the current generic class.
Box rawBox = new Box(); Therefore, Box is the raw type of the generic type Box<T>. However, a non-generic class or interface type is not a raw type. The warning shows that raw types bypass generic type checks, deferring the catch of unsafe code to runtime.
Generic methods are methods that introduce their own type parameters. This is similar to declaring a generic type, but the type parameter's scope is limited to the method where it is declared. Static and non-static generic methods are allowed, as well as generic class constructors.
List<Long> listLong = new ArrayList<Long>(); List<Number> listNumbers = listLong;
So, listNumbers
and listLong
would be two references to the same list, if that was possible, right?
listNumbers.add(Double.valueOf(1.23));
So, you would be able to add a Double to that list. listLong
, of type List<Long>
, would thus contain a Double. The type-safety would thus be broken.
If that was the case, then we could add other different subtypes of Number
into listNumbers
, which must be forbidden.
Imagine you're now inserting objects of type Double
and Long
, and later you try to use Long#reverse
. Your code will compile but of course will fail at runtime (bad) the first Double
it'll come through.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With