What does "Object" mean in E[] temp = (E[]) new Object[capacity] - java

I'm look at dynamic arrays and I'm not sure what "Object" means for
protected void resize (int capacity) {
E[] temp = (E[]) new Object[capacity];
for (int k = 0; k < size; k++) {
temp[k] = data[k];
data = temp;
}
Cheers!

Every class has Object as a superclass, i.e. even if you write something like:
class A {}
then A implicitly extends Object. Because of this we can use variables of type Object to store any type:
Object x = new SomeClass();
and then to cast to the type we need when reading:
SomeClass someClass = (SomeClass) x;
Now, since we can not construct generic arrays, i.e. we can't do new T[], the only solution is to construct an "universal" (that can contain any type) array new Object[] and then to cast to the type wee need.

Its the root object that everything else derives from :
https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html
Most IDE's enable you to click through and see the implmentation (ie ctrl+click on Object, and it will take you to its definition).
A new array of objects is being created, then casted (which is lame).

Object is the root of all classes in Java. In this case it is just being used to allocate memory for the references of whatever objects are stored in that array. You can store any type of Object in that array and cast it to another type at runtime like (MyClass) temp[3];

Since all objects extend Object this is just creating an array that can hold anything, so we copy all the contents of "data" one by one, and it doesn't matter what type they are since each item will definitely extend Object. Since you can't instantiate generic types (ie. new E[]()) you must use a type you can instantiate and cast to the generic - we can instantiate Object and cast to E safely.

"Object" means the Object class. In java, all other classes in inherit from the Object class. So, here you are declaring an array of any java type.

Related

Java - Why declare an array as a type of Interface?

This is from Professor Mark Weiss in his book Data Structures and Algorithm Analysis in Java
public class BinaryHeap<AnyType extends Comparable<? super AnyType>>{
private void enlargeArray( int newSize ){
AnyType [] old = array;
array = (AnyType []) new Comparable[ newSize ];
for( int i = 0; i < old.length; i++ )
array[ i ] = old[ i ];
}
}
I was wondering why do we declare an array with a type of interface Comparable since we have to convert the Comparable[] to an AnyType[]? Any design philosophy in there?
The design "philosophy" is that you can't instantiate an array of a type parameter, so you have to instantiate the array with a type that is legal. The only available legal types known to the method are array of Object or of Comparable, and the latter captures more knowledge about the type.
You are allowed to downcast to an array of the type parameter, and the return type has to be that, so downcasting is required.
It's the "philosophy" of necessity.
AnyType I believe is a generic. In Java you can't create an array of generics. As a workaround for this, he has instantiated an array of Comparables (an interface) and then type-casted it to an array of generics.
If you look at this "how to create an array of generics" question, one person offers initializing an array of Objects and then type-casting to an array of the desired generic.

Generic list conversion to an array

Assuming that I have the following class
public class A <T>{
private T [] datas;
// more code here ...
}
And I desire to take advantage of the constructor to initialize the array. Suppose that I have the following constructor
public A(T element){....}
Java does not allow me to use something like
datas = new T[10]
And it will complain that I cannot create a generic array of T
But I can still use a work around like:
#SuppressWarnings("unchecked")
public A(T element){
List<T> datasList = new ArrayList<T>();
datasList.add(element);
datas =(T[]) datasList.toArray();
}
I have a warning from the compiler that's why I had to add the #SuppressWarnings, but my point is related to the following comment from the toArray method documentation (Please take a look at the picture)
It talks about the returned array being safe. So does that means it is safe to use this method? If not why? And what would be a better way to do such an initialisation in a constructor? I would like to also consider the case of a variable list of T elements in an overloaded constructor like
public A(T... elements){....}.
You can create an instance of a generic array using the following:
public A(T element){
int length = 10;
datas = (T[])Array.newInstance(element.getClass(), length);
}
However, there's a problem if element would be a subclass of T, e.g. if you'd call it like this:
A<Number> numberA = new A<>( Integer.valueOf(1) );
Here T would be Number but the class of element would be Integer.
To mitigate that you could pass a vararg array of type T, e.g. like this:
//firstElement only exists to force the caller to provide at least one element
//if you don't want this then just use the varargs array
A(T firstElement, T... furtherElements){
int length = 10;
Class<?> elementClass = furtherElements.getClass().getComponentType();
datas = (T[])Array.newInstance( elementClass, length);
}
Since varargs always result in an array (even of length 0) you'll get an array of type T and can get the component type of that.
So in the case above numberA.datas would be a Number[] array and not an Integer[] array.
You can pass generics, but you can't call new T (or new T[ ]).
Keep in mind that generics are gone after compilation, so it actually only helps when writing the code. Knowing it's gone during runtime, it's also obvious that new T( ) can't be called as generic, T is removed in runtime.
It's safe to do, because you create that list in full control, accepting only objects of your generic type.
A nicer way (imho) is to create a static method as it is purely input-->output. You have to declare your generics before the method return type:
public < T > T[ ] toArray(T... objects) { ... }

What is the Use of TypeCasting in java

we can achieve the output in two ways one is typecasting and one is without typecasting
A a=new B() // without typecaste
A a = (A)a// with Typecaste
in both ways we get same output.so, what is the use of typecasting
Let's assume that you have a list of Animals. and you have Tigers and Lions in it.
ArrayList<Animal> animals = new ArrayList<>();
//add some Tigers and some Lions
//sort so Tigers are at the beggining of the list
Tiger t = (Tiger)animals.get(0);
Without casting you will get type missmatch at compile time. With a cast you only risk ClassCastException which can be easy caught with a try-catch
It's just an example of a proper use of class casting in Java.
Casting is for "the opposite direction", i.e. for converting to a expression of a subtype of the original expression.
Example
Given
Object o = "Hello World";
String s = o;
does not compile, but
String s = (String) o;
compiles. This may yield a ClassCastException however, e.g. if a Integer was stored in o.
Casting has different uses. Unfortunately, your example doesn't exercise any useful example of casting since you create an instance of A (a) then cast it to an A.
What you need to understand is there are apparent types and actual types. An apparent type would be List<T> list;. Here we see that it's a list. But the actual type might be an ArrayList<T> (List<T> list = new ArrayList<>();). In this scenario we can, with care, cast the apparent type to the actual type. This would allow us to then use the functionality of the actual type. For example, let's look at some code; given:
List<Integer> list = new ArrayList<>();
ArrayList<Integer> aList;
LinkedList<Integer> lList = new LinkedList<>();
We can do this without issue (although dangerous in general)...
// Dangerous but OK with a cast
// list might not be an ArrayList
aList = (ArrayList<Integer>) list;
// Use ArrayList methods
aList.trimToSize();
list = lList;
LinkedList<Integer> danger = (LinkedList<Integer>) list;
...but it's also possible to do:
aList = (ArrayList<Integer) list;
// Use ArrayList methods
aList.trimToSize();
// list = lList;
LinkedList<Integer> danger = (LinkedList<Integer>) list;
The last snippet results in a ClassCastException because list isn't a LinkedList.
Casting goes beyond that though. Consider when you have two integers you want to divide. Without a cast you could end up with an integer result where a floating point is more appropriate. Consider:
int i = 2;
int j = 3;
System.out.println("No cast: " + i/j + " ;With cast: " + (double)i/j);
Output:
No cast: 0 ;With cast: 0.6666666666666666
So, it depends on the use case.
A a = new B();
will only works if B inherit from A.
If B inherit from A, the type cast is not required as B is a A. Type cast will be necessary if you need to type cast to a subclass:
A a = new B();
B b = (B) a;
While this would be illegal :
A a = new A();
B b = (B) a;
as a is not a B.
Java implicitly upcast with assignment, so in the code you've provided the casting operator is redundant; a is already of type A:
A a = new B(); // without typecast operator (implicit upcast)
A a = (A)a; // with redundant typecast operator
One reason to have a casting operator is that you may also wish to downcast (which is not done implicitly in Java). For instance, when a is a type A reference to an object of class B (e.g. when B is a subclass of A) one may need to downcast to access certain methods:
A a = new B(); // implicit upcast
C c = ((B)a).methodOfBOnly(); // explicit downcast
You may also want to check this question on why Java doesn't do implicit downcasting.
There can be times when upcasting needs to be done explicitly as well. For instance, if a class contains overloaded methods
C method(A x){/*does one thing*/}
C method(B x){/*does another*/}
and assuming b is of type B, the calls to method((A)b) and method(b) would behave differently.
A a=new B()
is applicable only when class B extends class A. In this way the extra methods that are available in class B other than class A will be available with reference a.
When you do this
A a = (A)a
Then actually you are down casting the object of class B into an object of class A. And it is true that child can be type cast to parent. After this statement the reference a will not be able to call any method of class B which were not in class A because now the reference a points to an object of class A.
It is useful in many scenarios.
For example, you want to have a collection of Objects that point to same base class. Instead of maintaining separate collections for each sub class, you maintain a single collection of base class. And then when you want to use any child object you type cast the base class object to child class object to do that.
ArrayList<Base> children = new ArrayList<Base>();
children.add(new Child1());
children.add(new Child2());
Console.WriteLine(((Child1)children.get(0)).getChildName());
Console.WriteLine(((Child2)children.get(1)).getChildName());
Now base class does not have any method named getChild1Name or getChild2Name. And you need to typecast object of base class to respective child class to do that.

Generic Types & the toArrayMethod

I have a class MyStack<T> which defines the following
public T[] toArray(){
int s=size();
#SuppressWarnings("unchecked")
T[] result=(T[])new Object[s];
Node n=first;
for (int i=0; i<s; i++){
result[i]=n.data;
n=n.next;
}
return result;
}
Since this returns an array of type T, I would think that if I declared this instance: MyStack<String> s=new MyStack<>, that the following would be perfectly valid: String[] test=s.toArray(). I think this because since s is of type String, toArray should return an array of type String, since String has basically been substituted in for every T in this class (only for this particular instantiation, I know). The only way this runs without errors is if I do this: Object[] test=s.toArray().
Why is this?
In a word, type erasure. Taken from the Java website:
Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.
What this means is that, when your code is compiled, MyStack<String> is compiled into MyStack<Object>. This is to make sure that generics do not incur an overhead by needing to create new classes. How does this apply to you? Well..
MyStack<String> s = new MyStack<>();
is converted into..
MyStack<Object> s = new MyStack<>();
Now, this means that when you call the toArray method, the only type that can be guarenteed is the Object type. The compiler can't be sure that everything it returns is of type String, so it won't let you treat it as a String, due to the strong typing in Java. So, what is the only variable type left?
Object[] array = s.toArray();
Extra Reading
Type Erasure in Java.
Well, hold on a minute. Suppose your hypothesis were correct that String were substituted for every T.
Would the following cast be valid?
String[] result = (String[])new Object[s];
No, it would not. We can be sure that a new Object[] is not a String[].
Now sometimes you will see something like (T[])new Object[n] but it only works because the cast actually becomes erased inside the generic class. (It is a deceptive idiom.)
When the class gets compiled, what actually happens is that references to T are replaced with its upper bound (probably Object unless you had something like <T extends ...>):
public Object[] toArray(){
int s=size();
Object[] result=new Object[s];
Node n=first;
for (int i=0; i<s; i++){
result[i]=n.data;
n=n.next;
}
return result;
}
And the cast is moved to the call site:
MyStack stack = new MyStack();
String[] arr = (String[])stack.toArray();
So in fact, while the cast is erased inside the class, the cast does happen once the value is returned to outside the class, where ClassCastException is thrown.
The inability to instantiate arrays (and objects in general) generically is why the Collections framework defines their toArray method to take the return array as an argument. A simple version of this for you would be like the following:
public T[] toArray(T[] inArray){
int s = size();
Node n = first;
for (int i = 0; i < s; i++){
inArray[i] = n.data;
n = n.next;
}
return inArray;
}
For some ideas on how to create an array generically, you may see 'How to create a generic array in Java?'; however you will need the caller to pass some argument to the method.

Couple java questions regarding type casting and inheritance

Hello I have a few questions regarding type casting and inheritance. I have been doing some reading and I understand the point and basics of type casting. However, I don't fully understand where I can and can't use it.
Consider this class:
class A{
public A(){}
}
A temp = new A();
temp = (Object)temp;
This code gives me the error "Cannot convert from type Object to type A". However, wouldn't this be converting from type A to type Object? Can you not type cast up the hierarchy?
Now my second question regards inheritance and such.
When you type:
Object temp = new A();
what is really happening? Is temp an A or is it an Object?
Here the excerpt from JLS 8.1.3:
If the class declaration for any other
class has no extends clause, then the
class has the class Object as its
implicit direct superclass.
Of course, Object itself is a bit special (JLS):
Each class except Object is an
extension of (that is, a subclass of)
a single existing class (§8.1.3) and
may implement interfaces (§8.1.4).
Every Class is a descendant of Object.
In your case, you are trying store an object of A into a Class object called A. This isn't going to work. You need to do:
Object testObject = (Object)temp;
This will store the Object into testObject, which has the type Object that you casted to.
Here it is working on ideone.
It's just because you can't assign superclass object to the subclass reference.
So you can't do:
temp = (Object)temp;
because it's the same as:
Object newObject = new Object();
A temp = newObject;
You will get the same compile error here.
Of course you can do something like that:
Object newObject = new Object;
A temp = new A();
newObject = temp;
You can do it because you can assign subclass to the superclass reference
The problem is in the last line. First you promise Java that temp is of type Object by the statement:
(Object) temp
Afterwards you try to assign an object that the compiler thinks is of type Object to a variable that should be of type A. So to conclude, the part where you cast temp to type Object is fine, the problem is when you afterwards try to assign it to a variable expecting something of type A.
For your second question, temp is an A. When creating an object with the new keyword, the type of the object will always be whatever comes right after. In your case A. Afterwards you then assign temp to a variable of type Object, but that does not change the actual type of temp. Having a variable of some type X just tells you that whatever the variable is pointing to is a subtype of X.
A a = (Object)temp;
"Cannot convert from type Object to type A". However, wouldn't this be converting from type A to type Object? Can you not type cast up the hierarchy?
You are correct that
(Object)temp;
is converting temp, which is an A to an Object. However, that's not what the compiler is complaining about. Now that you have, effectively,
A a = anObjectNOTAnA
(A = ... is invalid code. I've changed it to A a = ....)
It's saying that you cannot convert an Object back to an A, unless you explicitely cast it and potentially suppress the unchecked-cast warning:
A a = (A)anObjectNOTAnA
or
#SuppressWarnings("unchecked")
A a = (A)anObjectNOTAnA
Regarding your other question:
Object temp = new A();
What is really happening? Is temp an A or is it an Object?
When you cast an object of any type, it never changes the actual type of the underlying object. A new A() is always an A, whether its
A a = new A();
or
Object objButReallyA = new A();
or
#SuppressWarnings("unchecked")
A a = (A)((Object)new A());
If an A is stored in an Object, it's just a different "view" of the same object. In order to use the A specific functions, however, you must first revert it back to the A view:
objButReallyA.getAOnlyField(); //compile error
((A)objButReallyA).getAOnlyField(); //Okay

Categories