Java unchecked conversion of arraylist - java

Can anybody tell me how to create an array-arraylist the right way ?!
.\File.java:5: warning: [unchecked] unchecked conversion
ArrayList<myObjectType> myParkingLotArray[] = new ArrayList[3];
^
required: ArrayList<Vehicle>[]
found: ArrayList[]
1 warning
I want an arry (or any other solution) which stores 3 arraylists. How to add objects to the arrylists would be nice to know too.
ParentArray
ChildArrayList1
ChildArrayList2
ChildArrayList3
Im happy for any Help
SOLUTION:
public class myClass {
ArrayList<myObjectType>[] myArryName= new ArrayList[3];
public void addLists() {
myArryName[0] = new ArrayList<myObjectType>();
myArryName[1] = new ArrayList<myObjectType>();
myArryName[2] = new ArrayList<myObjectType>();
}
}
The warning can be ignored or suppressed.

You can not create an Array of classes that use generic types - see here!
And there is no way to work around that error message. The compiler tells you: this ain't possible!
Instead - simply stay with one concept. There is no point of mixing arrays and Lists anyway. Just go for
List<List<Vehicle>> parents = new ArrayList<>();
And then
List<Vehicle> someChild = new ArrayList<>();
To finally do something like
parents.add(someChild);

You can do this with a cast
ArrayList<myObjectType>[] myParkingLotArray = (ArrayList<myObjectType>[]) new ArrayList[3];
However, I agree with GhostCat you should try to use arrays or lists but not mix them. a List<List<myObjectype>> would be better.

You cannot create arrays of parameterized types.
What you can do insteade is the following:
List [] arrayOfLists = new ArrayList[10];
arrayOfLists[0] = new ArrayList<Vehicle>();
but you can't be sure that all the lists will be List of the same type.
Otherwise you can use simply List of Lists in this way:
List<List<Vehicle>> listOfLists = new ArrayList<>();
List<Vehicle> list = new ArrayList<>();
listOfLists.add(list);

Related

Type inference in Java 7, When and why should it be used?

