String array instance assigned to single Object - java

I came across this Java question:
Which one of the following declaration is false:
a. Object[] myarr1 = new String[3];
b. Object myarr2 = new String[3];
c. String[] myarr3 = new String[3];
d. String myarr3[] = new String[3];
I thought it seems obvious that b is the answer. However, the declaration in b is actually correct upon my checking in Eclipse!
Furthermore, I tried the following:
A. Object[] myarr1 = new String[]{"a1","b1","c1"};
B. Object myarr2 = new String[]{"a2","b2","c2"};
C. String[] myarr3 = new String[]{"a3","b3","c3"};
and printed out the content of each array to study what it actually means by assigning an Object to a String array.
System.out.println(myarr1[0]); //print "a1"
System.out.println(myarr2[0]); //error
System.out.println(myarr3[0]); //print "a3"
System.out.println(myarr1); //print address of myarr1
System.out.println(myarr2); //print address of myarr2
System.out.println(myarr3); //print address of myarr3
It seems myarr1 and myarr3 behave like ordinary String arrays, while myarr2 is different. Debugging to look into the content of myarr2 however showed that the content and structure of myarr2 seems to be the same as myarr1 and myarr3.
Can someone explain to me the significance of this? What are we doing when we use declaration b or B. What is the structure of myarr2 and how do I access its elements or cast it as if it is a String array? I tried (String[])myarr2 but that was an error.
Thanks to all.

They all compile, so they are all correct, as of Java 6.
b. Object myarr2 = new String[3];
This works, because everything you create with the new operator is an object in Java. You could later cast it back to its real type, for example these will work as expected:
Object myarr2 = new String[] { "first", "second" };
String[] real = (String[]) myarr2;
real[1] = "hello";
System.out.println(real[1]); // will output "hello"
System.out.println(((String[])myarr2)[1]); // will output "hello"
d. String myarr3[] = new String[3];
This is valid but discouraged as per this doc:
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html

The reason your second print statement emits an error is because the compiler does not know what myarr2 actually is, it just knows it's an Object. For example, you could have had:
Object myarr2 = rand() ? new String[3] : new Dog();
i.e. myarr2 could be some other completely unrelated object as well.
Hence, you cannot index myarr2 as an array. Of course, this can be addressed with a cast:
System.out.println(((String[])myarr2)[0]);

Related

How is String arr = new String[] not possible in Java

i have trouble understand reference types in Java. So in C++ if we wanna allocate some 1D array dynamicly or single object all we do is:
int *a = new int();
int *a = new int[];
But in Java pointers are not avaliable to programers, references are introduced as some type of pointers but without possibilty of arithemtic operation on the value they hold(point?).
As far as i know every non-primitive data type in Java is of type reference :
String obj; //reference
obj = new String();
And if wanna allocate it something we gotta allocate it on heap, and the obj will hold the adress of that object on heap. So in C++ it would be like :
String *obj = new String();
But for the array we gotta do :
String[] obj = new String[];
And I dont understand why exactly? If obj is already of reference type(simple *ptr) why cant we just do :
String obj = new String[];
How does this exactly work in Java?
Is String[] obj actualy **ptr in C++ or am i missing something?
The reason why you can't write
String obj = new String[];
is that the left-hand side and right-hand side have different types. That's all there is to it. An array of Strings is not a String. A reference to an array of Strings is not a reference to a String.
Maybe more fundamentally, Java is not C++.

How does using add() to one ArrayList interfere the size of the other one?

