Instantiating JAVA Array of Generic Class - java

E[] arr = (E[])new Object[INITIAL_ARRAY_LENGTH];
The code above was taken from this following post:
Where E is a generic class type. How does the compiler/JVM know how much memory it needs to assign when we are using type Object to instantiate the array. My understanding is, type casting only allows to change reference type, but not the underlying object structure.

An array of a certain size of reference type will take same size in memory no matter what types of objects it holds. This is because the memory holds only the references (pointers) and that's it and not the memory for the array items which is assigned when those objects are created. The heap will then hold new objects as they're created and assigned to the array.
So, the following arrays will all take up the same size:
new Integer[10]
new BigInteger[10]
new String[10]
new Object[10]
Note that to the compiler, an array of a non-constrained generic type translates to an array of Object.
Also note that arrays of primitives likely have a different memory footprint.
.....
Again, this is just the memory for the array itself, not the items it references -- and this is a very important point in all of this, probably the most important point for understanding this.

Related

How does Java allocate storage for array of interfaces?

Since interfaces only specify methods and not instance variables, how is storage allotted to something like:
Comparable[] aux = new Comparable[20];
How much per location storage (i.e. not counting array overhead) will be allocated?
The array is only allocating enough contiguous memory for the pointers to the objects, it doesn't need to allocate memory for the actual objects itself.
We can sometimes forget, Java still uses "pointers" (aka references), it just doesn't provide the same level of access to those pointers that other languages do
Objects are reference types, therefore every Object subtypes (including Comparator and every other interface) are reference types. It means that the size of every array item is the size of an object reference. It doesn't make a difference what kind of object it is.

Purpose of new keyword in creating array in Java

I want to know why an array created in Java static even when we use the new keyword to define it.
From what I've read, the new keyword allocates a memory space in the heap whenever it is encountered during run time, so why give the size of the array at all during definition.
e.g. Why can't
int[] array1=new int[20];
simply be:
int[] array1=new int[];
I know that it does not grow automatically and we have ArrayList for that but then what is the use of keyword new in this? It could have been defined as int array1[20]; like we used to do it in C, C++ if it has to be static.
P.S. I know this is an amateurish question but I am an amateur, I tried to Google but couldn't find anything comprehensive.
This may be an amateurish question, but it is one of the best amateurish questions you could make.
In order for java to allow you to declare arrays without new, it would have to support an additional kind of data type, which would behave like a primitive in the sense that it would not require allocation, but it would be very much unlike a primitive in the sense that it would be of variable size. That would have immensely complicated the compiler and the JVM.
The approach taken by java is to provide the bare minimum and sufficient primitives in order to be able to get most things done efficiently, and let everything else be done using objects. That's why arrays are objects.
Also, you might be a bit confused about the meaning of "static" here. In C, "static" means "of file scope", that is, not visible by other object files. In C++ and in Java, "static" means "belongs to the class" rather than "belongs to instances of the class". So, the term "static" is not suitable for describing array allocation. "Fixed size" or "fixed, predefined size" would be more suitable terms.
Well, in Java everything is an object, including arrays (they have length and other data). Thats why you cannot use
int var[20];
In java that would be an int and the compiler would be confused. Instead by using this:
int[] var;
You are declaring that var is of type int[] (int array) so Java understands it.
Also in java the length of the array and other data are saved on the array, for this reason you don't have to declare size of array during declaration, instead when creating an array (using new) the data are saved.
Maybe there is a better reason that oracle may have answered already, but the fact that in Java everything is an object must have something to do with it. Java is quite specific about objects and types, unlike C where you have more freedom but everything is more loose (especially using pointers).
The main idea of the array data structure is that all its elements are located in the sequential row of memory cells. That is why you can not create array with variable size: it should be unbounbed space vector in memory for this purpose, which is impossible.
If you want change size of array, you should recreate it.
Since arrays are fixed-size they need to know how much memory to allocate at the time they are instantiated.
ArrayLists or other resizing data structures that internally use arrays to store data actually re-allocate larger arrays when their inner array data
structure fills up.
My understanding of OP's reasoning is:
new is used for allocating dynamic objects (which can grow like, ArrayList), but arrays are static (can't grow). So one of them is unnecessary: the new or the size of the array.
If that is the question, then the answer is simple:
Well, in Java new is necessary for every Object allocation, because in Java all objects are dynamically allocated.
Turns out that in Java, arrays are objects, different from C/C++ where they are not.
All of Java's variables are at most a single 64bit field. Either primitives like
integer (32bit)
long (64bit)
...
or references to Objects which depending on JVM / config / OS are 64 or 32 bit fields (but unlike 64bit primitives with atomicity guaranteed).
There is no such thing as C's int[20] "type". Neither is there C's static.
What int[] array = new int[20] boils down to is roughly
int* array = malloc(20 * sizeof(java_int))
Each time you see new in Java you can imagine a malloc and a call to the constructor method in case it's a real Object (not just an array). Each Object is more or less just a struct of a few primitives and more pointers.
The result is a giant network of relatively small structs pointing to other things. And the garbage collector's task is to free all the leaves that have fallen off the network.
And this is also the reason why you can say Java is copy by value: both primitives and pointers are always copied.
regarding static in Java: there is conceptually a struct per class that represents the static context of a class. That's the place where static instance variables are anchored. Non-static instance variables are anchored at with their own instance-struct
class Car {
static int[] forAllCars = new int[20];
Object perCar;
}
...
new Car();
translates very loosely (my C is terrible) to
struct Car-Static {
Object* forAllCars;
};
struct Car-Instance {
Object* perCar;
};
// .. class load time. Happens once and this is referenced from some root object so it can't get garbage collected
struct Car-Static *car_class = (struct Car-Static*) malloc(sizeof(Car-Static));
car_class->forAllCars = malloc(20 * 4);
// .. for every new Car();
struct Car-Instance *new_reference = (struct Car-Instance*) malloc(sizeof(Car-Instance));
new_reference.perCar = NULL; // all things get 0'd
new_reference->constructor();
// "new" essentially returns the "new_reference" then

Having two stores of an object in Java

Suppose I have the following code in java
Object object = new Object();
mylist.add(object);
mylist2.add(object);
As far as I understand I have created one object in memory and both mylist and mylist2 have some kind reference to this object. Is that correct?
In which case how much more memory does the program above use compared to if I had just done
Object object = new Object();
mylist.add(object);
I'm wondering because I sometimes feel it would be useful to have two different data structures holding the same information for different purposes.
Ex:
A binary tree and a hash map such that you can easily search for objects in constant time and easily iterate through an ordered list of the objects.
It depends on what type of list you use. If you use an ArrayList, then there is no overhead for each entry except the reference itself (4 bytes on a 32 bit machine, ignoring the empty space in this kind of list ;)). If you use for example a LinkedList then there is a wrapper object around it, which additionally holds a reference to the previous/next element in the list.
On most VMs the size of a reference is the native pointer size (from John Skeet)
So if you use a 32bit VM e.g. it will be 4 bytes.