#Test
public void TypeInferenceTest() {
inference();
uncheckedAssignment();
explicit();
}
private void inference() {
ArrayList<String> strings = new ArrayList<>();
strings.add("abc");
String s = strings.get(0);
assertThat(s, is("abc"));
}
private void uncheckedAssignment() {
ArrayList<String> strings = new ArrayList();
strings.add("abc");
String s = strings.get(0);
assertThat(s, is("abc"));
}
private void explicit() {
ArrayList<String> strings = new ArrayList<String>();
strings.add("abc");
String s = strings.get(0);
assertThat(s, is("abc"));
}
The code above used three ways to instantiate a list: type inference, open generic type and closed generic type.
But if I decompile the generated bytecode using JD-GUI, this is the result:
#Test
public void TypeInferenceTest() {
inference();
uncheckedAssignment();
explicit();
}
private void inference() {
ArrayList strings = new ArrayList();
strings.add("abc");
String s = (String)strings.get(0);
Assert.assertThat(s, Matchers.is("abc"));
}
private void uncheckedAssignment() {
ArrayList strings = new ArrayList();
strings.add("abc");
String s = (String)strings.get(0);
Assert.assertThat(s, Matchers.is("abc"));
}
private void explicit() {
ArrayList strings = new ArrayList();
strings.add("abc");
String s = (String)strings.get(0);
Assert.assertThat(s, Matchers.is("abc"));
}
Looks like they generated the same bytebote.
So when and why should we use type inference instead of the other two?
Others have covered why it generates the same code. So, to answer the actual question - the short answer is to prefer this:
ArrayList<String> strings = new ArrayList<>();
Because it's briefer than this, while conveying the same meaning (to humans and to the compiler):
ArrayList<String> strings = new ArrayList<String>();
But avoids unnecessarily causing a warning like this:
ArrayList<String> strings = new ArrayList();
As for being briefer, this:
ArrayList<String> strings = new ArrayList<String>();
Isn't that bad, and there's no real harm in typing it out (after all, we've all been doing it for years). But if you wind up writing something like:
Map<String, Map<Widget<Spork>, Bar<Llama>>> myMap = new HashMap<>();
It becomes far more tedious if you have to type this twice:
<String, Map<Widget<Spork>, Bar<Llama>>>
The type inference is just a shortcut for an unnecessarily long way of instantiating paremeterized types. Generics are still implemented by type-erasure, so your bytecode will only have the raw types.
As your example demonstrates, Java generics are implemented by type erasure and generic code is no different from non-generic code at runtime. This makes generics purely a compile-time feature - added type safety for the benefit of the developer.
In the case of your example, there's really no difference between new ArrayList(), new ArrayList<String>(), and new ArrayList<>() - all that matters is the type of the variable it gets assigned to. Using new ArrayList() is still discouraged because it looks like legacy code and may confuse another developer. It will cause compilers/IDEs to show the standard "raw types" warning and is therefore distracting. But that's it, for a no-arg constructor at least.
However, providing a type argument or using type inference really is important for any constructor that takes generic arguments. Consider this example:
Collection<Integer> ints = Arrays.asList(1, 2, 3);
List<String> strings1 = new ArrayList(ints); // compiles!
List<String> strings2 = new ArrayList<String>(ints); // won't compile
List<String> strings3 = new ArrayList<>(ints); // won't compile
As for why to use new ArrayList<>(ints) over new ArrayList<String>(ints), well, it's less verbose and avoids repeating the generic type already specified in the variable being assigned to.

Why can't you have a "List<List<String>>" in Java? [duplicate]

This question already has answers here:
Is List<Dog> a subclass of List<Animal>? Why are Java generics not implicitly polymorphic?
(19 answers)
Closed 5 years ago.
In Java, why doesn't the following line of code work?
List<List<String>> myList = new ArrayList<ArrayList<String>>();
It works if I change it to
List<ArrayList<String>> myList = new ArrayList<ArrayList<String>>();
At first, I thought maybe you can't have lists of an interface, but I can create a List<Runnable> just fine.
Ideas?
Generic types are more pedantic.
List means List or any sub-type, but <List> means only List. If you want a sub-type you need to have <? extends List>
I suspect you can use
List<List<String>> myList = new ArrayList<List<String>>();
The reason you can't do this is that you can be using a reference to a reference and with an extra level of indirection you have to be careful.
// with one level of indirection its simple.
ArrayList alist = new ArrayList();
List list = aList; // all good
list = new LinkedList(); // alist is still good.
With generics you can have two level of indirection which can give you problems so they are more pedantic to avoid these issues.
// with two levels of indirection
List<ArrayList> alist = new ArrayList<ArrayList>();
List<List> list = (List) alist; // gives you a warning.
list.add(new LinkedList()); // adding a LinkedList into a list of ArrayList!!
System.out.println(alist.get(0)); // runtime error
prints
Exception in thread "main" java.lang.ClassCastException: java.util.LinkedList
cannot be cast to java.util.ArrayList
Lets start with this:
ArrayList<ArrayList<String>> myList = new ArrayList<ArrayList<String>>();
This is creating an ArrayList whose elements are ArrayLists.
Now suppose we could assign that to
List<List<String>> myList2 = myList.
Now, we should be able to do this:
myList2.add(new LinkedList<String>());
But that means we have added a LinkedList to a list whose elements are supposed to be ArrayLists. Ooops!!!
In reality, the assignment of myList to myList2 is not legal ... and that ensures that it is not possible to add the wrong kind of List<String> to the ArrayList<ArrayList<String>> object. (No Peter, it is not just pedantry :-) )
Only the top level collection can be declared as an implementing class, while the nested ones must remain interfaces until you actually create instances:
List<List<String>> rootList = new ArrayList<List<String>>();
and then when you create an element to go in, you make it an implementation:
List<String> nodeList = new ArrayList<String>();
rootList.add(nodeList);
Its comparing Type from left(declaration) side to Type from right(instantiation) side. In Left, your type is List<String> while in right, it's ArrayList<String>. If complaining about the difference.
Please update the right side(instatiation) as List i.e.
List<List<String>> myList = new ArrayList<List<String>>();
This should work fine.
I know this is an old question but I just wanted to share my idea.
Instead of making a List of Lists, I personally just make a List of Type[] (List<Type[]> listArray = new ArrayList<Type[]>();), I generate a separate List of just Type (List<Type> list = new ArrayList<Type>();), then .add(list.toArray()). This way, it's clearer and easier to read than the List of Lists syntax which is confusing.
For example, in a recent project where I had an input file where each line with only a "0" meant a new line in the original (it was an encryption algorithm):
String[] input = getInputContents(inFile);
List<String> currentBuffer = new ArrayList<String>();
List<String[]> buffers = new ArrayList<String[]>();
for(String line : input) {
if(line.equals("0")) {
buffers.add((String[])currentBuffer.toArray());
currentBuffer = new ArrayList<String>();
} else {
currentBuffer.add(line);
}
}
the list<list<string>> l1=new list<list<string>>(); is allowed if the list contains one more list inside the list.
public final class CPanelXMLBuilder extends PanelXMLBuilder {
public CPanelXMLBuilder(AuthenticatedUser pAuthenticatedUser, Map<String, Object> pSessionMap, Map<String, Object> pRequestMap, String pPanelTemplate) throws Exception {
super(pAuthenticatedUser, pSessionMap, pRequestMap, pPanelTemplate, null);
}
public Map<String, Object> buildXMLDocument(List<List<String>> pDetailsList) {
if (pDetailsList.size() == 1) {
List<String> pCustomerDetail = pDetailsList.get(0);
xmlDocument.getRootElement().getChild("E_SHOW1").setText(pCustomerDetail.get(0));
xmlDocument.getRootElement().getChild("E_SHOW2").setText(pCustomerDetail.get(1));
xmlDocument.getRootElement().getChild("E_SHOW3").setText(pCustomerDetail.get(2));
xmlDocument.getRootElement().getChild("E_SHOW4").setText(pCustomerDetail.get(3));
xmlDocument.getRootElement().getChild("E_SHOW5").setText(pCustomerDetail.get(4));
xmlDocument.getRootElement().getChild("ServerTimestamp").setText(pCustomerDetail.get(5).substring(0, 19));
} else {
xmlDocument.getRootElement().getChild("AlertType").setText("INFO");
xmlDocument.getRootElement().getChild("Alert").setText("There is no matching record.");
}
requestMap.put(RequestMapKeys.XML_DOCUMENT, xmlDocument);
return requestMap;
}
}

