I am new to Java, so I am not aware of the nitty gritties.
Why can't I create generic array of parametrized ArrayList?
Instead I have to write,
ArrayList<String>[] alist = new ArrayList[10];
or I have to create List of ArrayLists.
Aren't arrays supposed to be more efficient than ArrayLists? Then why doesn't Java allow it?
Also, what is the difference between following two lines.
ArrayList<String>[] alist = new ArrayList[10];
ArrayList<String>[] alist = new ArrayList<?>[10];
The reason you have to do that is because generics don't really exist in Java. It's actually a compiler hack.
As for the two lines you posted, there shouldn't be any difference in terms of the bytecode produced. However, in the first case you'll probably get a warning because your compiler thinks you forgot java.util.ArrayList wants a type parameter, whereas the latter won't compile because you're trying to instantiate a generic array. Lose-lose situation :(
Actually the implementation of ArrayList is very efficient for read and write actions that don't change the size of the list. In many cases (at least since java 1.6) the compiler will totally remove the method call overhead (for instance for get()).
Also not many programs require the performance that an array offers, so don't worry about using arrays until your code is too slow (and even then you probably don't need the arrays)
If you could do that, this will happen :
ArrayList<String>[] alist = new ArrayList<String>[10];
Object[] olist = alist; // This is okay because ArrayList is an Object
olist[0] = new ArrayList<Dog>();
olist[0].add(new Dog());
String s = alist[0].get(0); //Uh oh, Dog is not string
I would also recommend creating an arraylist of arraylists.
ArrayList<ArrayList<Type>> alist = new ArrayList<ArrayList<Type>>();
, where Type is whatever type you wanted the list to be. You now have an arraylist that holds array lists. If you want to add an arraylist, you can do:
alist.add(new ArrayList<Type>());
Related
This question already has answers here:
ArrayList Generic without Type
(5 answers)
Closed 5 years ago.
I have a question about the history of Java.
Java has had ArrayList since 1.2.
Java has generics since version 1.5.
How was the implementation of ArrayList without generics to define the type?
It was all done with Object (and there was a lot of casting involved), e.g.:
ArrayList list = new ArrayList();
list.add(new Thingy());
// ...
Thingy t = (Thingy)list.get(0);
// Note ---^^^^^^^^
The list only knew what it stored was Object, it was up to the code using the list to cast back to a useful type.
As you can imagine, this lead to all sorts of unpleasantness — you could put the wrong kind of object in the list, and then get ClassCastExceptions later when you tried to cast it to the type you were expecting; if you changed what was in the list, you had to change your casts everywhere and inevitably forget one, etc., etc. Generics helped remove those pain points.
Before generics, ArrayList have the Object as a type so that you can insert and get back the type Object which mean that you need to cast them while retrieving back to respected type. After generics these kind of redundant code got removed.
If you have close look at generic docs, your specific question been answered
Elimination of casts.
The following code snippet without generics requires casting:
List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0);
When re-written to use generics, the code does not require casting:
List<String> list = new ArrayList<String>();
list.add("hello");
String s = list.get(0); // no cast
Actually you should not ask these type of questions in stackoverflow.What everyone expects is somecode from you to debug..But anyway you seems to be like new to stackoverflow...
You can use arraylist without generics too.
For example if you use generics to hold items of particular type it looks like this..
ArrayList<String> list=new ArrayList<>();
If you don't want to use generics you can simply use this
ArrayList list =new ArrayList();
Let me tell you the very big disadvantage of using without generics.If you don't use generics then it assumes every thing as objects.So you need to type cast these to your particular datatype each time you retreive elements.
For example
for (Object o:list)
{
String s=(String)o;
System.out.println(s);
}
is what you have to do if you dont use generics..
If you use generics
then
for(String s:list)
{
System.out.println(s)
}
Hope this helps....:)
I giving a mock test on SCJP. I encounter two different question having the statements as
ArrayList<Integer> arr = new ArrayList<Integer>();
and
ArrayList arr = new ArrayList();
1) What is the differnce between these two?
My Analysis=> first can store Integerand its subclasses. and the second can store Object and its subclasses.
2) Can we make object without <> of any generic class?
1) What is the differnce between these two?
You already find the answer yourself. I suggest you to go deeper in the Java documentation to look for details...
2) Can we make object without <> of any generic class?
IMO, you should always use the first approach:
ArrayList<Integer> arr = new ArrayList<Integer>();
or better
List<Integer> arr = new ArrayList<Integer>();
because you make clear to the reader what you intent to put in the ArrayList.
1) What is the differnce between these two?
ArrayList<Integer> arr = new ArrayList<Integer>(); This list store Integer class objects.
ArrayList arr = new ArrayList(); - This list is generic list it will store all type of objects.
2) Can we make object without <> of any generic class?
<> is a generics which introduced by Java 5
Generics add stability to your code by making more of your bugs
detectable at compile time.
when you are adding object in collection its become error prone when you don't know which type of objects your collection takes. and which type of object you have to retrieve from that collection.
So, It's better to use generics, Read more about Generics
Short answer: ArrayList without <> is basically equivalent to ArrayList<?> which means that the type of the List's content in not known at compile time.
Due to type erasure at runtime there's no difference between the generic and non-generic version: they are just list containing objects.
What you gain using the generic (with <>) version is that the compiler can do some static type checking assuring that your code is sound at least at the type level.
As per your second question, yes. You can create non-generic version of any generic class, although this is generally a bad practice both for the clarity of your code as well as its safeness.
It is necessary to use generics with ArrayList? Like this:
ArrayList<Object> software=new ArrayList<Object>();
Can I write it without it? Because I face a problem when I want to add object to it.
What I try to do is to get info from the frame and then create object and add it to tha arraylist
class Listener implements ActionListener {
public void actionPerformed(ActionEvent e) {
ArrayList software= new ArrayList();
String s = (String) major.getSelectedItem();
if((e.getActionCommand()).equals("SAVE")){
int st_id=Integer.parseInt(id.getText());
String st_name=name.getText();
String st_gender = (String) gender.getSelectedItem();
String st_major = (String) major.getSelectedItem();
String code1=code_sw1.getText();
String code2=code_sw2.getText();
String code3=code_sw3.getText();
double mark1=Double.parseDouble(m_sw1.getText());
double mark2=Double.parseDouble(m_sw2.getText());
double mark3=Double.parseDouble(m_sw3.getText());
St_Sw ob1=new St_Sw(st_id,st_name,st_gender,st_major,code1,code2,code3,mark1,mark2,mark3);
software.add(ob1);
}
}
}
What you mean is not parameter, it's a generic type. You can do a raw list like this:
List list = new ArrayList();
and it will work fine however the whole point of introducing generics in Java was to "fix" raw lists. If you store different objects than Object then it might go wrong when you for example iterate through the list and call one method on each element.
It technically isn't necessary, and you can make an ArrayList without a type and have everything work just fine.
That being said, you should consider it necessary and whenever you run into a situation where you have to not type it, you are probably doing something wrong. Chances are you should look into polymorphism/inheritance (http://en.wikipedia.org/wiki/Polymorphism_%28computer_science%29), or interfaces (http://docs.oracle.com/javase/tutorial/java/concepts/interface.html) so that you can store multiple types of objects in the same ArrayList.
The main reason you want to type all of your ArrayList is so that Java will tell you when you try to so something wrong. At first, you might think that this is causing the problem, and making it stop yelling at you is always better than it not compiling. In reality, though, if Java is yelling at you, you are doing something wrong.
In your case, it appears that the arrayList only contains St_Sw Objects. If that is the case, you would want to make your ArrayList with:
ArrayList<St_Sw> software=new ArrayList<St_Sw>();
Since Java 7 you can use the diamond operator:
ArrayList<Object> software=new ArrayList<>();
Arraylist is a dynamic array with means that new memory is allocated when you add new items to the list. There is no need to define the size before creating a arraylist. To add a object just call the add method for software.
As mentioned before,
List list = new ArrayList();
but also:
List<String> list = new ArrayList();
Is valid code in Java, and is supported for backwards compartibility reasons, as Java started having raw, non-generic types for structures like List etc. Non-generic types do not provide safety of type checking in compile time and should be avoided in new code, in general (Look here for more).
However, you can use diamond type inference for a shorthand, putting an "empty" diamond on the right side.
In Java, this
List<String> list = new ArrayList<>();
Is equal to this
List<String> a = new ArrayList<String>();
Code 1:
ArrayList arr = new ArrayList();
arr.add(3);
arr.add("ss");
Code 2:
ArrayList<Object> arr = new ArrayList<Object>();
arr.add(3);
arr.add("ss");
Code 3:
ArrayList<Object> arr = new ArrayList<Object>();
arr.add(new Integer(3));
arr.add(new String("ss"));
all the above three codes are working fine.. can some one tell me the which is prefered and why.. and why the eclipse compiler always gives warning when type of arguments are not mentioned to the Arraylist.. thanks in advance..
First simple rule: never use the String(String) constructor, it is absolutely useless (*).
So arr.add("ss") is just fine.
With 3 it's slightly different: 3 is an int literal, which is not an object. Only objects can be put into a List. So the int will need to be converted into an Integer object. In most cases that will be done automagically for you (that process is called autoboxing). It effectively does the same thing as Integer.valueOf(3) which can (and will) avoid creating a new Integer instance in some cases.
So actually writing arr.add(3) is usually a better idea than using arr.add(new Integer(3)), because it can avoid creating a new Integer object and instead reuse and existing one.
Disclaimer: I am focusing on the difference between the second and third code blocks here and pretty much ignoring the generics part. For more information on the generics, please check out the other answers.
(*) there are some obscure corner cases where it is useful, but once you approach those you'll know never to take absolute statements as absolutes ;-)
The second one would be preferred:
it avoids unnecessary/inefficient constructor calls
it makes you specify the element type for the list (if that is missing, you get a warning)
However, having two different types of object in the same list has a bit of a bad design smell. We need more context to speak on that.
The second form is preferred:
ArrayList<Object> arr = new ArrayList<Object>();
arr.add(3);
arr.add("ss");
Always specify generic arguments when using generic types (such as ArrayList<T>). This rules out the first form.
As to the last form, it is more verbose and does extra work for no benefit.
Actually, a third is preferred:
ArrayList<Object> array = new ArrayList<Object>();
array.add(Integer.valueOf(3));
array.add("ss");
This avoids autoboxing (Integer.valueOf(3) versus 3) and doesn't create an unnecessary String object.
Eclipse complains when you don't use type arguments with a generic type like ArrayList, because you are using something called a raw type, which is discouraged. If a class is generic (that is, it has type parameters), then you should always use type arguments with that class.
Autoboxing, on the other hand, is a personal preference. Some people are okay with it, and some not. I don't like it, and I turn on the warning for autoboxing/autounboxing.
You are getting the warning because ArrayList is part of java generics. Essentially, it's a way to catch your type errors at compile time. For example, if you declare your array list with types Integer (ArrrayList<Integer>) and then try to add Strings to it, you'll get an error at compile time - avoiding nasty crashes at runtime.
The first syntax is there for backward compatibility and should be avoided whenever possible (note that generics were not there in older versions of java).
Second and third examples are pretty much equivalent. As you need to pass an object and not a primitive type to add method, your 3 is internally converted to Integer(3). By writing a string in double-quotes you effectively are creating a String object. When calling String("ss") you are creating a new String object with value being the same as the parameter ("ss").
Unless you really do need to store different types in your List, I would suggest actually using a proper type declaration, e.g. ArrayList<Integer> = new ArrayList<Integer>() - it'll save you a lot of headache in the long run.
If you do need multiple datatypes in the list, then the second example is better.
Two last variants are the same, int is wrapped to Integer automatically where you need an Object. If you not write any class in <> it will be Object by default. So there is no difference, but it will be better to understanding if you write Object.
Well by doing the above you open yourself to run time errors, unless you are happy to accept that your arraylists can contains both strings and integers and elephants.
Eclipse returns an error because it does not want you to be unaware of the fact that by specifying no type for the generic parameter you are opening yourself up for run time errors. At least with the other two examples you know that you can have objects in your Arraylist and since Inetegers and Strings are both objects Eclipse doesn't warn you.
Either code 2 or 3 are ok. But if you know you will have either only ints or only strings in your arraylist then I would do
ArrayList<Integer> arr = new ArrayList<Integer>();
or
ArrayList<String> arr = new ArrayList<String>();
respectively.
There's a faster and easy way in Java 9 without involving much of code: Using Collection Factory methods:
List<String> list = List.of("first", "second", "third");
in the first you don't define the type that will be held and linked within your arraylist construct
this is the preferred method to do so, you define the type of list and the ide will handle the rest
in the third one you will better just define List for shorter code
I have a question about using generics with collections.
ArrayList<Integer> al=new ArrayList<Integer>();
We know that the above line means that ArrayList al is restricted to hold only integers. So the following line gives a compilation error:
al.add("wwww");
But I don't understand what the below line means,
ArrayList al=new ArrayList<Integer>();
Where we don't give ArrayList<Integer> at the left side while declaring. Now the following line doesn't give a compilation error:
al.add("wwww");
So if I declare like
ArrayList al=new ArrayList<Integer>();
that means a1 can accept any types?
What's the difference between those two declarations?
The latter declaration (without generic type) is obsolete and deprecated. You shouldn't use it, it compiles only for backward compatibility. Modern IDEs will generate warning here.
Also note that Java only enforces generic types at compile time, so technically you can add incorrect type to a collection with some extra casts. That's why it is better to stay with generics all the time and do not bypass them.
With this code:
ArrayList al = new ArrayList<Integer>();
a1.add("www");
the compiler will generate a warning (which you should heed!) but the code will run without error. The problem comes on extracting data from a1. If you "know" that it contains Integer values, you can just do this:
Integer val = (Integer) a1.get(index);
But when you hit the "www" element you're going to get a ClassCastException. Generics are meant to move such errors to compile time instead of forcing the poor developer to track down how a String value ended up in that Integer array list.
The latter declaration is basicly the same as:
ArrayList<Object> al=new ArrayList<Object>();
thus accepting any Object. It should not be used, and it is possible to use so that Java is backward compatible (pre Java1.5).
you should write like this ArrayList<Integer> al=new ArrayList<Integer>(); to avoid adding to your list objects with another types because you'll see the error compile time. Of course you can use ArrayList al=new ArrayList<Integer>(); but then you must be careful. In another words, always use the first one :D
Generics are implemented by type erasure: generic type information is present only at compile time, after which it is erased by the compiler. So, ArrayList al declaration let compiler accept any type. Here is java doc on this topic.
This kind of declaration is allowed for backward compability. So you can for example pass you generic list to the method from old-style library wich accepts only raw list:
List<Integer> list = new ArrayList<Integer>();
OldStyledClass.method(myArray);
where method is declared like:
public static void method(List list)...
In this case you have some special utility methods in java.util.Collections. So you can pass to this method protected list:
OldStyledClass.method(Collections.checkedList(myArray, Integer.class));
If method will try to put into your list object of some other type you will get ClassCastException immediatley.