Why doesn't the following line compile? [duplicate] - java

This question already has answers here:
Creating new generic object with wildcard
(2 answers)
Closed 3 years ago.
I am trying to create an arraylist which can contain any type of object by using a generic with an unbounded wildcard.
ArrayList<?> params = new ArrayList<?>();
I do not understand why I receive the following error and I want to know where I am going wrong?
required: class or interface without bounds
found: ?

A simple approach to your problem is to use an ArrayList<Object>:
ArrayList<Object> params = new ArrayList<>();
The ? operator refers to all objects that are of unknown type, so using it to add objects of known type (e.g. String) will cause errors, as described here.

You simply aren't allowed to do this. It says this in JLS 15.9:
If TypeArguments is present immediately after new, or immediately before (, then it is a compile-time error if any of the type arguments are wildcards (§4.5.1).
A list instance never has a bounded type: a list is always a list with elements of a particular type.
It is only list variables which can be bounded, in order to store lists with elements of particular types within those bounds.
So, this would be fine:
ArrayList<?> params = new ArrayList<SomeType>();
or
ArrayList<?> params = new ArrayList<>();
That's not to say that you can't use bounds on the RHS at all:
new ArrayList<List<?>>()
would be fine, because List<?> isn't a wildcard (because syntactically wildcards always start with ?).

You can’t write new ArrayList<?> because there’s no such thing as an ArrayList<?>.
Every ArrayList has a specific type. When you write ArrayList<?> params, you are telling the compiler: “This variable will hold an ArrayList whose elements are a specific type, like String or Number, but as I write this line of code, I don’t know what that type will be.”
So you can refer to an ArrayList as having a type that is not known at compile time, but every existing ArrayList has an actual type, regardless of how variables refer to it. When code creates an ArrayList, that type has to be specified.

Related

Why "new ArrayList<E>" is allowed?

I am studying "Java in a Nutshell" 5th Edition. In p169, it says "Remember,
though, that type variables exist only at compile time, so you can’t use a type variable
with the runtime operators instanceof and new.". If I understand it correctly (Am I??), new and instanceof should not be used with type variables. But after I did some tests, I became more confused.
List< ?> l = new ArrayList< ?>(); // not compiled and I may know why
List< E> l = new ArrayList< E>(); // compiled!! WHY??
Could anyone tell me why (2) is allowed??
Really thanks for any information.
The statement "you can't use type variable with new" means you can't do this:
E e = new E(); // can't do this
But you can pass a type variable through to another class for it to use:
class MyClass<E> {
List<E> = new ArrayList<E>(); // OK
}
You're not instantiating E, you're instantiating an ArrayList with the type E.
Regarding using ?, that's a different issue. The ? means "unknown" type, while a variable can be of an unknown type, you can't instantiate a generic class by specifying unknown type - you must pass a known type through to the generic class.
You can however code this:
List<?> list = new ArrayList<E>();
Unless you've defined it, E isn't a class.
E is just a way to make reference to a class during compilation. That way, proper methods can be called with it.
List<String> list1 = new ArrayList<String>(); // Diamond types for Java 7+
List<Integer> list2 = new ArrayList<Integer>();
// Populate lists
list1.get(0).charAt(0); // Perfectly fine, String#charAt(int) exists
list2.get(0).charAt(0); // Error! Integer doesn't have a charAt(int) method!
So, the type E inside the ArrayList class is used to ensure that you can perform operations on the elements if you know the type, as if it were that type. This avoids running into issues when calling on methods that only exist in the specific class, as I showed with the charAt(int) method.
Adding onto this, it can be pointed out why you can't make the call with the ?.
List<?> list1 = new ArrayList<String>(); // Fine
List<?> list2 = new ArrayList<?>(); // What type is this list composed of?
It doesn't make sense to make a list of an unknown type. If you want a list of a generic type, you can always pass the Object into the generics, but there was no reason to add support for creating instances with an unknown type.
Bohemian answered a bit of the "what," but I'd like to take a crack at some of the "why."
Let's start with what you can't do. It all comes down to erasure, which basically means that when your code has a List<String>, the bytecode information only has a List. Anything between the angle brackets is missing from the bytecode (and thus from the runtime).
So, why can't you do foo instanceof E? Well, because that's a runtime check, and E isn't known at runtime.
And why can't you do new E()? Again, because that requires the runtime to know what E is (how else can it call the right constructor? Or even ensure that a no-arg constructor exists?), but that information isn't available to it.
In all these cases, the thing to keep in mind is that the language isn't preventing you from doing something just for the sake of preventing you. It's preventing you from doing it because it'd be impossible to execute at runtime.
So, why can you type new ArrayList<String>()? Because the only information that the runtime needs for that is the fact that an ArrayList is being instantiated, and it has that information. The fact that it's an ArrayList of Strings doesn't matter to the runtime, because erasure means that the ArrayList doesn't know or care about what it's a list of, at runtime.

List and List<?> in Java

What is the difference between List and List<?>? I know I can't add any element to the List<?>. I have a code:
List<String> myList = new ArrayList<String>();
processList(myList);
processListGeneric(myList);
public static void processList(List myList) {
Iterator it = myList.iterator();
while(it.hasNext())
System.out.println(it.next());
}
public static void processListGeneric(List<?> myList) {
Iterator<?> it = myList.iterator();
while(it.hasNext())
System.out.println(it.next());
}
The name of the two methods cannot be the same, because it causes compile time error. So is there any difference in these two approaches?
Both do the same, but in second case compiler is informed that you really want a list with no type bounds and raises no warnings. If you are working with Java 5 or later you are encouraged to use second approach.
The difference is that you can't add anything to a List<?>, since it's a List of an unknown type.
For example, you are prevented from doing this:
List<Integer> listOfInt = new ArrayList<Integer>();
List<?> list = listOfInt;
list.add("hello?"); // Compile-time error
You can add anything you want to the base type List since the type of the list items is not checked.
List<?> (pronounced "collection of unknown")is a collection whose element type matches anything. It's called a wildcard type for obvious reasons.
Refer to the following code
List<String> myList = new ArrayList<String>();
myList.add("John");
String name = myList.get(0);
System.out.println(name); //print John
List<?> myListNew = myList;
myListNew.add("Sam");//Compile time error
String nameNew = myListNew.get(0);//Compile time error
Object newName = myListNew.get(0);
System.out.println(newName);//Prints John
Since we don't know what the element type of myListNew stands for, we cannot add objects to it. The add() method takes arguments of type E, the element type of the collection. When the actual type parameter is ?, it stands for some unknown type. Any parameter we pass to add would have to be a subtype of this unknown type. Since we don't know what type that is, we cannot pass anything in. The sole exception is null, which is a member of every type.
On the other hand, given a List<?>, we can call get() and make use of the result. The result type is an unknown type, but we always know that it is an object. It is therefore safe to assign the result of get() to a variable of type Object or pass it as a parameter where the type Object is expected.
List is raw type and List< ?> is wildcard type. Take look http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html
Both of them behave same. Using parametrized notation you are just avoiding any warnings in Java5 and above. You cannot have both the syntax in same java file because due to type erasure compiled unit has two methods with exactly same signature in same class file and thus violating language rules.
Following is what you would be getting from compiler:
Method processList(List) has the same erasure processList(List) as another method in type ...
Just writing List without a type parameter is deprecated, but otherwise the same as writing List<Object>. So the question becomes "What's the difference between List<Object> and List<?> and which one should I use?".
As you already know, you can't add (anything other than null) to a List<?>, so if you need to add to a list, you should use a List<Object> (or a more specific type where applicable, of course). On the other hand, a method that takes a List<Object>, only accepts List<Object>s and not any lists that contain a subclass of Object. That is, it would not accept a List<String>. If the method takes a List<?> however, it accepts any kind of list. So if you don't need to add to the list, you should use List<?> as it is more general.
The second method uses generics (introduced in Java 5).
One important distinction is the <?> represents a single type, not any object like this:
List<? extends Object> myList
So you could say that using the first method (without the wildcard syntax) is more flexible, as you'd be able to add any object to your List. Although, you'll get a (compiler) warning that you declaration should be parameterized.
Using the <?> unbounded wildcard syntax will avoid the warning, but you're telling the compiler it could be a list of any type, instead of actually using generics to enforce type safety. You are strongly encouraged to use generics to assist you in making your application type safe.
If, for example, you know that the list should only ever contain String objects, declare it thus:
List<String> myList
Then you'll avoid unnecessary casting of use of the instanceof operator, etc.
Here's a brief tutorial on generics in Java, for your information:
http://javarevisited.blogspot.co.uk/2011/09/generics-java-example-tutorial.html

Creating an array to store generic types in Java [duplicate]

This question already has answers here:
Generic arrays in Java
(5 answers)
Closed 9 years ago.
Suppose I have to create an array which stores ArrayList's of Integers and the array size is 10.
The below code will do it:
ArrayList<Integer>[] pl2 = new ArrayList[10];
Question 1:
In my opinion the more appropriate code would be
ArrayList<Integer>[] pl2 = new ArrayList<Integer>[10];
Why does this not work?
Question 2:
Both of the below compile
ArrayList<Integer>[] pl2 = new ArrayList[10];
ArrayList[] pl3 = new ArrayList[10];
What is the difference as far as the reference declaration of pl2 and pl3 is concerned?
The generic info only matters in compile time, it tells the compiler which type could be put into an array, in runtime, all the generic info will be erased, so what matters is how you declare the generic type.
Quoted from Think in Java:
it’s not precisely correct to say that you cannot create arrays of
generic types. True, the compiler won’t let you instantiate an array
of a generic type. However, it will let you create a reference to
such an array. For example:
List<String>[] ls;
This passes through the compiler without complaint. And although you
cannot create an actual array object that holds generics, you can
create an array of the non-generified type and cast it:
//: arrays/ArrayOfGenerics.java
// It is possible to create arrays of generics.
import java.util.*;
public class ArrayOfGenerics {
#SuppressWarnings("unchecked")
public static void main(String[] args) {
List<String>[] ls;
List[] la = new List[10];
ls = (List<String>[])la; // "Unchecked" warning
ls[0] = new ArrayList<String>();
// Compile-time checking produces an error:
//! ls[1] = new ArrayList<Integer>();
// The problem: List<String> is a subtype of Object
Object[] objects = ls; // So assignment is OK
// Compiles and runs without complaint:
objects[1] = new ArrayList<Integer>();
// However, if your needs are straightforward it is
// possible to create an array of generics, albeit
// with an "unchecked" warning:
List<BerylliumSphere>[] spheres =
(List<BerylliumSphere>[])new List[10];
for(int i = 0; i < spheres.length; i++)
spheres[i] = new ArrayList<BerylliumSphere>();
}
}
Once you have a reference to a List[], you can see that you
get some compile-time checking. The problem is that arrays are
covariant, so a List[] is also an Object[], and you can use
this to assign an ArrayList into your array, with no error at
either compile time or run time.
If you know you’re not going to
upcast and your needs are relatively simple, however, it is possible
to create an array of generics, which will provide basic compile-time
type checking. However, a generic container will virtually always be a
better choice than an array of generics.
Question 1:
Basically, this is forbidden by Java language. This is covered in Java Language Specification for generics.
When you use
ArrayList<Integer>[] pl2 = new ArrayList[10]; // warning
you get the compiler warning, because the following example will compile (generating warning for every line of code):
ArrayList wrongRawArrayList = new ArrayList(); // warning
wrongRawArrayList.add("string1"); // warning
wrongRawArrayList.add("string2"); // warning
pl2[0] = wrongRawArrayList; // warning
but now you array, that supposed to contain ArrayList of Integer, contains totally wrong ArrayList of String objects.
Question 2:
As it was already answered, declaration of p12 provides you with compile time checking and frees you from using casting when getting items from your ArrayList.
Slightly modified previous example:
ArrayList<Integer>[] pl2 = new ArrayList[10]; // warning
ArrayList<String> wrongArrayList = new ArrayList<String>(); // OK!
wrongArrayList.add("string1"); // OK!
wrongArrayList.add("string2"); // OK!
pl2[0] = wrongArrayList; // ERROR
Now, since you are using generics, this won't compile.
But if you use
ArrayList[] pl2 = new ArrayList[10];
you will get the same result as in the first example.
Arrays are covariant. That means they retain the type of their elements at runtime. Java's generics are not. They use type erasure to basically mask the implicit casting that is going on. It's important to understand that.
You need to use Array.newInstance()
In addition, arrays carry runtime type information about their
component type, that is, about the type of the elements contained.
The runtime type information regarding the component type is used when
elements are stored in an array in order to ensure that no "alien"
elements can be inserted.
For more details look here
This does not work because generic classes does not belong to Reifiable Types.
The JLS about Array creation expression states :
It is a compile-time error if the [class type] does not denote a reifiable type (§4.7). Otherwise, the [class type] may name any named reference type, even an abstract class type (§8.1.1.1) or an interface type (§9).
The rules above imply that the element type in an array creation expression cannot be a parameterized type, other than an unbounded wildcard.
The definition of Reifiable Types is :
Because some type information is erased during compilation, not all types are available at run time. Types that are completely available at run time are known as reifiable types.
A type is reifiable if and only if one of the following holds:
It refers to a non-generic class or interface type declaration.
It is a parameterized type in which all type arguments are unbounded wildcards (§4.5.1).
It is a raw type (§4.8).
It is a primitive type (§4.2).
It is an array type (§10.1) whose element type is reifiable.
It is a nested type where, for each type T separated by a ".", T itself is reifiable.
For example, if a generic class X<T> has a generic member class Y<U>, then the type X<?>.Y<?> is reifiable because X<?> is reifiable and Y<?> is reifiable. The type X<?>.Y<Object> is not reifiable because Y<Object> is not reifiable.
Let's start with question 2 first and then get back to question 1:
Question 2:
>
ArrayList[] pl2 = new ArrayList[10];
ArrayList[] pl3 = new ArrayList[10];
What is the difference as far as the reference declaration of p12 and
p13 is concerned?
In pl2 ensures better type safety than p13.
If I write for pl2:
pl2[0]=new ArrayList<String>();
it will give me a compiler error stating "cannot convert from ArrayList<String> to ArrayList<Integer>"
Thus it ensures compile time safety.
However if I write for p13
pl3[0]=new ArrayList<String>();
pl3[1]=new ArrayList<Integer>();
it will not throw any error and the onus will be on the developer to code and check properly while extracting data from p13, to avoid any unsafe type conversion during runtime.
Question 1:
That's just probably the way generics work. During the main array initialization, ArrayList<Integer>[] pl2 = new ArrayList[10], the left hand side, ArrayList<Integer>[] pl2, will ensure type safety only when you initialize the ArrayList object in the index position:
pl2[0]=new ArrayList<Integer>();
The right hand side main array declaration = new ArrayList[10] just ensures that the index position will hold ArrayList type items. Also have a look at type erasure concepts in Type Erasure for more information.
Question 1.
Well, it's not the correct syntax. Hence that does not work.
Question 2.
ArrayList<Integer>[] pl2 = new ArrayList[10];
ArrayList[] pl3 = new ArrayList[10];
Since pl2 is defined with generic type <Integer> at compile time, the compiler will be know that pl2 is only allowed to have Integers and if you try to assign somthing other than Integers you will be alerted and compilation will fail.
In pl3 since there is no generic type you can assign any type of object to the list.
ArrayList<Integer>[] pl2 = new ArrayList<Integer>[10];
Means you don't need to do casting when you retrive data from the ArrayList
example
in normal case
ArrayList[] pl2 = new ArrayList[10];
pl2.put(new Integer(10));
Integer i = p12.get(0); // this is wrong
Integer i = (Integer)p12.get(0); // this is true with casting
but
ArrayList<Integer>[] pl2 = new ArrayList<Integer>[10];
pl2.put(new Integer(10));
Integer i = p12.get(0); // this is true no need for casting
Problems with generics are by default issued as a warning by the compiler.
After compilation, because of type erasure, they all become ArrayList[] pl2 = new ArrayList[10], but the compiler warns you that this is not good.
Generics have been added to Java, and to be backwards compatible you can use generic with non-generic interchangeably.
Question1
You cannot create arrays of parameterized types
Question 2
ArrayList<Integer>[] pl2 = new ArrayList[10];
It means you are telling to compiler that you are going to create array which will store arraylist of integers. Your arraylist will only contain Integer objects. That's where generics comes in. Generics make your code more safer and reliable. If you are sure your list should only contain integer objects, you should always go ahead with this.
But when you say
ArrayList[] pl3 = new ArrayList[10];
it means arraylist can store any object type like string, integer, custom objects, etc.
It seems like you cannot create an array of arraylists with a generic type, according to an answer to Stack Overflow question Create an array of ArrayList elements.
As far as I know, in Java there are no such things as generics. In terms of types, ArrayList<Integer> and ArrayList are the same things.
Java uses type erasure for generics. It means that all type information about the generic is erased at compile time. So ArrayList<Integer> become ArrayList.
So it's just a compile-time trick. I am guessing, to avoid any confusions or mistakes that the programmer might do, they allowed ArrayList<Integer>[] to be instantiated like this: new ArrayList[10].
So an ArrayList<Integer>[] and a ArrayList[] are the same thing because the information in brackets is erased at compile time.

what is "<>" use for in java? for example List<File> sourceFileList = new ArrayList<File> [duplicate]

This question already has answers here:
Java Generics: List, List<Object>, List<?>
(13 answers)
Closed 10 years ago.
I am new to java.
I would like to know what is <> used for in java.
This is an example where I get confused:
List<File> sourceFileList = new ArrayList<File>
<> is a place holder which hold's generic type. you embed the Type Parameter in the angle brackets.
List<File> sourceFileList = new ArrayList<File>
The above piece of code describes that your List can only have instance of type File.
It provides compile time type safety. you can only add File/sub type of File Objects into the list.
sourceFileList.add(new File("test.txt"));
sourceFileList.add("abc");// compiler error as your
list only accepts File instances
Links:
Awesome Tutorial for Generics
Oracle Official Docs
It is part of Java Generics introduced in version 1.5.
Following link might be useful: http://docs.oracle.com/javase/tutorial/java/generics/
<> are generally used for Generic data types in java.
So here List means that you are having a list of files.
So if you write List<Person> it will become list of persons. Thus you can replace the text within <> with any class' object.
It is to tell the compiler what kind of data is going into the object. For example, List<File> tells java that you want to create a List that will be filled with File type data. For another example: Array<Integer> would tell java you want an Array that you will be filling with Integer data.
Java Generics (not to be confused with C++ templating). It allows you to define types when defining classes that are Generi-fied.
In your case, the List<File> states that you have a List containing types of File.
You should take a look at the java generics tutorial:
http://docs.oracle.com/javase/tutorial/java/generics/
And if you are really into it, check out the java language specification, specifically the part about generics:
http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.1.2
In your example the <> is being used to instantiate an ArrayList of File objects. The <> merely specifies the type of objects your ArrayList holds
Generics...
We stored String objects in the array list and to retrieve an object, we had to type cast it. Only programmer knows which objects he has stored in the ArrayList, so he is responsible to type cast it in the required type. What if, he by mistake casts it into wrong type?
Java Code:
System.out.println((Integer)myArrayList.get(3));
Error:
Exception in thread "main" java.lang.ClassCastException: java.lang.String
To avoid such conditions, generics come into play. We can specify the type for a List so that list can only hold or store objects of that very type. Objects of some other types wont be stored into the list and no type casting is required then.
Java Code:
ArrayList<String> myArrayList = new ArrayList<String>();
myArrayList can not only store ‘String objects. Type safety is ensured and now programmer has better control over the array list.
The type is specified in angle brackets when we are declaring an instance of a class or interface. Without generics the type parameters are omitted, but one must explicitly cast whenever an element is extracted from the list.
If you want to translate your code into English to read it, you could say "of type" when you see <>.
eg for
List<File> sourceFileList
say "List of type File, "sourceFileList""
Datatype of your List.
Example:
ArrayList<String> yourArrayList = new ArrayList<String>;
It declares your ArrayList as a String. Instead of using yourArrayList.get(index).toString(); you may use yourArrayList.get(index); and will return a String(In this example) and will only accept String datatype.

Warning ArrayList is a raw type. References to generic type ArrayList<E> should be parameterized [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
ArrayList is a raw type. References to generic type ArrayList<E> should be parameterized
In order to save an ArrayList with payments done by one member I want to change the List of Payment ID's into a string, so I created the following method:
public String fromArraytoString(ArrayList items){
JSONObject json = new JSONObject();
json.put("uniqueArrays", new JSONArray(items));
return json.toString();
}
But I get the following warning:
ArrayList is a raw type. References to generic type ArrayList<E> should be parameterized
Can anyone explain me why?
You definitely should read this tutorial on Java generics:
http://docs.oracle.com/javase/tutorial/java/generics/
In a nutshell:
Many Java classes and types (called generic classes or generic types), typically collections, have so called type parameters, such as E in ArrayList<E> (E is just an arbitrary chosen name, other classes name it as T or whatever):
public class ArrayList<E> extends ... {
public E get(int index) { ... }
public boolean add(E element) { ... }
// other methods...
}
Now, when you create an instance of such class, you define a concrete value of the type parameter, for example String (E can usually be evaluated to whatever type you want):
ArrayList<String> stringList = new ArrayList<String>();
From now on, all the Es are "replaced" by String for the stringList variable, so you can add only Strings to it and get only Strings from it. The compiler checks for you that you don't mistakenly add an object of another type:
stringList.add(Integer.valueOf(1));
// compile error - cannot add Integer to ArrayList of Strings
However, because generics were added to Java 5, it is still possible to write code without them for backwards compatibility. So you can write:
ArrayList list = new ArrayList();
But you lose all the type checking benefits. Es in method signatures become simply Objects.
list.add(Integer.valueOf(42)); // adding an Integer
list.add("aaa"); // adding a String
Object something = list.get(0); // unknown type of returned object, need to cast
Integer i0 = (Integer) something; // this unsafe cast works...
Integer i1 = (Integer) list.get(1); // but this fails with a ClassCastException
// because you cannot cast a String to Integer
The fact that using a raw type (that is a generic type with its type parameters omitted) is unsafe, is the reason for the warning you've got. Instead of just ArrayList, use ArrayList<String> or ArrayList<Integer> or whatever the type of your items is.
What kind of objects are stored in the ArrayList? You need to add it to the declaration. It's always
ArrayList<Type>
So if it's a list of JSONObjects, you would put
ArrayList<JSONObject>
Hope that helps.
JsonArray's constructor expects to receive a generic type Collection with parameter T, while items's type is ArrayList without type specified(i.e raw type). You may check this question to get some idea about raw type: What is a raw type and why shouldn't we use it?
Solution 1(recommended): pass items with paramter T or specify concrete type such as String. This question might help you in your specific problem: convert ArrayList<MyCustomClass> to JSONArray.
Solution 2: add #SuppressWarnings("unchecked") before the method fromArraytoString.
This is not recommended, but you can refer to this question: What is SuppressWarnings ("unchecked") in Java?
This is because Java compiler tries to do certain checking for you. The way you have written it you effectively tell compiler you will receive ArrayList of Object's as parameter.
It's simply encouraging you to specify class of objects you will to store in ArrayList. Specifying ArrayList<MyClass> or ArrayList <?> would get rid of the warning. Second version effectively tells compiler that you would pass ArrayList of objects of class not known at compile time.
I think it might be useful for you to read a bit about generics in Java.
http://docs.oracle.com/javase/tutorial/java/generics/

Categories

Resources