This question already has answers here:
What is a raw type and why shouldn't we use it?
(16 answers)
Closed 6 years ago.
I was messing around with lists and got to this code (its a part of the main):
List l1 = new ArrayList<Object>();
List l2 = new ArrayList<String>();
Object t = "a";
l1.add("a");
l2.add(t);
System.out.println(l1.equals(l2));
System.out.println(l2.get(0));
The dynamic type of l2 is ArrayList(type:String) , but I managed to add an Object to it. Moreover, it said the lists are equal. I thought that maybe it casts it to String somehow, but then I tried:
Object t = 9;
And it still worked. Pretty sure it has something to do with the list being a raw type, but still, I can't understand how I can add an object to an ArrayList(type: String). Thanks in advance.
You are declare l2 as raw list. Thus you can add element of any type.
Regarding the equality of the l2 and l1 lists the documentation of equals method on the arraylist class says:
Compares the specified object with this list for equality. Returns
true if and only if the specified object is also a list, both lists
have the same size, and all corresponding pairs of elements in the two
lists are equal
.
The String class is a child of the Object class, so there is an inheritance of objects.
You should not use "equals" with inheritance.
More here : Why should I not use equals with inheritance?
The thing is, the object could be converted back to string, either through an explicit conversion (in this case I'd call it unboxing, like in C#), or by the Java analog of C#'s ToString() method. Either way, the object could successfully be converted to a string so the runtime doesn't complain.
If t was a number converted to an object, either you'd get an exception or you'd get a string representation of that number.
List equality must have been overridden to call the .equals method of the objects in each list.
Related
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.
This question already has answers here:
What is the difference between the HashMap and Map objects in Java?
(13 answers)
Closed 8 years ago.
I am trying to understand what is the difference between the below 2 lines of code.
I know for a reason that one is of the reference type List and the other of the reference type ArrayList. But does it really matter or is it just 2 different ways of doing the same thing ?
Its not only with these classes/interface but with others as well. I believe it is a Polymorphism feature of an object taking different forms is that correct ?
List a1 = new ArrayList();
ArrayList a1 = new ArrayList();
You don't declare objects, you declare variables (and members).
The difference in the interface you have to the object. In the first case, the interface is List, whereas in the second it's ArrayList. The underlying object is the same, but you have different access to it. In theory, ArrayList could have methods that List doesn't have (although in practice I don't think it does).
The advantage to using List is that you can change the underlying object to be a different kind of list (by changing what kind you create) without breaking your contract with any code that's using it. If you declare it as ArrayList, you have to change your contract if you want to change the underlying implementation.
Disclosure: This is an adapted form of my answer to this question. It's basically the same question, but you probably wouldn't find it when looking with the terms you were using. :-)
List a1 is an interface meaning that for example it can reference a LinkedList as well (doesn't restrict the implementation to ArrayList).
While ArrayList a1 can be only assigned ArrayList instances, which is a restriction you don't wish to have sometimes.
It is usually considered better approach to use interfaces (List, Map etc.) instead of concrete types especially if you expose methods to external apps, therefore you don't enforce implementation details. You just expect the variable a1 to behave as a List.
List is an interface, ArrayList implements that interface.
List a1 = new ArrayList();
a1 will be a List variable that contains an instance of the object ArrayList, the cast of the new ArrayList to List will be done implicitly.
It does have to do with inheritance/polymorphism. Think of it as similar to:
Animal dog1 = new Dog();
Dog dog2 = new Dog();
Both will let you perhaps .eat(), but only dog2 can .bark()
beware: non-experienced coder...
I have an arraylist (named a) of arraylists (named b). b is an arraylist of characters. When I try to get a single character from the b by doing
a.get(0).get(0);
it gives me an error saying I'm giving it a object, not a character.
Because the second get is returning an Object, the first get seems to return the ArrayList (or a List) properly. The most likely explanation is that you have a partially generic, partially raw ArrayList, presumably of the type ArrayList<ArrayList>. The generic type parameter ArrayList is itself a raw type, meaning it will return an Object upon a call to get. Another possibility is that you have an ArrayList<ArrayList<Object>>.
Fully specify the generic type, nesting generics all the way down to the scalar type.
ArrayList<ArrayList<Character>> a;
That is nature of generics. If you don't specify type of elements in your a list in your case using
List<List<Character>> a;
but instead you will use raw type
List a;
compiler can only assume that you are storing Objects so result of get() will also be assumed to be Object which doesn't have any get()
a.get(0).get(0)
//^-this method can't be invoked from reference of Object type
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.
I have this method getData as shown .
It is expecting an array of bag Objects as shown
please see the code below :
public static String getData(Bag[] bag)
{
}
public class Bag
{
public char side;
}
But , when i tried i am getting ClassCastException .
I have done this way :
Object bagArray[] = new Object[1];
Bag bagData = new Bag();
bagData.side = 'S';
bagArray[0]=bagData;
String bagData = ApplicationUtil.getData(Bag[]) bagArray);
Please let me , how to resolve this error ??
Why are you creating an Object array rather than an array of Bag objects?
Try just changing the first line to Bag[] bagArray = new Bag[1].
As an Object array can hold any kind of object, so I don't think it can be cast to a Bag array. You could however cast bagArray[0] to a Bag object.
In future, try using a List or other collection rather than an array for stuff like this.
The problem is that bagArray is an array of Object and not an array of Bag.
Either change that to Bag bagArray[] = new Bag [1]; or use a Collection (e.g. List) instead - note that you can cast List<Object> to List<Bag> but that is an unsafe operation and not recommended unless you know what you're doing.
You're trying to cast an Object[] into a Bag[]. Not allowed.
You bagArray is an Object array and not a Bag array. Just because it is capable of holding an object of type Bag (which is a subclass of Object), does not mean the vice versa. You are trying to cast Object to Bag type, which is not allowed. Define you bag array in the following way
Object bagArray[] = new Bag[];
See this question: Quick Java question: Casting an array of Objects into an array of my intended class
As others have said, you can't cast an Object[] to, well, anything. In this case, you have a Bag inside an Object array, so in this specific instance it seems like it might work. But imagine that you had a larger array, full of objects of different types. In that case, the cast wouldn't work. The program has to work for the general case.
You can solve this by:
1) Using a Bag[] type instead of Object[]
2) Using a List - collections are nearly always better
3) Using the Arrays class to create a new Bag[]: Arrays.copyOf(bagArray,bagArray.length,Bag[].class)