I created two ArrayList and I want to add some Integers to ArrayList a.
In Java code I did this:
ArrayList < Integer > a = new ArrayList < Integer >();
ArrayList b = a;
a.add(new Integer(4));
b.add(new Integer(5));
a.add(new Integer(6));
a.add(new Integer(7));
System.out.println(a.size());
My quesiton is why does b.add(new Integer(5));also add one object to ArrayList a?
Consider the following image where the illustration is given with Date objects. A variable declaration such as ArrayList<Integer> a creates a reference which is then assigned the adress of the object created by the right part of the statement new ArrayList < Integer >();with the help of the assignment operator =
Now when you declare ArrayList b=ayour are stating that the 2nd reference called b is assigned the same adress as the first reference a. Therefore a and b both refer to the same object in memory
The problem is that a and b are pointing to the same object.
You are confusing primitive values with object references. When you run something like this:
int a = 10;
int b = a;
a = 15;
System.out.println("a = " + a);
System.out.println("b = " + b);
The output will be:
a = 15
b = 10;
When you use a primitive (int, String, long, byte, double, boolean, short...), you are COPYING the value of that variable into another, like in the example above. b looks at the value of a, and assigns it to b creating two separate variables.
What you did with ArrayLists, on the other hand, since they are OBJECTS, both a and b are pointing to the same thing. If you want to create separate objects, you would need to do:
ArrayList<Integer> a = new ArrayList<Integer>();
ArrayList<Integer> b = new ArrayList<Integer>();
Then you would get the results you want.
Hope this helps. =)
ArrayList b = a;
From here both a and b point the same memory. So both the objects having same values.
a = new ArrayList<>(); a points to an object (an ArrayList instance) at memory address 0x1234 (the address is made up).
b = a; b points to the same address as a points to.
So every operation on a or b affects the same object in memory. Hence b.add(new Integer(5)) has the same result as a.add(new Integer(5))
ArrayList b is a reference to ArrayList a. There is really only one list with two pointers to it.
Arraylist b is referencing arraylist a. If you want the split, look up java's clone() method.
When you pass value of a to b. You actually the pass the value of the reference to the object. which means that a and b are pointing to the array.
Explaining the code as is:
ArrayList b = a;
on this line you create a variable able to hold an ArrayList, and you make this b variable you just created point at a which is another variable able to hold an ArrayList.
a points on an Arraylist object (the new ArrayList you created on line one).
This does not mean that after line two you have two ArrayLists. There only exist one ArrayList object and two variables that point to the memory this object is stored.
So by calling the add method on any of the variables a or b you add on the same ArrayList.

Java Object class MYSTERY

While Porting a Game I come to a below statement
Object o = new Object[]{"A","B"};
It's really weird!
But when I try the same with "String" then compiler report me an Error msg
String s = new String[] {"A", "B", "C"}; Error: Type mismatch:
cannot convert from String[] to String
Can you please reveal the Mystery of it ?
You have a trivial error in your code. The fact that every class extends Object makes the error more difficult to find.
Since every class (including arrays) extends Object, conversion from A[] to Object is possible.
You wrote int i = new int[] but that's a mistake, you should have written int[] i.
Probably. Object a = new Object[] is not what you wanted to do.
In Java, Array is an Object too. So you can do
Object o = new Object[]{"A","B"};
or
Object o = new String[]{"A","B"};// But array of String not a String
or
Object o = new int[]{1,2};// But array of int not an int
An "Array" of objects is also an object. But an "Array" of ints is NOT an int.
i.e, an int reference cannot point to an Array but an object reference can.
Object[] obj = new Object[5];// works fine
An object can be anything. It can be an array, it can be an single variable.
Object O = new Object[]{"S","A"};
When you define object you can type cast it to your desired data type.
You can not assign an array of a data type to a single variable of that 'same' datatype.
Every array is an Object[] AND an Object, that's why the following are equally valid:
Object[] o = new Object[]{"A","B"};
Object o = new Object[]{"A","B"};
However a String[] is not a String (and vice-versa) and a int[] is not a int (and vice-versa).
Indeed, you would blend primitives with objects in this latter case.

Nameless variable declaration - why does it work?

