I saw sometimes a type object inside <> beside of another object type declaration.
For instance:
NavigableMap<Double, Integer> colorMap = new TreeMap<Double, Integer>()
or
private final CopyOnWriteArrayList<EventListener> ListenerRecords =
new CopyOnWriteArrayList<EventListener>();
Could you give me an easy explication?
They're known as generics in java, and templates in C++.
http://java.sun.com/developer/technicalArticles/J2SE/generics/
These are called Generics. Here http://java.sun.com/docs/books/tutorial/java/generics/index.html is a tut from sun for them.
As some others said before: Your dealing with Java Generics. They're in Java since SDK 1.5.
E.g:
new CopyOnWriteArrayList<EventListener>()
means that you're creating a new (concurrent) ArrayList which is able to store objects of type EventListener. If you would create an ArrayList the old (pre Java 1.5) way like:
new ArrayList()
All contained objects would be of type Object and you would have to cast them to their real type. See also http://en.wikipedia.org/wiki/Generics_in_Java#Motivation_for_generics.
These are called Generics in Java. They give you a way to tell the compiler what type the collection is going to hold.
http://java.sun.com/j2se/1.5.0/docs/guide/language/generics.html
They're called Generics, and allow the compiler to do type checking of contents of lists etc, and also reduces the amount of casting you have to do in your code.
It's also helpful when reading code, as you know what type of object can be put into the item in question, or what type to expect out of it.
Java's implementation isn't as thorough as C++, as Java's is only available at compile time.
At runtime, the type information is no longer available.
In your example TreeMap the key of the TreeMap has type Double and the value referenced by this key has the type Integer. And as already answered it's called generics.
This is an extension introduced in java 1.5. This makes code more readable
They are Generics, classes that are written with one or more types left to be specified later, so they can be used with any type. The generics can be very useful for containers or algorithms, where the algorithm or the data structure used is independent from the actual type stored or manipulated.
Related
The diamond operator in java 7 allows code like the following:
List<String> list = new LinkedList<>();
However in Java 5/6, I can simply write:
List<String> list = new LinkedList();
My understanding of type erasure is that these are exactly the same. (The generic gets removed at runtime anyway).
Why bother with the diamond at all? What new functionality / type safety does it allow? If it doesn't yield any new functionality why do they mention it as a feature? Is my understanding of this concept flawed?
The issue with
List<String> list = new LinkedList();
is that on the left hand side, you are using the generic type List<String> where on the right side you are using the raw type LinkedList. Raw types in Java effectively only exist for compatibility with pre-generics code and should never be used in new code unless
you absolutely have to.
Now, if Java had generics from the beginning and didn't have types, such as LinkedList, that were originally created before it had generics, it probably could have made it so that the constructor for a generic type automatically infers its type parameters from the left-hand side of the assignment if possible. But it didn't, and it must treat raw types and generic types differently for backwards compatibility. That leaves them needing to make a slightly different, but equally convenient, way of declaring a new instance of a generic object without having to repeat its type parameters... the diamond operator.
As far as your original example of List<String> list = new LinkedList(), the compiler generates a warning for that assignment because it must. Consider this:
List<String> strings = ... // some list that contains some strings
// Totally legal since you used the raw type and lost all type checking!
List<Integer> integers = new LinkedList(strings);
Generics exist to provide compile-time protection against doing the wrong thing. In the above example, using the raw type means you don't get this protection and will get an error at runtime. This is why you should not use raw types.
// Not legal since the right side is actually generic!
List<Integer> integers = new LinkedList<>(strings);
The diamond operator, however, allows the right hand side of the assignment to be defined as a true generic instance with the same type parameters as the left side... without having to type those parameters again. It allows you to keep the safety of generics with almost the same effort as using the raw type.
I think the key thing to understand is that raw types (with no <>) cannot be treated the same as generic types. When you declare a raw type, you get none of the benefits and type checking of generics. You also have to keep in mind that generics are a general purpose part of the Java language... they don't just apply to the no-arg constructors of Collections!
Your understanding is slightly flawed. The diamond operator is a nice feature as you don't have to repeat yourself. It makes sense to define the type once when you declare the type but just doesn't make sense to define it again on the right side. The DRY principle.
Now to explain all the fuzz about defining types. You are right that the type is removed at runtime but once you want to retrieve something out of a List with type definition you get it back as the type you've defined when declaring the list otherwise it would lose all specific features and have only the Object features except when you'd cast the retrieved object to it's original type which can sometimes be very tricky and result in a ClassCastException.
Using List<String> list = new LinkedList() will get you rawtype warnings.
This line causes the [unchecked] warning:
List<String> list = new LinkedList();
So, the question transforms: why [unchecked] warning is not suppressed automatically only for the case when new collection is created?
I think, it would be much more difficult task then adding <> feature.
UPD: I also think that there would be a mess if it were legally to use raw types 'just for a few things'.
In theory, the diamond operator allows you to write more compact (and readable) code by saving repeated type arguments. In practice, it's just two confusing chars more giving you nothing. Why?
No sane programmer uses raw types in new code. So the compiler could simply assume that by writing no type arguments you want it to infer them.
The diamond operator provides no type information, it just says the compiler, "it'll be fine". So by omitting it you can do no harm. At any place where the diamond operator is legal it could be "inferred" by the compiler.
IMHO, having a clear and simple way to mark a source as Java 7 would be more useful than inventing such strange things. In so marked code raw types could be forbidden without losing anything.
Btw., I don't think that it should be done using a compile switch. The Java version of a program file is an attribute of the file, no option at all. Using something as trivial as
package 7 com.example;
could make it clear (you may prefer something more sophisticated including one or more fancy keywords). It would even allow to compile sources written for different Java versions together without any problems. It would allow introducing new keywords (e.g., "module") or dropping some obsolete features (multiple non-public non-nested classes in a single file or whatsoever) without losing any compatibility.
When you write List<String> list = new LinkedList();, compiler produces an "unchecked" warning. You may ignore it, but if you used to ignore these warnings you may also miss a warning that notifies you about a real type safety problem.
So, it's better to write a code that doesn't generate extra warnings, and diamond operator allows you to do it in convenient way without unnecessary repetition.
All said in the other responses are valid but the use cases are not completely valid IMHO. If one checks out Guava and especially the collections related stuff, the same has been done with static methods. E.g. Lists.newArrayList() which allows you to write
List<String> names = Lists.newArrayList();
or with static import
import static com.google.common.collect.Lists.*;
...
List<String> names = newArrayList();
List<String> names = newArrayList("one", "two", "three");
Guava has other very powerful features like this and I actually can't think of much uses for the <>.
It would have been more useful if they went for making the diamond operator behavior the default, that is, the type is inferenced from the left side of the expression or if the type of the left side was inferenced from the right side. The latter is what happens in Scala.
The point for diamond operator is simply to reduce typing of code when declaring generic types. It doesn't have any effect on runtime whatsoever.
The only difference if you specify in Java 5 and 6,
List<String> list = new ArrayList();
is that you have to specify #SuppressWarnings("unchecked") to the list (otherwise you will get an unchecked cast warning). My understanding is that diamond operator is trying to make development easier. It's got nothing to do on runtime execution of generics at all.
The diamond operator in java 7 allows code like the following:
List<String> list = new LinkedList<>();
However in Java 5/6, I can simply write:
List<String> list = new LinkedList();
My understanding of type erasure is that these are exactly the same. (The generic gets removed at runtime anyway).
Why bother with the diamond at all? What new functionality / type safety does it allow? If it doesn't yield any new functionality why do they mention it as a feature? Is my understanding of this concept flawed?
The issue with
List<String> list = new LinkedList();
is that on the left hand side, you are using the generic type List<String> where on the right side you are using the raw type LinkedList. Raw types in Java effectively only exist for compatibility with pre-generics code and should never be used in new code unless
you absolutely have to.
Now, if Java had generics from the beginning and didn't have types, such as LinkedList, that were originally created before it had generics, it probably could have made it so that the constructor for a generic type automatically infers its type parameters from the left-hand side of the assignment if possible. But it didn't, and it must treat raw types and generic types differently for backwards compatibility. That leaves them needing to make a slightly different, but equally convenient, way of declaring a new instance of a generic object without having to repeat its type parameters... the diamond operator.
As far as your original example of List<String> list = new LinkedList(), the compiler generates a warning for that assignment because it must. Consider this:
List<String> strings = ... // some list that contains some strings
// Totally legal since you used the raw type and lost all type checking!
List<Integer> integers = new LinkedList(strings);
Generics exist to provide compile-time protection against doing the wrong thing. In the above example, using the raw type means you don't get this protection and will get an error at runtime. This is why you should not use raw types.
// Not legal since the right side is actually generic!
List<Integer> integers = new LinkedList<>(strings);
The diamond operator, however, allows the right hand side of the assignment to be defined as a true generic instance with the same type parameters as the left side... without having to type those parameters again. It allows you to keep the safety of generics with almost the same effort as using the raw type.
I think the key thing to understand is that raw types (with no <>) cannot be treated the same as generic types. When you declare a raw type, you get none of the benefits and type checking of generics. You also have to keep in mind that generics are a general purpose part of the Java language... they don't just apply to the no-arg constructors of Collections!
Your understanding is slightly flawed. The diamond operator is a nice feature as you don't have to repeat yourself. It makes sense to define the type once when you declare the type but just doesn't make sense to define it again on the right side. The DRY principle.
Now to explain all the fuzz about defining types. You are right that the type is removed at runtime but once you want to retrieve something out of a List with type definition you get it back as the type you've defined when declaring the list otherwise it would lose all specific features and have only the Object features except when you'd cast the retrieved object to it's original type which can sometimes be very tricky and result in a ClassCastException.
Using List<String> list = new LinkedList() will get you rawtype warnings.
This line causes the [unchecked] warning:
List<String> list = new LinkedList();
So, the question transforms: why [unchecked] warning is not suppressed automatically only for the case when new collection is created?
I think, it would be much more difficult task then adding <> feature.
UPD: I also think that there would be a mess if it were legally to use raw types 'just for a few things'.
In theory, the diamond operator allows you to write more compact (and readable) code by saving repeated type arguments. In practice, it's just two confusing chars more giving you nothing. Why?
No sane programmer uses raw types in new code. So the compiler could simply assume that by writing no type arguments you want it to infer them.
The diamond operator provides no type information, it just says the compiler, "it'll be fine". So by omitting it you can do no harm. At any place where the diamond operator is legal it could be "inferred" by the compiler.
IMHO, having a clear and simple way to mark a source as Java 7 would be more useful than inventing such strange things. In so marked code raw types could be forbidden without losing anything.
Btw., I don't think that it should be done using a compile switch. The Java version of a program file is an attribute of the file, no option at all. Using something as trivial as
package 7 com.example;
could make it clear (you may prefer something more sophisticated including one or more fancy keywords). It would even allow to compile sources written for different Java versions together without any problems. It would allow introducing new keywords (e.g., "module") or dropping some obsolete features (multiple non-public non-nested classes in a single file or whatsoever) without losing any compatibility.
When you write List<String> list = new LinkedList();, compiler produces an "unchecked" warning. You may ignore it, but if you used to ignore these warnings you may also miss a warning that notifies you about a real type safety problem.
So, it's better to write a code that doesn't generate extra warnings, and diamond operator allows you to do it in convenient way without unnecessary repetition.
All said in the other responses are valid but the use cases are not completely valid IMHO. If one checks out Guava and especially the collections related stuff, the same has been done with static methods. E.g. Lists.newArrayList() which allows you to write
List<String> names = Lists.newArrayList();
or with static import
import static com.google.common.collect.Lists.*;
...
List<String> names = newArrayList();
List<String> names = newArrayList("one", "two", "three");
Guava has other very powerful features like this and I actually can't think of much uses for the <>.
It would have been more useful if they went for making the diamond operator behavior the default, that is, the type is inferenced from the left side of the expression or if the type of the left side was inferenced from the right side. The latter is what happens in Scala.
The point for diamond operator is simply to reduce typing of code when declaring generic types. It doesn't have any effect on runtime whatsoever.
The only difference if you specify in Java 5 and 6,
List<String> list = new ArrayList();
is that you have to specify #SuppressWarnings("unchecked") to the list (otherwise you will get an unchecked cast warning). My understanding is that diamond operator is trying to make development easier. It's got nothing to do on runtime execution of generics at all.
I was going through lectures of Algorithms on Coursera by Robert Sedgewick.I was a bit confused when Mr.Robert pointed out that one cannot use Generics with Arrays as it is not allowed.
But ArrayList in Collection Framework uses Arrays internally and Generic datatypes are allowed.I mean to say that we can do the following:
ArrayList<Integer> list = new ArrayList<Integer>();
One hack he pointed out was this:
public class FixedCapacityStack<Item>{
private Item[] s;
private int N = 0;
public FixedCapacityStack(int capacity)
{ s = (Item[]) new Object[capacity];} //this hack
He also mentioned that this is an ugly hack and must be avoided and it also produces warning during compilation.
My Question is:
1.) How does ArrayList then internally represent various Generics Types?
2.) If (assumed) they use the hack mentioned above why it doesn't produce a warning when we compile a program with ArrayList?
3.) Is there any better way apart from that cast above?
Per the source:
1 - ArrayList stores items in an Object[], and casts the value when retrieving individual elements. There's actually an #SuppressWarnings("unchecked") where the cast happens.
2 - Two answers here - the first is that you're not (typically) compiling ArrayList, but just including it on your classpath from rt.jar in the JRE/JDK. The second is that ArrayList uses a #SuppressWarnings on its unchecked conversion from Object to the generic type.
3 - Your other alternative ("better" is quite subjective) would be to require the Class for your generic type, and use Array.newInstance(Class clazz, int capacity) to create your array, as described in this question
1.) How does ArrayList then internally represent various Generics Types?
What do you mean "internally"? Generics only exist at compile time. ArrayList has already been compiled by someone else for you and you are just using the class file. So there is no generics there.
Different Java library implementations could write the source differently, but that is of no concern to you. What it does "internally" is an internal implementation detail that a user of the class should not care about.
If you were to write your own class like FixedCapacityStack, then you could do it in different ways:
You could do the thing where s is of type Item[] as you have shown above, and you create an Object[] and cast to Item[]
Or you can make s of type Object[] and cast to type Item when you get elements out of it
Note that both approaches are the same after erasure, so both will compile to the exact same bytecode. The difference is just style at compile-time.
The advantage of the first approach over the second is that when you get elements out of it, it's already the right type, so you don't have all these ugly casts everywhere. The disadvantage of the first approach is that the initial cast from Object[] to Item[] is basically a "lie", and it will only work if you make absolutely sure not to expose s to the outside of the class (e.g. do not have a method that returns s as type Item[]); otherwise you will have class cast exceptions in unexpected places.
2.) If (assumed) they use the hack mentioned above why it doesn't produce a warning when we compile a program with ArrayList?
There would only be a warning when you actually compile this class. But not if it was already compiled and you are just using the class file. In fact, you don't usually even have the source of ArrayList.
3.) Is there any better way apart from that cast above?
Depends on what you mean by "better". I have shown the two approaches and the advantages and disadvantages of each.
I want to create an array of ArrayLists, similar to that in this thread: How to do an array of hashmaps?. However, Java gives the warning
"Cannot create a generic array of ArrayList<String>"
when I try to do the following
ArrayList[] arrayOfLists = new ArrayList[size];
I have sort of understood the problems and the workarounds provided.
I have my own approach which unfortunately does not fix the problem either.
I tried creating a list of ArrayLists and then used toArray().
ArrayList<ArrayList<String>> listOfLists = new ArrayList<ArrayList<String>>();
ArrayList<String>[] arrayOfLists = (ArrayList<String>[])listOfLists.toArray();
Worked fine, but got the warning :
Type safety: Unchecked cast from Object[] to ArrayList<String>[]
When I tried to check for type safety, using
if(listOfLists.toArray() instanceof ArrayList<String>[])
I get the error:
Cannot perform instanceof check against parameterized type ArrayList<String>[]. Use the form ArrayList<?>[] instead since further generic type information will be erased at runtime
Why cant I use this method? Why does toArray() return Object[] instead of ArrayList<String> since the instance was initialised with theArrayList<String>; type?
Any other workarounds/suggestions on how I can get this done? A 2D array will not work since different lists can vary greatly in size.
The currently accepted answer has a major error in describing Java's generics, so I felt I should answer to make sure there aren't any misconceptions.
Generics in Java are an entirely compile-time feature and for the most part don't exist at runtime due to erasure (you can get the runtime to cough up generic type information in some cases, but that's far from the general case). This provides the basis for the answers to your questions.
Why cant I use this method?
Because generics are erased, an ArrayList<String>[] (as well as all other parameterized ArrayList<>[] instances) at runtime is really an ArrayList[]. Thus, it is impossible for the runtime to check if something is instanceof ArrayList<String>[], as the runtime doesn't actually know that String is your type parameter -- it just sees ArrayList[].
Why does toArray() return Object[] instead of ArrayList since the instance was initialised with theArrayList; type?
Again, erasure. The type parameter is erased to Object, so at runtime what you effectively have is an ArrayList<Object>. Because of this erasure, the runtime doesn't have the information necessary to return an array of the proper type; it only knows that the ArrayList holds Objects, so it returns an Object[]. This is why the toArray(T[]) overload exists -- arrays retain their type information, so an array could be used to provide the requisite type information to return an array of the right type.
Any other workarounds/suggestions on how I can get this done?
As you can see, mixing generic stuff and arrays doesn't work too well, so ideally, you wouldn't mix Lists and arrays together. Therefore, if possible, you should use List<List<String>> or something of the sort instead of List<String>[]. If you want to keep a ArrayList<String>[], though, you could do this:
#SuppressWarnings("unchecked")
ArrayList<String>[] array = new ArrayList[size];
You'll still get the unchecked type warning, but you can be reasonably sure that you won't encounter heap pollution as the only reference to the object is through array. You can also use this as the parameter to toArray():
#SuppressWarnings("unchecked")
ArrayList<String>[] temp = new ArrayList[0];
ArrayList<String>[] arrayOfLists = listOfLists.toArray(temp);
or
#SuppressWarnings("unchecked")
ArrayList<String>[] arrayOfLists = listOfLists.toArray((ArrayList<String>[]) new ArrayList[0]);
For more reading on why you can't parameterize an array, see this SO question. In short, such a thing isn't safe because arrays are covariant, while generics are invariant.
The problem is that Generics are created during runtime, but type conversions and array sizes must be checkable at compile time. The compiler cannot tell what class ArrayList<String> will be during compile time (as it will be generated later), it can only tell that it will be at least an Object, because every class in Java is at least an Object. You can do type conversion and suppress the warning and it might even work, but you run into a pitfall to accidentally confuse types somewhere and mess up your code.
Java is a type-safe language by choice to prevent you from doing one of the most recurring mistakes programmers do in their daily work: confusing variable types. So while it is possible to do the type conversion, you - as an upcoming good Java programmer - should not do that. Use the ArrayList<ArrayList<String>> if you need such a construct, and use arrays only when they are necessary.
The main reason to use arrays is speed of execution, as obviously using an object will keep the runtime busy with some overhead. The main reason to not use arrays is the fact that this overhead will allow you more flexibility in coding and reduce the amount of errors you make. So as a general advice: unless you know (as in measured and determined to be a bottleneck) that you need the speed, go with Lists. Java even does some internal optimizations beyond what you would expect to speed up Lists to a point where they come very close to the execution speed of arrays.
I just stumbled upon the compiler treating these two terms differently. when I type:
LinkedList<String> list = new LinkedList();
I get a compiler warning about a raw type. however:
LinkedList<String> list = new LinkedList<>();
removes the warning. It seems to me as though the two statements mean essentially the same thing (i.e. create a new LinkedList with no specified object type). Why then does the complier all ow the empty generics? What is the difference here?
The statements do not mean the same thing at all.
The first statement tries to fit an untyped LinkedList into a declared generic LinkedList<String> and appropriately throws a warning.
The second statement, valid in Java 1.7 onward, uses type inference to guess the type parameter by using the declaring type's type parameter. In addition, sometimes this can be used in method calls. It doesn't always work, however.
See this page for more info.
It's the diamond operator in Java 7, that helps you save writing the type again. In Java 7 this is equivalent to the same generic type argument that is used on the left side of the declaration. So the initialization is type safe and no warning is issued.
With LinkedList<>, you use the new Diamond Operator, from java 7.
The Diamod operator uses the generic value setted in the left side of the line.
In Java 6, this doesnt works!
The diamond operator, however, allows the right hand side of the
assignment to be defined as a true generic instance with the same type
parameters as the left side... without having to type those parameters
again. It allows you to keep the safety of generics with almost the
same effort as using the raw type.
I think the key thing to understand is that raw types (with no <>)
cannot be treated the same as generic types. When you declare a raw
type, you get none of the benefits and type checking of generics. You
also have to keep in mind that generics are a general purpose part of
the Java language... they don't just apply to the no-arg constructors
of Collections!
Extracted from: https://stackoverflow.com/a/10093701/1281306
Backword compatibility (Inter-operating with legacy code) is the reason why java allows above signature. Generics are compile time syntax only. At runtime "all generic" syntax will be removed. You will just see if you de-compile any class file. Read this documentation.
LinkedList list = new LinkedList();