Generics Declaration differences in Java

List<String> v = new ArrayList<String>();
I understand the generics helps you declare that the ArrayList() has Objects of type String. My question is
how is the following one different from the above?
List<String> v = new ArrayList();
or the one below different from others
List v = new ArrayList<String>();
List<String> v = new ArrayList();
This one isn't really functionally different. The type parameter on the right side doesn't really do anything. It's used as a matter of style and to avoid the use of a Raw type, which is considered a programming error. In fact, in Java 7 it has been enhanced so you can just do this: List<String> v = new ArrayList<>(); and not have to repeat yourself on the right hand side.
List v = new ArrayList<String>();
The list with no type parameter is called a Raw Type. It is generally considered a programming error to declare a Raw Type in new code that is using generics. Basically there is no type checking going on at all when you declare it this way, you can put anything in that list.
Java generics are a compile time check. So it is the type of the reference at compile time that matters. If your reference is of type Raw List it doesn't matter what you declared on the right hand side, that is what the compiler will check against.
List<String> isn't really a "List that has Strings." It is a "List that I have asked the compiler to return errors and/or warn me if I put something in there that isn't a String. If you ignore compiler warnings, it is perfectly possible to get stuff in there that isn't a String.
List v = new ArrayList();
It is before java 5 way of declaring a list.
List<String> v = new ArrayList<String>();
It uses generics, introduced in java 5. It adds compile-time type safety.
List<String> v = new ArrayList<>();
is just an optimization introduced in java 7. It just simplifies the code
by maintaining the type safety
public static void main(String[] args) throws Exception {
List<String> list1 = new ArrayList<String>();
List<String> list2 = new ArrayList(); //This is equivalent to list1 but with compilation warning
List list3 = new ArrayList<Integer>(); //This is equivalent to list3 = new ArrayList<Object>()
//list1.add(new Object()); //does not compile
//list2.add(new Object()); //does not compile
list3.add(new Object()); //this is fine
list1 = list3; //ok, but
System.out.println(list3.get(0)); // this is fine
System.out.println(list1.get(0)); //Runtime error: ClassCastException
//List<Object> list5 = list1; //does not compile
List<Object> list5 = list3; //ok
}
These all compile, and are all valid. The second case is likely only going to throw a warning - you won't be able to add anything that isn't a string due to List<String>. In the third case you have the opposite problem. You CAN add things that aren't Strings, but may run into a runtime exception as a result.
In the first and third case (new ArrayList<String>()) you instantiate an ArrayList that can hold String instances
In the second case (new ArrayList()) you instantiate an ArrayList that can hold Object instances (that is instances of any type -- even mix & match)
In the first and second case (ArrayList<String> v) you declare an instance of ArrayList that can hold String instances
In the third case (ArrayList v) you declare an instance of ArrayList that can hold instances of Object.
The problem with the second case is that if you were to get hold of a "raw" ArrayList (like the one instantiated), then it could hold anything theoretically; not just String instances, which is what the users of the declaration expect.
Similarly, in the third case, you create an ArrayList that is supposed to hold Strings, but the users of the declaration do not know that and might try to put other object instances in it
Note: of course under the hood, in the JVM, the generic type information is lost, so there are no differences in terms of execution, but for programming type safety, the compiler will flag the incorrect use. This way, there is no need to dynamically check/ensure the type of the objects put into/coming out of the list -- you can assume they are the correct type, because the compiler ensured this

