ArrayList ali = new ArrayList() and ArrayList ali = new ArrayList() This will generate a compiler warning re: unchecked conversion. You will only get the compile safety of Generics if you do not ignore these warnings, or Supress them with the annotation because you can prove it's safe You do a raise an interesting point with: ArrayList ali = new ArrayList() As you will only be using ali you do have safety with the reference. However you'll have the Compiler warning for the right hand side of the expression, so it's best to add the parameterized type and keep the compiler free of warnings.
The reason the compiler is warning you is because someone could come and do this: ArrayList strings = new ArrayList(); ArrayList integers = new ArrayList(strings) Oh no you've now got Strings in your Integers! This is where Java 7's type inference comes in i. E ArrayList ali = new ArrayList() So there will no longer be a need for the parameterized type to be specified, as Integer is inferred.
You can do this in Java 5 or 6 by writing a generic method such as makeArrayList() which infers the type (see Joshua Bloch Effective Java book).
ArrayList ali = new ArrayList(); and ArrayList ali = new ArrayList(); This will generate a compiler warning re: unchecked conversion. You will only get the compile safety of Generics if you do not ignore these warnings, or Supress them with the annotation because you can prove it's safe. You do a raise an interesting point with: ArrayList ali = new ArrayList(); As you will only be using ali you do have safety with the reference.
However you'll have the Compiler warning for the right hand side of the expression, so it's best to add the parameterized type and keep the compiler free of warnings. The reason the compiler is warning you is because someone could come and do this: ArrayList strings = new ArrayList(); ArrayList integers = new ArrayList(strings); Oh no you've now got Strings in your Integers! This is where Java 7's type inference comes in i.e.
ArrayList ali = new ArrayList(); So there will no longer be a need for the parameterized type to be specified, as Integer is inferred. You can do this in Java 5 or 6 by writing a generic method such as makeArrayList() which infers the type (see Joshua Bloch Effective Java book).
Yes I noticed that. But will that cause real-time troubles for the proejct? – Ziyao Wei Jun 8 at 14:01 @Ziyao compile time safety is a good thing.So yes by having unchecked conversions you run the risk of your code failing with RunTimeExceptions.
– planetjones Jun 8 at 14:03 I believe that Eclipse warned me for a reason, but I just cannot think of one. Could you give me an example? – Ziyao Wei Jun 8 at 14:04 Well this won't be an error: ArrayList ali = new ArrayList(); ali.
Add("Bob"); But if you had added the parameterized type properly i.e. ArrayList ali = new ArrayList(); it would be a compile time error, which you would need to fix. – planetjones Jun 8 at 14:06.
You are right in your assessment that your last code snippet is not actually dangerous (though it does generate the compiler warning). The reason why using raw types is potentially dangerous, is because you lose the type-safety that generics provides. More specifically, you lose the guarantee that you can't treat the " generic parameter as two different types in two different scenarios.(This is what the problem is in your casting-to-String example - the list is considered to contain integers at one point (when being populated) but considered to contain Strings at another point).
In the last example you've provided, the warning is technically spurious since the raw-typed list that's being constructed can only be referenced by the ali reference, which is correctly typed. Therefore, it would be impossible to insert strings into it. However, the compiler can't guarantee this in general, as it's an implementation detail of how the ArrayList constructor works that makes this safe.(Another list implementation could "publish" a reference to itself externally, which could then be used to insert the wrong type of elements into this list).
The compiler just sees that you're assigning something that's of the raw type ArrayList to a variable of type ArrayList, and correctly says that "the thing on the right hand side might have been used for things other than Integers in the past, you know - are you sure this is OK? " It's roughly equivalent to ArrayList al = new ArrayList(); ArrayList ali = al; where in this slightly expanded case, the "temporary" variable al allows one to call al. Add("not an int") without compile time errors.
There's no real benefit to doing things this way and "knowing" it's correct, you may as well construct the list with the right generic parameters from the get-go, as in your first example. Unchecked conversion warnings are often not a real problem, but quite often can be - suppressing the warnings runs the risk that you'll migrate from the first situation to the second without noticing. Getting the compiler to check for you means it can tell you if your underlying assumptions become invalidated.
The compiler only checks if a variable that declares a generic type is used correct. If the variables type is a raw type, then it won't complain (with an error). So the following lines compile and run with no error: ArrayList list = new ArrayList(); list.
Add("hello"); String s = (String) list. Get(0); Note, that the compiler doesn't care that we used the generic constructor and that the runtime won't notice because of type erasure. Once the variable has a generic type, then the compiler can check, if you use the variable "correctly" (like for collection: the compiler knows that get(0) will return the generic type and can complain on illgal casts) The last example is safe (in this case).
It is critical, if the constructor uses some typed parameters. The following lines show the problem: ArrayList doubles = new ArrayList(); ArrayList integers1 = new ArrayList(doubles); // error ArrayList integers2 = new ArrayList(doubles); // no error With the third line we can legally populate a Integer typed array with Double values, we just have to ignore the warning (and catch all runtime exceptions later ;) ) OT and Trivia With Java 7 we get the diamond operator: ArrayList multilist = new ArrayList(); // Java 1.5+ ArrayList multilist = new ArrayList(); // Java 7.
Thanks for the reply! What about the last situation? Will that cause trouble too?
– Ziyao Wei Jun 8 at 14:06 @Ziyao Wei - added an example to show why you should always create generic classes with type parameters – Andreas_D Jun 8 at 14:20.
The problem is that ArrayList ali = new ArrayList(); is an untyped Collection. The compiler warns your about it with this warning message: ArrayList is a raw type. References to generic type ArrayList should be parameterized However, since you have not typed it, the compiler can not know what types are in variable ali.At runtime, however the type is erased - you in effect have ArrayList.
When you retrieve an element (an Integer) and try to assign it to a String, it explodes, of course with a ClassCastException.
Thanks for the reply, however, my major concern was about the second scenario, which could produce a compile error, thus prevent the program from crashing in runtime. – Ziyao Wei Jun 8 at 14:03.
If you don't care about code clarity, you could do it - but I don't see why you'd want to. There seems to be absolutely no gain (aside from saving a few characters worth of typing) in doing so, and it just makes your code slightly harder to read if you're not declaring and initialising on the same line.
By themselves, neither of these will produce runtime errors: ArrayList ali = new ArrayList(); or ArrayList ali = new ArrayList(); However, that's only because you've not tried to populate the list. If you do, and you make a mistake, you can get unexpected ClassCastExceptions when using values extracted from the list. For example: ArrayList ali = new ArrayList(); ali.
Add(" ArrayList oop = ali; // unsafe conversion Integer first = oop. Get(0); The last line won't give a compilation error or warning, but at runtime it will give a ClassCastException. The CCE is thrown because the compiler does an implicit type cast as part of the assignment.
If you do not specify ali as an ArrayList(Integer) but just as a general ArrayList, the compiler has no idea of knowing what's inside it! It will just treat everything as a general Object. However, at the moment you try to cast it to a string (which you're doing wrong anyhow, doing (String) is always bad) it will fail, because only at that time it will look what kind of object the 'Object' actually is.It's like doing: Object o = new String(""); int I = (String)o; The compiler will accept this; at runtime the cast will fail!
As a sidenote, this casting process also makes a general ArrayList much slower than a arraylist that has it's contenttype defined. Not to mention that it's much better programming to define what's in an ArrayList.
– Ziyao Wei Jun 8 at 13:59 @Ziyao If you don't specify the type in the right hand side, you are basically trying to instantiate an ArrayList – Marcelo Jun 8 at 14:01 The casting process does not slow anything down - Generics are erased, so the Casting still has to be done - just you as a code author do not do it. – planetjones Jun 8 at 14:01 @Ziyao Wei Nope. See the example I've just added.
The compiler just checks the general filetype, as in some cases (like extended classes and such) such a conversion will go fine. – Vincent Koeman Jun 8 at 14:01 1 @Vincent re: casting - o.toString() is definitely not the same as casting. Casting is an assertion of a sort - this is a String, let me treat it as one.
Getting a runtime exception if it's of a different class is the correct behaviour - you don't just want an arbitrary string representation of a different object instead. Also, this fails with null where casting would correctly return a null String. Basically, if you want to cast to a String, casting is the only (and thus best) way to do it.
If you want to convert to a String, casting isn't even an option. – Andrzej Doyle Jun 8 at 14:23.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.