Less reading and more reasoning!
Both compile but only one give a warning, but which one and why? View the compile warning as it's way of saying-"hey this is legal but that doesn't mean it's safe- don't be surprised if it blows up at runtime!!".
So lets look at the first example. list1 can only take a
String object, which means that list2 will only contain String which is perfectly fine. When you get() an item out of the list it will return an object which you have to then cast to String for you to assign it to a String reference. No problems there.
Now the 2nd example. Here you have a list1 that can contain
anything, including String. Now this list is assigned to another list that
should only contain Strings so the compiler flags a warning to say what you are doing might not be safe. Why- because this now gets past the compiler even though list2 might not contain a String.
String str = list2.get(0);
This code also compiles, but with a warning, and runs fine. Adding anything to an untyped collection will cause a warning and the above example shows why. list1, the typesafe String list, list1, now contains an Integer! Just to be clear adding a String would also have given a warning.