unchecked conversion on multidimensional arraylist

Does anyone know how to fix this warning?
MyMain.java:12: warning: [unchecked] unchecked conversion
found : java.util.ArrayList[][]
required: java.util.ArrayList<java.lang.String>[][]
obj[count].someArrayList = new ArrayList[4][4];
I tried to change this to:
obj[count].someArrayList = new ArrayList<String>[4][4];
But the amendment changes the warning into the following error:
MyMain.java:12: generic array creation
obj[count].someArrayList = new ArrayList<String>[4][4];
The declaration of someArrayList is:
public ArrayList<String>[][] someArrayList;
You cannot create arrays with generics (hence the error). The warning indicates the heavily discouraged use of raw types with an ArrayList.
Instead, the following creates a multidimensional ArrayList:
public ArrayList<ArrayList<String>> someArrayList;
You can then perform normal operations on your multidimensional ArrayList.
obj[count].someArrayList = new ArrayList<ArrayList<String>>();
ArrayList<String> toAdd = new ArrayList<String>();
toAdd.add("test");
toAdd.add("test2");
obj[count].someArrayList.add(toAdd);
Only way to declare a multidimensional array of ArrayList is like this:
#SuppressWarnings("unchecked")
ArrayList<String>[][] someArrayList = new ArrayList[4][4];
someArrayList[0][0] = new ArrayList<String>();
someArrayList[0][1] = new ArrayList<String>();
....
....

Java 1.6: Creating an array of List<T>

Why can't I create an array of List ?
List<String>[] nav = new List<String>[] { new ArrayList<String>() };
Eclipse says "Cannot create a generic array of List"
or
ArrayList<String>[] nav = new ArrayList<String>[] { new ArrayList<String>() };
Eclipse says "Cannot create a generic array of ArrayList"
or
List<String>[] getListsOfStrings() {
List<String> groupA = new ArrayList<String>();
List<String> groupB = new ArrayList<String>();
return new List<String>[] { groupA, groupB };
}
But I can do this:
List[] getLists() {
return new List[] { new ArrayList(), new ArrayList() };
}
Eclipse says that List and ArrayList are raw types but it compiles...
Seems pretty simple, why won't it work?
Well, generics tutorial give the answer to your question.
The component type of an array object
may not be a type variable or a
parameterized type, unless it is an
(unbounded) wildcard type.You can
declare array types whose element type
is a type variable or a parameterized
type, but not array objects.
This is
annoying, to be sure. This restriction
is necessary to avoid situations like:
// Not really allowed.
List<String>[] lsa = new List<String>[10];
Object o = lsa;
Object[] oa = (Object[]) o;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
// Unsound, but passes run time store check
oa[1] = li;
// Run-time error: ClassCastException.
String s = lsa[1].get(0);
If arrays of parameterized type were
allowed, the previous example would
compile without any unchecked
warnings, and yet fail at run-time.
We've had type-safety as a primary
design goal of generics.
You can't create arrays of generic types, generally.
The reason is that the JVM has no way to check that only the right objects are put into it (with ArrayStoreExceptions), since the difference between List<String> and List<Integer> are nonexistent at runtime.
Of course, you can trick the compiler by using the raw type List or the unbound wildcard type List<?>, and then cast it (with a unchecked cast) to List<String>. But then it is your responsibility to put only List<String> in it and no other lists.
No exact answer, but a tip:
Last example has a raw type warning because you omitted the typization of the list; it is generally a better (type safe) approach to specify which object types are contained in the list, which you already did in the previous examples (List<String> instead of List).
Using arrays is not best practice, since their use contains errors most times; Using Collection classes (List, Set, Map,...) enables use of typization and of convenient methods for handling their content; just take a look at the static methods of the Collections class.
Thus, just use the example of the previous answer.
Another solution is to extend LinkedList<String> (or ArrayList<String>, etc.), then create an array of the subclass.
private static class StringList extends LinkedList<String> {}
public static void main(String[] args)
{
StringList[] strings = new StringList[2];
strings[0] = new StringList();
strings[1] = new StringList();
strings[0].add("Test 1");
strings[0].add("Test 2");
strings[1].add("Test 3");
strings[1].add("Test 4");
System.out.println(strings[0]);
System.out.println(strings[1]);
}

Categories