I am surprised to see this behaviour.
Is it a bug or something?
for(Object obj = new Object(), Integer = new Integer(300);
obj.toString().length()>3;
System.out.println("on object's loop")) {
} //causes an infinite loop (not foreach loop, of course)
above code compiles and run fine without any reference to new Integer(300). Why so?
I am only interested in knowing why Integer = new Integer(300); is okay without any reference.
Object obj = new Object(), Integer = new Integer(300);
This creates two variables:
obj of type Object, which gets assigned to new Object().
Integer (yes, that's the name of the variable) also of type Object, which gets assigned to new Integer(300).
By the way this has nothing to do with the for-loop; that line would compile fine on its own. Now, if that , was really a ;, it would be a different story.
In general, we can construct valid statements of the form:
Type t1 = ..., t2 = ..., t3 = ..., ...;
which is equivalent to
Type t1 = ...;
Type t2 = ...;
Type t3 = ...;
...
I think he's asking why Integer = new Integer(300) works. – arshajii 2 mins ago
Integer is valid identifier name and its type is Object because of
Object obj = new Object(), Integer = new Integer(300);
Which is equivalent to
int a=2, b=4;
obj.toString() prints the String (consisting classname and hashcode), which has length > 3 so the infinite loop
String String = "foo";
System.out.println(new String(String));
is also legal - the compiler is clever enough to figure out which is a variable reference and which is not.

Creating an array of objects in Java

I am new to Java and for the time created an array of objects in Java.
I have a class A for example -
A[] arr = new A[4];
But this is only creating pointers (references) to A and not 4 objects. Is this correct? I see that when I try to access functions/variables in the objects created I get a null pointer exception.
To be able to manipulate/access the objects I had to do this:
A[] arr = new A[4];
for (int i = 0; i < 4; i++) {
arr[i] = new A();
}
Is this correct or am I doing something wrong? If this is correct its really odd.
EDIT: I find this odd because in C++ you just say new A[4] and it creates the four objects.
This is correct.
A[] a = new A[4];
...creates 4 A references, similar to doing this:
A a1;
A a2;
A a3;
A a4;
Now you couldn't do a1.someMethod() without allocating a1 like this:
a1 = new A();
Similarly, with the array you need to do this:
a[0] = new A();
...before using it.
This is correct. You can also do :
A[] a = new A[] { new A("args"), new A("other args"), .. };
This syntax can also be used to create and initialize an array anywhere, such as in a method argument:
someMethod( new A[] { new A("args"), new A("other args"), . . } )
Yes, it creates only references, which are set to their default value null. That is why you get a NullPointerException You need to create objects separately and assign the reference. There are 3 steps to create arrays in Java -
Declaration – In this step, we specify the data type and the dimensions of the array that we are going to create. But remember, we don't mention the sizes of dimensions yet. They are left empty.
Instantiation – In this step, we create the array, or allocate memory for the array, using the new keyword. It is in this step that we mention the sizes of the array dimensions.
Initialization – The array is always initialized to the data type’s default value. But we can make our own initializations.
Declaring Arrays In Java
This is how we declare a one-dimensional array in Java –
int[] array;
int array[];
Oracle recommends that you use the former syntax for declaring arrays.
Here are some other examples of legal declarations –
// One Dimensional Arrays
int[] intArray; // Good
double[] doubleArray;
// One Dimensional Arrays
byte byteArray[]; // Ugly!
long longArray[];
// Two Dimensional Arrays
int[][] int2DArray; // Good
double[][] double2DArray;
// Two Dimensional Arrays
byte[] byte2DArray[]; // Ugly
long[] long2DArray[];
And these are some examples of illegal declarations –
int[5] intArray; // Don't mention size!
double{} doubleArray; // Square Brackets please!
Instantiation
This is how we “instantiate”, or allocate memory for an array –
int[] array = new int[5];
When the JVM encounters the new keyword, it understands that it must allocate memory for something. And by specifying int[5], we mean that we want an array of ints, of size 5.
So, the JVM creates the memory and assigns the reference of the newly allocated memory to array which a “reference” of type int[]
Initialization
Using a Loop – Using a for loop to initialize elements of an array is the most common way to get the array going. There’s no need to run a for loop if you are going to assign the default value itself, because JVM does it for you.
All in One..! – We can Declare, Instantiate and Initialize our array in one go. Here’s the syntax –
int[] arr = {1, 2, 3, 4, 5};
Here, we don’t mention the size, because JVM can see that we are giving 5 values.
So, until we instantiate the references remain null. I hope my answer has helped you..! :)
Source - Arrays in Java
You are correct. Aside from that if we want to create array of specific size filled with elements provided by some "factory", since Java 8 (which introduces stream API) we can use this one-liner:
A[] a = Stream.generate(() -> new A()).limit(4).toArray(A[]::new);
Stream.generate(() -> new A()) is like factory for separate A elements created in a way described by lambda, () -> new A() which is implementation of Supplier<A> - it describe how each new A instances should be created.
limit(4) sets amount of elements which stream will generate
toArray(A[]::new) (can also be rewritten as toArray(size -> new A[size])) - it lets us decide/describe type of array which should be returned.
For some primitive types you can use DoubleStream, IntStream, LongStream which additionally provide generators like range rangeClosed and few others.
Here is the clear example of creating array of 10 employee objects, with a constructor that takes parameter:
public class MainClass
{
public static void main(String args[])
{
System.out.println("Hello, World!");
//step1 : first create array of 10 elements that holds object addresses.
Emp[] employees = new Emp[10];
//step2 : now create objects in a loop.
for(int i=0; i<employees.length; i++){
employees[i] = new Emp(i+1);//this will call constructor.
}
}
}
class Emp{
int eno;
public Emp(int no){
eno = no;
System.out.println("emp constructor called..eno is.."+eno);
}
}
The genaral form to declare a new array in java is as follows:
type arrayName[] = new type[numberOfElements];
Where type is a primitive type or Object. numberOfElements is the number of elements you will store into the array and this value can’t change because Java does not support dynamic arrays (if you need a flexible and dynamic structure for holding objects you may want to use some of the Java collections).
Lets initialize an array to store the salaries of all employees in a small company of 5 people:
int salaries[] = new int[5];
The type of the array (in this case int) applies to all values in the array. You can not mix types in one array.
Now that we have our salaries array initialized we want to put some values into it. We can do this either during the initialization like this:
int salaries[] = {50000, 75340, 110500, 98270, 39400};
Or to do it at a later point like this:
salaries[0] = 50000;
salaries[1] = 75340;
salaries[2] = 110500;
salaries[3] = 98270;
salaries[4] = 39400;
More visual example of array creation:
To learn more about Arrays, check out the guide.
Yes it is correct in Java there are several steps to make an array of objects:
Declaring and then Instantiating (Create memory to store '4' objects):
A[ ] arr = new A[4];
Initializing the Objects (In this case you can Initialize 4 objects of class A)
arr[0] = new A();
arr[1] = new A();
arr[2] = new A();
arr[3] = new A();
or
for( int i=0; i<4; i++ )
arr[i] = new A();
Now you can start calling existing methods from the objects you just made etc.
For example:
int x = arr[1].getNumber();
or
arr[1].setNumber(x);
For generic class it is necessary to create a wrapper class.
For Example:
Set<String>[] sets = new HashSet<>[10]
results in: "Cannot create a generic array"
Use instead:
class SetOfS{public Set<String> set = new HashSet<>();}
SetOfS[] sets = new SetOfS[10];
Suppose the class A is such:
class A{
int rollno;
int DOB;
}
and you want to create an array of the objects for the class A. So you do like this,
A[] arr = new A[4]; //Statement 1
for (int i = 0; i < 4; i++) {
arr[i] = new A(); //Statement 2
}
which is absolutely correct.
Here A is the class and in Statement 1 Class A is a datatype of the array. When this statement gets executed because of the new keyword an object is created and dynamically memory is allocated to it which will be equal to the space required for the 4 blocks of datatype A i.e, ( for one block in the array space required is 8 bytes (4+4), I am assuming int takes 4 bytes of space. therefore total space allocated is 4*4 bytes for the array ).
Then the reference of the object is given to the arr variable. Here important point to note is that Statement 1 has nothing to do with creating an object for class A ,no object is created for this class it is only used as a datatype which gives the size of the class A required for the memory allocation of the array.
Then when for loop is run and Statement 2 is executed JVM now allocates the memory for the Class A (i.e creates an object) and gives its reference to the arr[i]. Every time the loop is called an object is created and the reference of it is given to arr[i].
Thus, arr[0] which holds a space of 8 bytes is given the reference of the object of the Class A and everytime loop is run new object is created and reference is given to that object so that it can now access the data in that object .

Categories

Resources