Do ArrayLists that contain different types of objects use different amounts of memory?

For example, if you were to have
int a=2; int b=3;
ArrayList<Integer>integers=new ArrayList<Integer>();
integers.add(a); integers.add(b);
and
String c="cow"; String d="deer";
ArrayList<String> strings= new ArrayList<String>();
strings.add(c); strings.add(d);
Would they take different amounts of memory? Any help/answer would be highly appreciated, thanks!
The ArrayLists themselves are nothing more than a collection of references, and these take the same amount of memory (if the same size) no matter the type of objects they hold. However the items referred to by the ArrayList all take differing amounts of memory as you would expect.
ArrayLists are nothing but a collection of references, so the size of ArrayList does not depends on the type of the object it points to. Hence the memory of the ArrayList does not depend on the reference object types.
In your case, and in theory, they would consume the same amount of memory, in runtime generics "doesn't exist" and both arrays are actually arrays of objects.
ArrayList arr = new ArrayList<Foo>(10);
arr contains just 1 reference of the backing array. This backing array will have 10 references of 10 different Foo Objects in heap.
ArrayList is an object like String or smth else. It stores collection in an internal Object[] array. These arrays will take different amount if memory but ArrayList themselves will be the same size.

How objects are allocated in array?

I want to improve my knowledge about memory model of programming languages (particulary in Java), so I have one question.
Here is very simple code:
// Allocating memory in heap for SimpleObject's instance
// Creating reference to this object with name so1
SimpleObject so1 = new SimpleObject();
// Allocating memory in heap for array of 10 references to SimpleObject's objects
// Now I know, that array stores only references to the objects
// (Previously I thought that array stores objects)
// Then we create reference to this array with name soArray
SimpleObject[] soArray = new SimpleObject[10];
Now the question:
// What is going on here?
soArray[0] = so1;
// object so1 had been really moved to memory area of soArray?
// And so1 reference have been updated to new memory address?
// Or we just had assigned so1 object's reference to soArray[0] element?
// Or so1 object had been copied to the soArray[0]?
// Then original so1 object has been deleted and all links to it had been updated?
If you know, how it works in other languages, such as (C, C++, C# or other), please answer, I will be glad to know it.
Everybody know, that ArrayList can be faster than LinkedList, because elements of array could be stored in CPU cache, while if we working with LinkedList, CPU has to get next object from RAM each time.
So how could it work, if at first I had created object in heap and only then I had put object in array?
UPD: Thank you guys, now I understand how array is working, but what about caching array in CPU cache in that way?
Arrays store references to objects, not the objects themselves. You therefore swap the reference at position 0 when assigning soArray[0]. The objects themselved can be moved within the heap, but this is usually due to GC, not assignments.
If the objects themselves were stored directly in the array, you could not have instances of subclasses with more instance fields in your array. They would not fit into the allocated space and therefore only become instances of the base class. This is what actually happens in C++ when you assign class instances stored on the stack.
In Java, arrays store references to objects. In C++ parlance they store pointers to objects.
SimpleObject[] soArray = new SimpleObject[10]; //Java
SimpleObject* cppArray[10]; // C++ equivalent
soArray[0] = so1; puts a reference to so1 in soArray[0] in the same way that cppArray[0] = &so1 stores a pointer to so1. The original object remains unchanged, no additional memory is allocated or deallocated.
In C++ you can store the objects directly in an array.
SimpleObject soArray[10]; // An array that stores Simple Objects in place
SimpleObject so1; // A new object
soArray[0] = so1; // This *copies* so1 into soArray[0]
We assign the reference to the object pointed by so1 to the array element.
Here's an example in using Python Tutor (there's no equivalent tool for Java that I know, but the memory model is similar, except for the Class being an object, so ignore that):

Categories