As per the below statement,
An array of subclass may be assigned to an array of its superclass. An array of implementing class may be assigned to an array of its interface type. Size is irrelevant.
I wrote below sample code to check the behavior of size in array
interface I{}
class C implements I{}
/* dummy.java*/
public class dummy{
public static void main(String[] args){
C[] c = new C[6];
I[] i = new I[2];
c[0] = new C();
c[1] = new C();
c[2] = new C();
c[3] = new C();
c[4] = new C();
c[5] = new C();
i = c;
System.out.println(i[5].getClass());
}
}
When i say, new C[6];, an object [null,null,null,null,null,null] gets created of type class [LC and c points to this object. When i say, new I[2];, an object [null,null] gets created of type class [LI and i points to this object.
My question:
How interface array is working here, when i say i[5], despite an object [null, null] being created after defining new I[2]? What exactly is happening when i say i = c;? Is size of array of interface new I[2]; getting modified during assignment i = c;?
What that quote is trying to say is that the size of an array is part of the object, ie. it is not part of the reference or the variable type.
In
i = c;
you are assigning a copy of the value of the reference held in c to i. That is, i will reference the same instance as c.
Is size of array of interface new I[2]; getting modified during assignment i=c;?
No, that's the whole point. i and c are just variables. Variable assignment has no side effects.
When you set
i=c
You are setting i to point to the object created by c. Therefore, i will now point to C[6]; < this array
So...
i[1] = new I();
c[1] will return a I object
Related
I have a question which I consider to be rather vague.
How many objects(instances) of class A are created by the following method:
void create() {
A a;
A b;
A[] s;
a = new A();
b = a;
s = new A[10];
}
class A { }
I am not sure how to count the array. We can easily see that the objects a and b are the same, but do we consider the array itself to be an object, or do we consider that it has 10 objects, which are null?
I thank you in advance!
s = new A[10] is an object of A[], it's not an object of class A.
Therefore, you don't count the 10 null references of the array.
only a = new A() is created.
I ran the above code through the Eclipse profiler and found that only one instance was created a = new A() which b also references. Hence there was only one instance created. The array of type A was not allocated as null until I assigned an object to the first index of the array. Hope this helps.
I am having difficulty understanding what an Object[] is. Is it an Array that keeps Objects ? For example what happens when we do this :
int a = 5;
String b = "Hi";
Object[] c = { a, b };
Did I just create an object with properties a and b added to it ? Or did I get an Object Array in which a and b was counted as objects and elements of this c the object array ?
Thanks.
Actually you created an array of objects derived from Object (which is true for all object in Java), now containing an Integer (created by autoboxing) on position 0, and a String on position 1.
Java is not dynamically typed so you cannot add properties on the fly like in javascript (without reflection). Btw. in java you dont call them properties, but instance-members/fields or methods if its a function, which are defined in classes (but you usually work with instances which is constructed from a class). So Object is a class and Object obj = new Object(); obj is an instance
The notation ClassName[] always notates an array of type ClassName, so
Object[]
notates an array of objects. And
String[]
an array that can only contain Strings.
You can initialize an array with
Object[] objArr = new Object[3];
which creates a new empty array which can hold 3 elements. Or you can directly set the elements by
Object[] objArr = {"elem1","elem2","elem3"};
which creates an array with 3 elements (elem1-3). So therefore:
System.out.println(objArr[0]); //"elem1"
System.out.println(objArr[1]); //"elem2"
System.out.println(objArr[2]); //"elem3"
System.out.println(objArr[3]); // ArrayIndexOutOfBoundsException
Because you used Objectas a type you can set practically anything to the array since any class automatically inherits from Object
Object[] objArr = {"elem1",2.34,new Date()};
System.out.println(objArr[0]); //"elem1"
System.out.println(objArr[1]); //2.34
System.out.println(objArr[2]); //11.05.2014
2.34 is a double, so a primitive, but since 1.4 java autoboxes every primitive into its Object pendant (so Double), thats why it works. Note that usually in a statically typed language you dont want to do that this way since you lose alle the advantages of statical type checks, so better define your types and use them.
Did I just create an object with properties a and b added to it ?
No. Those are elements. Properties != Elements.
did I get an Object Array in which a and b was counted as objects and elements of this c the object array ?
Little wrong. Counted as elements, which are objects.
Object[] c = { a, b }; // a is Integer and b is String
When you write the above line, that means you created an array Objects with elements a and b in it. You can refer the array with c
Is it an Array that keeps Objects ?
To be precise, it's an Object that contains references to other Objects.
All objects in Java are created and live on the heap until the garbage collector reclaims them. References point to those memory locations and give your program access.
The example you gave uses two immutable objects. The real fun would happen if you chose a mutable object and added it to your array.
On executing the program it will print,
5
Hi
on iterating the array. that shows the Object array consist of a of Integer and b of String.
It's an array of objects. You've auto-boxed a from a primitive int into an Integer and added that, and String b to the Object array. Remember all Objects extend Object. Try casting the Objects to their subclass types and maybe this will help you understand what's going on. E.G.
int a2 = (Integer) c[0];
String b2 = (String) c[1];
Object[] is an array of object references. From your code, imagine you did this:
int a = 5;
String b = "Hi";
Object o1 = a; // Autoboxes to java.lang.Integer
Object o2 = b;
Pretty similar to:
int a = 5;
String b = "Hi";
Object[] c = new Object[2];
c[0] = a;
c[1] = b;
... right? Which is exactly what your code above does, in a more shorthand way. So, you create an array where each element holds a reference to an Object.
Objects are superclasses of every non-primitive in Java. In your code:
int a = 5; // <- int is a primitive
String b = "Hi"; // <- String is a subclass of Object
Object[] c = { a, b };
c wants to have an array of Objects, and since a is an int, autoboxing occurs (this means that the compiler makes the int an Integer-object). You can compare it to the following code (this is basically what the compiler does behind the scenes).
int a = 5; // <- int is a primitive
String b = "Hi"; // <- String is a subclass of Object
Object[] c = { new Integer(a), b }; // <- int is autoboxed to it's container-class Integer
As I mentioned, Objects are the superclass of every non-primive in Java. So let's compare your code to the following:
I have three classes:
class C{ } // Just compare this with Object
class B extends C{ } // Compare this with String
class A extends C{ } // Compare this with Integer
// translating your code to:
A a = new A();
B b = new B();
C[] c = { a, b };
The left side is the reference type and the right side is the object type.
// List is the reference type, ArrayList is the object type
List<String> list = new ArrayList<String>(); // (or List<String> list = new ArrayList<>(); in Java 7+)
// With the C, B and A classes above:
// C is the reference type, A is the object type
C myClass = new A();
consider the code below :
class B
{
int j =100;
}
class A extends B
{
int i=10;
}
public class Test
{
public static void main(String[] args)
{
A obj =new A();
System.out.println(obj);
B obj1 =obj;
System.out.println(obj1); // here i am confused
if( obj1 instanceof A )
{
System.out.println("yes"); //here i am confused
}
}
}
here the output is :
A#35186a
A#35186a
yes
Now obj1 is an instance of class B which is superclass , so why does the toString() show it to be object of A ? Also how can instanceof operator show it to be instance of class A ?
You have to distinguish between the reference and the actual object.
B obj1 = obj;
Here you create a new reference of type B named obj1. The object referenced is still an A object though, this can never be changed.
obj1 is pointing at obj which is an instance of A (see the new A()) you have got there. On the left hand side you are just referencing the super class. Your obj1 will only be able to see methods in B. obj will be able to see all methods in B and A (subject to correct access)
From the java trail
Declaration: The code left of the = associates a variable name with an object type.
Instantiation: The new keyword is a Java operator that creates the object.
Initialization: The new operator is followed by a call to a constructor, which initializes the new object.
There isn't any toString method in your code, you print the memory place holders (Java don't allow you to see the exact location of the object in the memory).
When you do "extends" you say "A is a son of B",then in the lines:
A obj =new A();
System.out.println(obj);
You create an A object and print is memory place holder (remember, A is son of B, so if you want to describe it, imagine a box called A and a box called B connected to her (on top of her, because it's her father)).
Now in the next lines:
B obj1 =obj;
System.out.println(obj1); // here i am confused
You create another object called obj1 and you assign him the memory place holder of A so, it's the first object that you created, called obj. how can you assign A object to a B? Polymorphism!1 and again you print it's memory place holder.
Next you do if:
if( obj1 instanceof A ){
System.out.println("yes"); //here i am confused
}
So, obj1 is an instanceof of A (it's a box of A and on top of her is a box of B (it's father, polymorphism)), and you print "Yes".
In polymorphism you print the lowest method, so you print the A methods if there is any, and if there isn't you "climbing up" to the father and check there and so on..
Polymorphism (computer science)
Now obj1 is an instance of class B which is superclass
That is not true, obj1 is still an instance of A. You just happen to assign a pointer of the super class to an already existing pointer of class A.
If you want an instance of class B just do this:
B b = new B();
If you want an instance of class A you can do this:
A a1 = new A();
or
B a2 = new A();
The later, a2, is correct because A is of type B. However, a2 is still an instance of A, because we used new A().
class A {}
class B extends A {}
Hi, I'm learning Java and I'm trying to understand why this works:
A[] tab = new A[10];
tab[0] = new B();
and not this:
A[] tab = new B[10];
tab[0] = new A();
this line A[] tab = new B[10]; means that the compiler is booking 10 places for B in memory. tab[0] = new A() is setting tab[0] equal to a new A object that is smaller (?) than B (B extends A).
Why is there an ArrayStoreException: A error ? How does it work ?
You can store subclasses of an object, inside that object. ie B can be stored in A, but A is a superclass of type B. Basically, any class below class X in the inheritance chain can be referred to as type X, but any class above class X in the inheritance chain can NOT be referred to as type X.
Your example
A[] tab = new A[10]; // Perfectly fine. Equal objects.
tab[0] = new B(); // B is a subclass of A, so this is allowed.
A[] tab = new B[10]; // Same principle as above, B is a subclass of A
tab[0] = new A(); // A is a SUPERCLASS of B, so it can not be referred to as A
In short, X can only be referred to as Y, if X is a subclass of Y. (Or a subclass of a subclass. It's a recursive definition).
Let's use some English terms
Instead of A and B, let's have Item and Book.
public class Item {}
public class Book extends Item {}
Now, it makes sense to say:
Item b = new Book(); // All Books are items.
It does not make sense to say:
Book b = new Item(); // All items are definitely not books.
According to Documentation
Thrown to indicate that an attempt has been made to store the wrong
type of object into an array of objects. For example, the following
code generates an ArrayStoreException:
Object x[] = new String[3];
x[0] = new Integer(0);
"My Animal array will contain only Butterflies (A[] tab = new B[10];). Add a new Animal in the array (tab[0] = new A();)."
How to be sure the inserted Animal is a Butterfly?
Because if B extends A, B has ALL of the A characteristics (attributes, methods, etc), PLUS his own.
Then each B is also an A, while an A (that would lack the characteristics of B) is NOT a B.
This boils down to the most essential property of a hierarchical type system, which is the Liskov Substitution Principle: wherever an instance of A is allowed, an instance of any of its subtypes is also allowed. Arrays are no special case.
The thumb rule in java is superclass reference variable can point to sub class object and not vice versa, if you think about it , it makes sense that parent class can point to child class object. List list = new ArrayList()
Given:
class A { }
class B extends A { }
We have:
A [] a = new A [10]; // can store A or B objects
A [] b = new B [10]; // can only store B objects
After testing the code (see below), I found out that I don't understand some fundamentals.
Class A.
class A {
private String s;
private int[] array;
private B b;
public A(String s, int[] array, B b) {
this.s = s;
this.array = array;
this.b = b;
}
}
Class B.
class B {
public int t;
public B(int t) {
this.t = t;
}
}
I thought that any changes I did after A a = new A(s, array, b); would affect a. Don't all the fields of a and the variables s, array, b refer to the same object?
String s = "Lorem";
int array[] = new int[] {
10, 20, 30
};
B b = new B(12);
A a = new A(s, array, b);
s = "Dolor";
array = new int[] {
23
};
b = new B(777); // Initialized with a new value, a.b keeps the old one. Why?
System.out.println(a);
The output.
String Lorem
Array [10, 20, 30]
B 12
And about this.
B b2 = new B(89);
B b3 = b2;
System.out.println(b3);
b2 = null;
System.out.println(b3); // b2 initialized with null, b3 keeps the old one. Why?
The output.
89
89
However, if I have two lists, this shows that they both refer to same object.
ArrayList<String> first = new ArrayList<String>();
first.add("Ipsum");
ArrayList<String> second = new ArrayList<String>();
second = first;
first.add("The Earth");
System.out.println(second);
The output.
[Ipsum, The Earth]
The difference is assignment versus modification.
Assignment (=) makes the variable point to something else, so this won't change the underlying data. So any other variables pointing to the same data don't change.
Modification (pretty much anything except =) doesn't change what the variable points to, it just modifies the underlying object. So any other variables pointing to the same data do change.
For you example:
b = new B(777); is assignment, so only b is changed to point to something else. a.b won't change.
b2 = null; is assignment, so only b2 is changed to point to something else. b3 won't change.
If you were to say b2.t = 5, this would be modification (we're not assigning a new value to b2, we're modifying it by changing one of its members), so b3 will change as well.
I hope that explains it.
No. The thing is, you are not changing a, you are assigning a new value to s. S is a String, which are immutable, which means you can never make a change to the value of s. You can, however, change the reference in S, which is what you are doing.
To make yourself more clear try these lines of code..
String s = "Lorem";
int array[] = new int[] {10, 20, 30};
B b = new B(12);
//A a = new A(s, array, b);
s = "Dolor";
array = new int[] {23};
b = new B(777);
A a = new A(s, array, b);
System.out.println(a);
ArrayList<String> first = new ArrayList<String>();
first.add("Ipsum");
ArrayList<String> second = new ArrayList<String>();
second = first;
second.add("The Earth");
first.remove("The Earth");
System.out.println("second :"+second);
What are the current values the String s, array and the object b are holding while creating the instance of class A ( at the time of calling class A constructor ) will be printed. After creating class A instance, the String s, array and object b will be referred as a.s, a.array and so. If you assign a new value to s, array and b, it wont affect the class A instance.
And for the array list question, the two array lists will refer the same reference only. If you want different reference then do like this... (But always = assign operator will make same reference only )
ArrayList<String> first = new ArrayList<String>();
first.add("Ipsum");
ArrayList<String> second = new ArrayList<String>(first);
second.add("The Earth");
System.out.println("first :"+first);
System.out.println("second :"+second);
Thanks Dukeling for explaing how assignments works with objects and primitives, I am adding here to explain how the list works when operations performed on them.
When we consider the two array lists created in the above code in the question, both the variables first and second are pointing to the same array object that resides in the memory.
So when an add operation is performed the underlying object itself gets updated. So the print operation prints the second array list which pointed to the same array-list object created during the creation of first array-list.