When I do something like:
List<Integer> myList = new LinkedList<>();
Is the object "myList" of type List? I am more interested about the correct definition. Would it be correct to say that:
myLyst is of type List but its instance is of type LinkedList?
That doesn't make sense to me because the object can be only one type. So maybe it would be better to say that it is of type LinkedList but restricted to the interface List?
myList has a concrete runtime class, and that is LinkedList.
But LinkedList as a type, is a subtype of List, so it is also correct to say that myList is a List.
The thing that is definite at runtime is that an object has only one runtime class, which in this case is LinkedList. This class can be read by calling myList.getClass().
But checking type hierarchies, i.e., whether an object is an instance of a given type (class or interface), doesn't require that the type it's being checked against is a class. So:
myList instanceof LinkedList //true
myList instanceof List //true
myList instanceof Collection //true
myList instanceof ArrayList //false,
//because it's not an instance of ArrayList,
//and LinkedList is not a subtype of ArrayList
The LinkedList class implements the List interface. myList is an instance of the LinkedList class and is therefore of type LinkedList.
Since an interface is not a type, myList is not of type List, as List, an interface, is not a type.
I hope this answer should clear some things up?
Java List is an interface that extends Collection interface.Pic shows the hierarchy
Now, correct way would be, to say that "myList" is an interface variable currently holding the instance of LinkedList class.
You can look it from another analogy as well, interface is just an abstract representation therefore we can never create an object of type List thus it can only be used to hold reference of object of the class that implements it.
I would say that the static type of the variable is List and its runtime type is LinkedList.
This is obviously made possible by the fact that LinkedList implements List.
The distinction is important when discussing overriding (inheritance and virtual calls) and overloading (different methods with different parameters — parameters only take the static type into account)
Related
Can i storage all my inherited objects as ArrayList? I dont want to create new ArrayList for each object type something like:
ArrayList<MyObjectTypeA>
ArrayList<MyObjectTypeB>
ArrayList<MyObjectTypeC>
I know i can do:
ArrayList<Object>
Then cast it to valid object type, but maybe there is faster and more performanced method to do it like:
ArrayList<MyObject>
and cast it to valid object type, will i lose additional object type data or cast will bring it back to my type?
If MyObjectTypeA and the rest inherit from MyObject then you can indeed create an ArrayList<MyObject> and store all of them and the cast them back to the correct object type.
However, note that this is an antipattern and usually a smell of bad code. You should only be doing this if you want to use any type of MyObject. If you want to use a specific type then you should create different Lists.
Regardless, if you are going to go through with bundling them all together in one list, at least before doing any casting you should check if the object you are casting is actually an instance of the type you are casting to like so:
if (object instanceof MyObjectTypeA){
MyObjectTypeA typeA = (MyObjectTypeA) object;
} else if (object instanceof MyObjectTypeB) {
// etc.
}
Note that the process of casting does not change the object itself. That's why the correct naming is type casting. You essentially declare than an instance is of a specific type. This essentially "enables" the usage of the specific type's methods and members whereas previously they were there but they were not accessible because the compiler didn't know about them (since he thought the type of the object did not contain such members but inside the program memory it actually did).
As an example, if you try cheat like so:
MyObjectTypeA typeA = new MyObjectTypeA();
MyObject object = (MyObject) typeA;
MyObjectTypeB typeB = (MyObjectTypeB) object;
This will actually compile since the compiler knows that object can be of type MyObjectTypeB but it will warn you that you are doing an unchecked casting (not checking with instanceof like I showed earlier). That specific scenario, when reaching line 3 will throw a ClassCastException since the interpreter will attempt to cast object to MyObjectTypeB but will fail since object is of type MyObjectTypeB.
You can declare an arraylist of type base class and add to it objects of the inherited types.
ArrayList<BaseClass>
You need to clearly define your objects.
For example, if you have a Class A, and classes B and C inherit from A, then yes do the following:
ArrayList<A> temp= new ArrayList<A>;
Here you will be able to call the methods you would want using polymorphism.
You should also be aware of type-safety and type-casting. The object class is too generic.
Why not use a HashMap and store the Object as the value and the Key as the type?
HashMap<Type, Object> typeObjectMap = new HashMap<Type, Object>();
I'm working with superclass and subclass. My subclass extends the SuperClass this way:
public class SubClass extends LinkedList<SuperClass>
Does this mean that my subclass hold LinkedList properties. For example, if I'm creating objects of my subclass from other classes, am I able to do something like:
public class another {
private SubClass object;
public another(ArrayList<String> list) {
object = new SubClass();
SubClass localObject = object;
for (String elements : list) {
localObject.addAll(elements);
}
}
}
I want to add elements to end of the linked list.
Would this work? Or would I have to create add(), addAll() etc methods in the subclass in order for it to work?
SubClass inherits all the methods of LinkedList, but since it extends LinkedList<SuperClass> it can contain only objects of type SuperClass.
Your code at
for (String elements : list) {
localObject.addAll(elements);
has two problems.
The method addAll takes a Collection<? extends T>, which in your case is Collection<SuperClass> but you are passing in a single String.
Even if you modified it to pass in a collection of String it would still fail to compile. Only a Collection<SuperClass> is acceptable here.
If you changed it to
for (String element : list) {
localObject.add(element);
i.e. change to the add method instead of addAll, this is still wrong because the add() method in SubClass only takes objects of type SuperClass.
Jim Garrison is correct. But let me make it concrete.
The class called Float extends the class called Number
Integer is another class that also extends Number.
If you create a list of numbers (aka List<Number>) then you can put floating point numbers in that list, and you can put integers in that list.
The following code will compile cleanly.
List<Number> numberList = new LinkedList<Number>();
numberList.add(new Float(1.5));
numberList.add(new Integer(1));
You can not, however, add a potato to a list of numbers. Nor can you add a String, or any other type of object which is not a Number (or subclass of Number). The following code will generate the compile time error you cited.
list.add("this is a String.");
Getting back to your code now.
First let me say that when you extend List<SuperClass>, this gets you another List<SuperClass> with a different name, Subclass in this case. Which is to say SubClass is a list containing SuperClass objects. You could add some additional methods to your newly named class to differentiated it from List<SuperClass> but first and foremost it is just a list containing instances of SuperClass. I think you knew that already but I want to be clear.
Your method called another accepts an argument that is a list of strings (List<String>). So that means that every member of that list, is a String. But you are trying to pulls stuff out of that list (of strings) and then add it to a list of SuperClass. But the list of SuperClass can ONLY accept instances of SuperClass (whatever that is). So unless SuperClass happens to be a super class of String (and String only extends Object), then you will get an error.
I am writing some java code and I want to write methods in my main class Array. This class implements ImplementableClass. The former extends Iterable. The Array class has an type.
ImplementableClass.java:
public interface ImplementableClass<E> extends Iterable<E>{
public void insertObject(E obj);
public E removeObj(E obj);
}
Main.java:
public class Array<Integer> implements ImplementableClass<E>{
public void insertObject(E obj){
}
public E removeLastObject(E obj){
}
//... main method and others below...
}
I have some questions regarding the code in the two files above.
Reading the java documentation, Iterable is of type E (generic value). From what I understand, interfaces are just "blueprints" of the methods that MUST be used in the class that "implements" them. From a basic point of view, there shall not be any variables in here. With that being said, as you may see I am indeed declaring the methods in my ImplementableClass in Main as well. With that being said, I have a couple of questions:
When declaring my methods from ImplementableClass class in my Array class, this "overrides" the methods from my ImplementableClass class right?
Since "E obj" is the argument in both methods, do they have to be the same whenever I declare my methods in my Array class? What should I pass to the methods? What does "E obj" mean?
I want to create an array that can hold objects of type E. This means that whenever I instantiate a new object-> Array<Integer> theArray = new Array<Integer> I can call the methods I have on my Array class on theArray instance right? (i.e theArray.removeLastObject() ) What should I pass as an argument?
Why would Iterable<E> be of use in this case?
When declaring my methods from ImplementableClass class in my Array class, this "overrides" the methods from my ImplementableClass class right?
Yes (well, not technically since there's no functionality in an interface to override, but you can use #Override to indicate you're overriding it)
Since "E obj" is the argument in both methods, do they have to be the same whenever I declare my methods in my Array class? What should I pass to the methods? What does "E obj" mean?
They need to be the same as the generic type you've specified when you implement the interface. E obj means that you've declared a parameter called obj that is of generic type E. This means that you're required to define the methods to take that particular type as a parameter.
It would make more sense though, to define the generic type of your interface in the declaration, such as:
public class ArrayClass implements ImplementableClass<Integer>
so you can have methods like:
public void insertObject(Integer obj) {}
public Integer removeObj(Integer obj) {}
Or else you can make your Array class generic, and leave the specification of the generic type to the caller:
public class ArrayClass<E> implements ImplementableClass<E>
I want to create an array that can hold objects of type E. This means that whenever I instantiate a new object-> Array theArray = new Array I can call the methods I have on my Array class on theArray instance right? (i.e theArray.removeLastObject() ) What should I pass as an argument?
In order to do that, you would need to make your Array class generic, like shown above. The argument you pass in would be the same type you specify when you create the array (Integer in your example).
Why would Iterable be of use in this case?
Iterable is of use so you can make use of the iterator features of an array, and the enhanced foreach syntax (for (Object o : someObjectArray) {...})
Also, I would suggest not naming your Array class Array... and perhaps look at making use of already existing Iterable classes to construct what you're doing, but this looks like a learning exercise, so have at it.
HTH
What's actually happening is that you're implementing the interface, not overriding it. Since interfaces (in Java <= 7) don't have an implementation, there's nothing for you to really override. You can use the #Override annotation to indicate that you're implementing a method from an interface.
You whiffed on the generics in your second class. If you really want it to be generic (that is, it can be bound to any object), then you want this declaration:
public class Array<E> implements ImplementableClass<E>
That <E> is called a type parameter, and it's applied at the class level, meaning any non-static method or field in the class may make use of it.
E obj is stating that you are willing to accept whatever type of object comes in as an argument. If you declared Array<Integer> intArray = new Array<>();, then E obj would translate internally to Integer obj instead. There's a decent amount of complex operations related to generics; reading up on it would be best.
Be specific as to what kind of data structure you want to use. Arrays and generics do not mix well. If you're creating a generic object array (as in, E[] backingStore), then creating a generic array would be a consideration to take into account.
Honestly, I'd recommend you use a List instead.
Iterable means that the object you have can be iterated with an enhanced-for statement. Why you'd want to do this is subject to your discretion, but that's why you'd want to use that particular interface.
I have a strange (and maybe silly) question: I was wondering.... why is java "Object" class called "Object", not "Class"?
For example, for ArrayList whe have the following hierarchy
Object ->
Collection ->
List ->
ArrayList
Ok: ArrayList is a List... List is a Collection... but a Collection (the class of all collections) is not an Object... it is a class!
Think about what the object itself is. An ArrayList is a list, yes? It's also an object. It's not a class of object. The class name describes what instances of that class represent.
A collection isn't a class of collections - it's a collection (and it's an object).
Well, you use Object to declare an instance of a (not better specified) Object, same as you use Collection to declare an instance of a Collection.
You can declare an object of type Class too, with java.lang.Class<T>, where an instance of it represents the Class of the Object
Collection is an interface (effectively a special type of class).
A Collection is an object.
Your assumption is incorrect. The correct hiearchy for ArrayList is:
ArrayList -->
AbstractList -->
AbstractCollection -->
Object
So even ArrayList has Object as the first thing in its hierarchy.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why should the interface for a Java class be prefered?
In Java, is there a difference between these two lines? If so, what is it, and when should I use either one? Is there a preferred convention?
Note that ArrayList implements List.
List<String> bunchOfStrings = new ArrayList<String>();
ArrayList<String> bunchOfStrings = new ArrayList<String>();
In Java, is there a difference between these two lines?
Yes, there is a slight difference, and the List<String> variant is preferred.
Is there a preferred convention?
The convention says that you should "program against interfaces". The reason is that it becomes much easier to swap the actual implementation (in this case from ArrayList to say LinkedList).
In both case you are instantiating an ArrayList. The difference is that in the first case you are referring it as a List (the interface that ArrayList implements ), so you don't have access to specific method of ArrayList class, but only interfaces method.
use thi first:
List<String> bunchOfStrings = new ArrayList<String>();
This way you can switch different List implementation (ArrayList, Vector):
public class AClass(){
List<String> bunchOfStrings;
public List<String> getList(){
bunchOfStrings = new ArrayList<String>();
//or you can switch to : bunchOfStrings = new Vector<String>();
return bunchOfString;
}
}
You should use the most generic type possible. So in this case that's List. The only time you would use a more specific type is if that type had methods defined on it that the more generic type does not.
The reason is that if a method accepts a type, like List, the user of the method can provide any type of List they want. If a method only accepts an ArrayList, the user can't use any other type of List.
If you declare bunchOfStrings as a List, you can't call any of the ArrayList methods (without casting), even though it is pointing to an ArrayList object -- you can only call methods that are declared in the List class.
For this reason, you might think that it's better to always declare your variable type to be as specific as possible, but declaring it as a List is generally preferable because it allows you to change the underlying implementation of your List without having to change anything else in your code. You can easily modify your code as follows without breaking anything else in your code:
List<String> bunchOfStrings = new LinkedList<String>();
As a rule of thumb, only ever declare the type of your variable to be a specific subclass if you...
...need access to methods that are only available in the subclass.
...need to pass the object instance to a method that only accepts objects of that subclass.
This is called Polymorphism. It is very useful and has no real drawbacks.
Pros:
You can send this instance variable to any method that wants a "List" object.
Using List in a method declaration, you are opening up the method to anything that is a sub-type of List, instead of just of type ArrayList.
Cons:
You would have to cast your variable to an ArrayList to access or set any features/methods/fields that are in ArrayList (but not in List). But those things are still available.