Could anyone please explain me why this code snippet works?
Object[] op = new Object[0];
ArrayList r = new ArrayList();
r.add("1");
r.add("3");
r.add("5");
r.add("6");
r.add("8");
r.add("10");
op = r.toArray();
System.out.println(op[3]);
This prints out 6. I know that you can convert list to array but I was thinking that if the array is fixed size then you can't add further elements. In this case the array op is with fixed size "0" so why/how are the list elements being added to the array? Thanks
You need to distinguish between the reference to your array object (that is Object[] op) and the actual array object to which the reference points.
With
Object[] op = new Object[0];
you are creating an array of size 0 and assign it to the op reference.
But then, with
op = r.toArray();
you are assigning a new array object to the op reference. This new array object has been created by the toArray() method with the appropriate size.
The earlier array object which was created with new Object[0]; is now dangling and subject to garbage collection.
For the same reason that this code prints out X instead of ABC:
String s = "ABC";
String t = "XYZ";
s = t.substring(0, 1);
System.out.println(s);
You're reassigning the value of op, and the new value has nothing to do with the old value.
You misunderstood one important thing here.
Java identifiers are only pointers to objects, not objects themselves.
Here when you do
Object[] op = new Object[0];
you create a new instance array with a fixed size of 0, and you point the identifier "op" to it.
But when you later do
op = r.toArray();
you just overwrite where your former identifier point to. You lose the reference to your first array that will be garbaged collected.
"op" desgin now a new array, your former one just disappear.
Related
One of the main Charucteristic of the Array is immutability(Size of the array cant be changed) but while i was practicing i found myself in this case :
We have an Array with specific size
String[] strArr = new String[1];
And ArrayList with Objects
ArrayList<String> list = new ArrayList<>();
list.add("Alex");
list.add("Ali");
list.add("Alll");
So when we try to convert the list to an array and assign it to strArr , like this
strArr = list.toArray(strArr);
for(String str : strArr ) {
System.out.println(str);
}
It works without a problem even if the size of the array doesnt equal the size of the list
So I JUST WANT TO KNOW HOW THIS IS POSSIBLE , WHEN THE SIZE OF THE ARRAY CANT BE CHANGED ?
New array allocated
strArray first references to a String array of size 1, when you do strArr = list.toArray(strArr);, you change the reference of strArray to a different array. So you are not changing the array size, you are only changing to which array now strArrays refers to.
Possibly you assume that list.toArral(strArr) modifies strArr but that's not the case, as you can read at the java documentation. It reads:
"If the list fits in the specified array, it is returned therein. Otherwise, a new array is allocated with the runtime type of the specified array and the size of this list"
The important section for your case, is where the documentation says: "Otherwise, a new array is allocated", so, no array resize is done.
You can use
strArr = list.subList(0, strArr.length).toArray(strArr);
Basicaly, the List#subList(fromIndex, toIndex) creates a new List with the elements starting in the fromIndex up to toIndex (self-explaintory)
You can read more about in https://docs.oracle.com/javase/8/docs/api/java/util/List.html#subList-int-int-
It changes the reference to a new object. You can check this by calling: System.out.println(strAttr) immediately after you first assign the variable and then again after you call strArr = list.toArray(strArr);
I'm developing for the Android platform and, to simplify the question, I'm using pseudo-names for the entities.
I have an object array stuff[] of the class StuffClass[].
StuffClass stuff[]={
new StuffClass(Argument, argument, argument),
new StuffClass(argument, argument, argument)
};
I have an activity returning a result of three arguments that I want to then use to add a new object to stuff[]. I've done so as follows:
stuff[stuff.length]=new StuffClass(argument, argument, argument);
and I get ArrayOutOfBounds (Figured that would happen).
So how might I go about creating a new object in the stuff[] array?
Arrays are static you can't change size without creating a new one before. Instead of that you can use a dynamic data structure such as an ArrayList
Example:
List<MyType> objects = new ArrayList<>();
objects.add(new MyType());
Here you forget about array size.
Array in Java is little bit special, it's length is fixed when it's initialized, you can not extend it later on.
What you can do is to create a new array, and use System.arraycopy to generate a new array, here's the sample code:
String[] arr1 = new String[]{"a", "b"};
String[] arr2 = new String[3];
System.arraycopy(arr1, 0, arr2, 0, 2);
arr2[2] = "c";
You cannot increase the size of an existing array. Once it's created, the size of the array is fixed.
You will need to create another bigger array and copy the items from the old array to the new array.
A better alternative is to use an ArrayList. When you add items to an ArrayList, the capacity will grow behind the scenes if needed; you don't have to worry about increasing the size.
you can use the ArrayList to do this
arraylist.add(object);
in java arrays are fixed length. you need to initialise them with the desired length.
Consider using a Collection such as ArrayList which will handle everything for you.
List<StuffClass> myList = new ArrayList<>();
myList.add(...);
Lists support similar behaviour to arrays ie:
myList.set(i, elem);
myArray[i] = elem;
elem = myList.get(i);
elem = myArray[i];
len = myList.size();
len = myArray.length;
You can then convert the list to an array.
StuffClass[] myArray = myList.toArray(new StuffClass[myList.size()]);
If you don't want to use lists consider using System.arrayCopy to create a new array with more elements.
read here for a good description.
I'm having trouble understanding how an array of ArrayLists is initialized in Java, can someone explain what's going on in this line of code?
edges = (ArrayList<Integer>[]) new ArrayList[nodeCount + 1];
Let's break it space-by-space.
edges is a variable of type ArrayList<Integer>[]
= is the assign operator which assignes the right-hand to the left-hand
(ArrayList<Integer>[]) is a cast of a variable to the type.
new ArrayList[nodeCount + 1] means we allocate space for an array of ArrayList with nodeCount+1 unknown elements.
This is a very bad way of initializing an array. What it does is it creates an array and makes the elements into Integers.
An alternative:
edges = new ArrayList<Integer>(nodeCount+1);
Explanation: The ArrayList class has a constructor which can specify its length*, this is what I use here.
Note: According to #Rohit Jain, it doesn't specify the length, but the initial capacity.
You cannot create an array whose component type is parameterized type. It's not type safe. Although you can create an array whose component type is raw type, but that won't be type safe either. Consider the following example:
List<Integer>[] list = null; // Declaration is OK
list = new ArrayList<Integer>[5]; // Compiler error: Generic array creation
list = new ArrayList[5]; // Compiles fine. But not safe. Gives warning
Suppose you created an array of raw types. Let's see what can be the implication:
List<Integer>[] list = new ArrayList[10]; // Not type safe
Object[] objArr = list; // We can assign List<Integer>[] to Object[]
// We can add even ArrayList<String> in Object[]
// This will successfully compile, and run.
objArr[0] = new ArrayList<String>() {
{
add("rohit"); add("jain");
}
};
// Here's the problem. It will compile fine, but at runtime will throw
// ClassCastException
Integer val = list[0].get(0);
Alternative is create a List of List:
List<List<Integer>> edges = new ArrayList<List<Integer>>();
Suggested Read: -
Angelika Langer Generic FAQs:
Can I create an array whose component type is a concrete parameterized type?
Can I declare a reference variable of an array type whose component type is a concrete parameterized type?
In the above line you are creating an array of ArrayList, you could replace ArrayList by a more simple type to help you to understand, e.g. an array of String:
edges = (String[]) new String[nodeCount + 1];
nodeCount + 1 corresponds to size of the array. The array can't have more than this number of elements.
Note that using an array of a parametrized ArrayList is quite strange and prone to misunderstanding and errors. I would use a List<List<Integer>> here, e.g.:
edges = new ArrayList<List<Integer>>();
this line defines an array, like any other array out there: exampe new Object[0], new String[0], ...
and just like any other array, the values will be initiated with the null value. for primitive types is that '0', for objects/classes is that null.
so you should initiate the different arraylists before using it like:
edges = new ArrayList<Integer>[nodeCount + 1];
for(int i=0; i<edges.length; i++){
edges[i] = new ArrayList<Integer>();
}
This does not initialize an ArrayList -- it initializes an array of ArrayLists:
new ArrayList[nodeCount + 1] = create an array of ArrayList objects with nodeCount + 1 slots
(ArrayList<Integer>[]) = cast it to an "array of ArrayList objects which in turn may only contain Integer objects". This is needed because the array declaration syntax of java apparently can't handle generics (just tried it -- I never needed this before).
It could be a misunderstanding, and the writer actually wanted to initialize one ArrayList with a capacity of nodeCount+ 1. The correct code for that would be
edges = new ArrayList<Integer>(nodeCount + 1);
Actually the capacity parameter is just an optimization, since ArrayList objects grow automatically as needed. But if you already know how many entries you need, the List can be created with enough capacity from the start.
new ArrayList[nodeCount + 1]
create a new array of ArrayList, its length is nodeCount + 1;
then
(ArrayList<Integer>[])
is a cast operation, it casts the array you just created into an array of ArrayList<Integer>
I'm new to Java so this might be a dumb question. Say I create a class called SomeObject with simple getters and setters for some parameter. Next I want to create an array of 3 instances of that object. Can anyone tell me what's the difference between:
SomeObject[] objectArray = {new SomeObject(),new SomeObject(),new SomeObject()};
objectArray[0].setValue(10);
and:
SomeObject[] objectArray = new SomeObject[3];
objectArray[0].setValue(10);
In the first case I can perfectly well get the value of objects[0]:
System.out.println(objectArray[0].getValue());
..while the latter gives a NullPointerException while trying to set the value. Am I missing something or could it be I made some mistake of a different kind?
When you create an array of objects, you actually need 2 steps
Create the array
Create the objects
The first method does both, while the 2nd method does only step one, thus the references to the actual objects are null.
Object[] objects = {new Object(),new Object(),new Object()};
Here the {...} creates the array and the inner news create the objects.
Object[] objects = new Object[3];
Here the new creates the array of size 3. But individual elements, such as object[0] are not created and thus the reference is null, and this causes the exception.
Your first line of code creates three Objects to fill the array with.
Your second line of code creates an empty array and never fills it, so it's still full of null.
The second version, Object[] objects = new Object[3];, creates an array of size three, but the objects don't exist, they're null.
The first one, Object[] objects = {new Object(),new Object(),new Object()}; explicitly creates the objects at the same time the array is created, so you can access them
If you want to do it the second way, you can try this:
SomeObject[] objectArray = new SomeObject[3];
objectArray[0] = new SomeObject(); //create SomeObject
objectArray[0].setValue(10); //give SomeObject the value of 10
I am preparing for the entry-level Oracle certification - OCA - Java Programmer I, since they require people to take this one before taking the next one (used to be possible to just go for SCJP directly, which is equivalent of OCP - Java Programmer II)
I came across this question on array initialization, that got me a bit puzzled. Obviously, one can declare and initialize an array like this:
Object[] objects = { new Object[1], new Object[34] };
as the arrays are objects, you can stick object arrays into an object array. You can easily get at one or the other object array by doing objects[0] or objects[1] but where would you go from there? How would you access the, say, 16th Object from the object array stored under objects[1]?
Basically, my question can be simplified to this:
Object o = new Object[100];
The above compiles. However, how would one access individual objects in the Object array o?
An Object[] is also an Object, which is why your declaration
Object o = new Object[100];
works.* To access the elements, though, you need to cast it back to an Object[]. For example:
Object elt = ((Object[]) o)[3];
For your original declaration:
Object[] objects = { new Object[1], new Object[34] };
you will have to do a similar thing to access the 16th element of objects[1]:
Object elt = ((Object[]) (objects[1]))[15];
Of course, you can avoid all this casting by declaring:
Object[][] objects = { new Object[1], new Object[34] };
in the first place. Then you can just do objects[1][15].
* Note that this is true only of Object, which has special status as the root of the object hierarchy in Java. An Integer[] cannot be assigned to an Integer variable.
You'd have to cast it back to Object[]:
Object o = new Object[] {new String("abc"), null, new Integer(1)};
Object[] arr = (Object[]) o;
Object elem = arr[0];
System.out.println(elem);
This prints abc.
It works because System.out.println() is happy to take an Object. If it required a String, you'd need another downcast.