Can anyone explain why the following piece of code compiles?
List<Long> longNums = new ArrayList(Arrays.asList("one", "two", "three"));
Is it due to type erasure?
If I have the following method:
public <T> T readProperty(String propName, Class<T> type);
How can I make sure that it will return, say a List<Long>
and not a List<String>
? Obviously, at the type of calling the method I can only supply List.class
and pray.
//run and pray
List<Long> longNums = readProperty("prop", List.class);
It has already happened to me that such a method incorrectly assigned a list of String objects to a list of long number, and it wasn't until I ran it, that I saw the ClassCastException
.
In cases where a transaction fails, the API Gateway can use a Generic Error to convey error information to the client based on the message type (for example, SOAP or JSON). By default, the API Gateway returns a very basic error to the client when a message filter fails.
Generics could be used to develop a better solution using a container that can have a type assigned at instantiation, otherwise referred to as a generic type, allowing the creation of an object that can be used to store objects of the assigned type.
Using Java Generic concept, we might write a generic method for sorting an array of objects, then invoke the generic method with Integer arrays, Double arrays, String arrays and so on, to sort the array elements. Polymorphism is the ability of an object to take on many forms.
You shouldn't expect the program to behave correctly, because you don't use Generics correctly.
First, you should not mix Generics with Raws, which means that this statement
List<Long> longNums = new ArrayList(Arrays.asList("one", "two", "three"));
is invalid (in terms of correctness). If it were:
List<Long> longNums = new ArrayList<Long>(Arrays.asList("one", "two", "three"));
it wouldn't even compile and you would get the error at compile-time (not at Runtime, which may be more confusing and scary).
So, in order to get compiled, your list should be defined as:
List<String> longNums = new ArrayList<>(Arrays.asList("one", "two", "three"));
Further, with regards to this statement
//run and pray
List<Long> longNums = readProperty("prop", List.class);
there actually no way to make sure that readProperty
will return List<Long>
, so you will have to either do a cast or add a @SuppressWarnings
annotation. The reason for this is the type-erasure feature of the compiler - the parameterized type Long
get erased and it's gone at Runtime (when actually the readProperty()
is executed and the value of prob
is obtained via Reflection).
These are two separate questions really.
List<Long> longNums = new ArrayList(Arrays.asList("one", "two", "three"));
For source compatibility reasons a raw type is allowed in these cases. You shouldn't rely on this because as you can see, it defeats the whole idea of generics.
As for the second question, you can sidestep the issue by doing something like this:
public <T> List<T> readListProperty(String propName, Class<T> type);
...
List<Long> longNums = readProperty("prop", Long.class);
It's more of a workaround than a solution and isn't always applicable. (For example when you need even more complex return types, like Map<String,List<String>>
)
You missed diamond <>
(this will not compile):
List<Long> longNums = new ArrayList<>(Arrays.asList("one", "two","three"));
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