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.
Related
The Java Language Specification says:
An object is a class instance or an array.
And it also says:
arrays [...] may be assigned to variables of type Object
But the part that confuses me is:
The class Object is a superclass of all other classes
If arrays may be assigned to variables of type Object, then it must mean that arrays can be Objects (not only behave as, but to be instead). Then it means that an array is a class instance, which does not seem to be consistent with the first quote (if it were, then why would it be listed as a different thing?).
How can all this fit together?
There is no contradiction.
An array is also an Object, albeit a special kind of Object.
It is like saying: An bird is also an animal, albeit a special kind of animal.
You can convince yourself by compiling and running the following Java code.
String[] arrayOfStrings = { "bla", "blah" };
// examine the class hierarchy of the array
System.out.println("arrayOfStrings is of type "
+ arrayOfStrings.getClass().getSimpleName()
+ " which extends from "
+ arrayOfStrings.getClass().getSuperclass().getSimpleName());
// assingning the array to a variable of type Object
Object object = arrayOfStrings;
The output will be
arrayOfStrings is of type String[] which extends from Object
Arrays are special classes provided to you by Java itself. All of them inherit from common superclass Object. As they inherit from Object they of course can be used anywhere where Object is expected. Instances of arrays are indeed instances of those classes. One can even reference array classes as they do with other classes' literals:
Class<int[]> intArrayClass = int[].class;
I see no conflict.
This can be useful https://docs.oracle.com/javase/specs/jls/se7/html/jls-10.html#jls-10.8
Yes... and no. It is true, indeed, that new Object[100] instanceof Object → true, but this is missing the true nature of arrays in Java. Arrays are objects (lowercase), but not Objects (capitalized). Being objects, for example, you have to use the new operator to allocate space for them.
However, the Java Language Specification is right to say that "An object is a class instance or an array", because arrays are fundamentally different from a regular Object. They are inherited from languages such as C++, that were much more deeply rooted in the low-level architecture of computers.
"arrays [...] may be assigned to variables of type Object" only because Java provides an interface for us, programmers, to refer to arrays as Objects. In fact, the JLS says:
All methods of class Object may be invoked on an array
Which of course is true, but it does not logically imply they are Objects. Arrays are not true Objects; therefore, they are not true class instances, and therefore the sentence "The class Object is a superclass of all other classes" doesn't apply here.
All in all, Java is not a pure Object-Oriented programming language (primitives are not objects, for example, but they are nonetheless present in Java). And arrays are a language feature that Java includes that behave as if they were class instances of the Object class, but are not actually class instances of it.
[This is my attempt at summarising the main points made here. Thanks a lot to all of you for your ideas, and feel free to add more!]
The class Object is a superclass of all other classes
All classes in Java extend Object. The class name is actually Object (proper name capitalized). It's why all classes have the method toString() and hashCode(), because they all inherited it from Object.class
An object is a class instance or an array.
An object (lowercase, not a proper name) is the instance generated by the new keyword. ie: File is a class and when you call new File() you just made a File object. I honestly think they should have called it a class instance. (clarification: I wish they never called an instance an object)
arrays [...] may be assigned to variables of type Object
Object[] is an array that can contain instances of type Object.
Object[] obj = new Object[100];
obj instanceof Object evaluates to true.
Your second link also says:
All methods of class Object may be invoked on an array.
So from a dev's POV, at least, it's an Object though there is no java.lang.Array (that is exposed to us) it has been instanced from.
A second indication is that arrays are also stored on the heap.
So it's only been few days that I touched on collection classes and stumbled upon a thing called "Iterator". And after few prying and poking I again stumbled upon docs.oracle.org and there I learned that Iterator is actually an interface and still we create it's object.
Iterator itr = myPrecious.iterator();
Is the "itr" not an object?? or am I missing something?? Wasn't it impossible to make object of an interface??
and what is that special thing
myPrecious.iterator(); ??
wasn't it
new Iterator(); to instantiate an object??
Edit : forgot to mention Javas is kinda my first programming language so forgive my stupidity.
Is the "itr" not an object??
It's a reference.
Wasn't it impossible to make object of an interface??
You can not instantiate an interface. Here, a parent type (Iterator) reference is referencing an object of child type.
and what is that special thing
myPrecious.iterator(); ??
Here iterator is a function in the class whose object is myPrecious. Check the definition of the function, iterator here for an example.
wasn't it
new Iterator(); to instantiate an object??
You can instantiate a non-abstract class using the keyword, new. You can instantiate an anonymous class by using new on the interface name as shown here for an example.
The point of an interface is:
You cannot directly create an instance of the interface, an object, you are correct.
A class may implement the interface. It declares that it implements the interface and it contains all the methods that the interface contains (unless it’s an abstract class, but then again you can’t create objects from it, so let’s forget this situation for now).
You may assign a reference to an instance (object) to a variable (or parameter) that is declared to have the interface type.
So to answer your questions:
Iterator itr = myPrecious.iterator();
Is the "itr" not an object?? …
myPrecious.iterator() returns a real object, and a reference to the object is stored into itr. The object probably belongs to some class that we haven’t heard of and do not need to care about. All that we know is that that class implements the Iterator interface. This means that we can use the iterator as specified by that interface.
wasn't it
new Iterator(); to instantiate an object??
Good question. Answer: In the end it is. However, very often in real-world programming we are calling an ordinary method in order to get a new object. That method must in turn use new. Or call another method that uses new (etc.). And this is where things go nicely hand in hand: since we don’t know the actual class of the object, we cannot use new ourselves. But myPrecious, your collection object, does know the class to use for instantiating an iterator object, so it can use new for us. And return the created iterator object to us.
One way to check is through this little code experiment:
List<String> myList = new ArrayList<>();
Iterator itr = myList.iterator();
System.out.println(itr.getClass());
On my Java 11 it prints:
class java.util.ArrayList$Itr
Output on other java versions may be different. You notice that the output doesn’t mention the Iterator interface as the class of the iterator object, but instead some ArrayList$Itr. This means a class named Itr declared inside the ArrayList class. So yes, the iterator is really an object belonging to a class.
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)
What is the difference between
Collection c = new ArrayList();
And
ArrayList c = new ArrayList();
They seem to be both of type ArrayList and thus able to invoke the same methods.
A Collection is an interface that defines the highest-level of shared collection behavior, and extends Iterable (which just defines the iterator() method).
A List is an interface that defines the highest-level of shared List behavior.
ArrayList is an implementation of List and in general wouldn't be used in a declaration unless you need an implementation guarantee (e.g., fast indexed access), but is fine to use as a list value.
Read the docs to see the differences–they're described in the API. The implementation (ArrayList) will have a type-specific implementation of each method in each interface it implements.
In the second case you can call methods on c that are specific to ArrayList as c is declared as type ArrayList.
In the first case, you can only call methods that are defined for Collection (and must also be in ArrayList).
For example, ArrayList declares functions that use indexes (such as get and indexOf) but Collection does not have them.
Is there a way to subclass the ArrayList class to only allow objects of a specific class (or subclass thereof).
Specifically, I have a base class called RecordStatus and I need to create ArrayLists with objects based on this class.
I know it would be easy to create a class based on ArrayList<RecordStatus> but then, every time I retrieve an element from the array, I need to cast it to the original class.
Is there an easier way to do this?
Is there a way to subclass the ArrayList class to only allow objects
of a specific class (or subclass thereof). Specifically, I have a base
class called RecordStatus and I need to create ArrayLists with objects
based on this class.
That's exactly what the generic construct in Java allows you to do. Note that you don't have to cast the instances coming out of your ArrayList<RecordStatus> as long as all subclasses of RecordStatus have the same API. You only have to do that if the subclasses have different methods/fields. For example, if RecordStatus has a method setStatus, and so does a subclass, no casting is necessary, as the dynamic dispatch of Java's polymorphism will make sure the method that gets implemented is correct based on the type of the instance on which the method is invoked at runtime.
You shouldn't need to cast anything if you set up your types correctly. For example, this should work:
List<RecordStatus> myList = new ArrayList<RecordStatus>();
//Add values to the list
RecordStatus myRecordStatus = myList.get(0);
But if you really want to subclass ArrayList, you can do the following:
private class MyArrayList<R extends RecordStatus> extends ArrayList<R> {
...
}
ArrayList<? extends RecordStatus> is as close as you can get.
I've created arrayList without troubles using a line like this
List<RecordStatus> list = new ArrayList<RecordStatus>();
Try Collections.checkedList(List<E> list, Class<E> type). This will ensure the Type-Safety.