C++ vs Java: Arrays of Objects - java

C++:
Student* sp = new Student[10];
Now, please correct me if wrong. I believe this creates an array of 10 instances of Student, each calling the default constructor with no arguments.Please use arrays and not vectors.
Java:
Student [] sa = new Student[10];
Again, correct me if I'm wrong but I think in case of Java though, no instances are created when this statement executes and instead only memory is reserved to hold 10 references to Student instances.
And it is necessary that we follow it up with:
sa[0] = new Student(*arguments*);
sa[1] = new Student(*arguments*);
.
.
.
sa[9] = new Student(*arguments*);
I'm trying to see the difference and quite frankly, I'm confused. Kindly clarify please.

What do you mean, you're trying to see the difference and you're confused? The difference is exactly what you've stated. The C++ code creates an array of 10 Student objects that are default-initialized [1], and the Java code creates an array of 10 references so no Student constructors are called until you do it yourself.
Maybe your question is why C++ and Java differ. That's because a Student[] in Java is an array of Student references, so the true C++ equivalent would be an array of Student pointers,
Student** sp = new Student*[10]
which you would indeed have to follow up with
sp[0] = new Student(args);
...
sp[9] = new Student(args);
analogously to your Java example.
Now, if you want an array of 10 Student objects in C++ initialized using a constructor other than a default constructor, you have to do it in two steps: first allocate memory for 10 Student objects, then manually construct the Student objects over that memory using placement new. I do not endorse this style of coding. It is very confusing even to experienced C++ programmers.
typedef Student SA[10]; // SA means array of 10 Students
SA* psa = static_cast<SA*>(::operator new(sizeof(SA)));
SA& sa = *psa; // sa refers to an array of 10 Students
new (&sa[0]) Student(args); // construct the Student object
// ...
new (&sa[9]) Student(args);
// later
for (int i = 0; i < 10; i++) {
sa[i].~Student(); // destroy the Student object
}
::operator delete(psa); // deallocate the memory for the array
Use a damn vector.
[1] Note: In C++, for a class, default-initialized means that the default constructor is called; for an array, it means each element is default-initialized; and for an arithmetic, pointer, reference, or enum type, it means it's not initialized at all.

Short answer:
Those two declarations are different. The C++ one allocates an array of Student objects, while the Java one allocates an array of references to Student objects.
Long answer:
The difference is that, in Java when you declare an object:
Student s;
It creates a reference (similar to a pointer in C++) to a Student and initializes the reference to null. You can then later assign a Student object to that reference variable with s = new Student().
But in C++ when you declare an object:
Student s;
It creates an actual object (not a reference to an object as in Java). And thus the object must be immediately instantiated.
So in Java, when you do this:
Student [] sa = new Student[10];
It actually creates an array of references to Student objects (not an array of actual Student objects), and they are all initalized to null references.
...I think in case of Java though, no instances are created when this statement executes and instead only memory is reserved to hold 10 references to Student instances.
So yes, you're right.
But in C++ this:
Student* sp = new Student[10];
dynamically allocates an array of actual Student objects. Again, not references as in Java, so each object will be instantiated immediately.
I believe this creates an array of 10 instances of Student, each calling the default constructor with no arguments.
Correct as well.
So in Java after declaring the array of references you can then instantiate the actual objects and assign them to those references in the array with this:
sa[0] = new Student(*arguments*);
But in C++ the Student objects in the array were already instantiated, so this is not needed.
Bonus: Array of pointers in C++
In C++, you can also declare an array of pointers to postpone object instantiation, similar to the Java array of references:
Student** spp = new Student*[10];
This will create an array of 10 pointers to Student objects. You can then instantiate the objects when needed and assign their memory addresses to the pointers:
spp[0] = new Student(*arguments*);
This looks a lot like Java, but is actually not generally recommended in C++. In fact, using new in C++ should be avoided most of the time.

Here's a round about way of accomplishing what you are hoping to using the new operator.
#include <new>
struct Student
{
Student(int ){}
};
int main()
{
// Allocate memory for 10 Students.
// Don't construct Student objects yet.
char* cp = new char[10*sizeof(Student)];
// Now construct the Student objects using
// placement new
Student* sp[10];
for ( int i = 0; i < 10; ++i )
{
sp[i] = new (cp + sizeof(Student)*i) Student(10);
}
// Use the Student objects
// ...
// ...
// Call the destructor on the Students explicitly.
for ( int i = 0; i < 10; ++i )
{
sp[i]->~Student();
}
// Deallocate the memory.
delete [] cp;
}

Related

Null pointer access: The variable b can only be null at this location

I get the above mentioned error in the last line of this following portion of my code.
String[][] b = null;
try {
br = new BufferedReader(new FileReader(csvFile));
while ((line = br.readLine()) != null) {
// use comma as separator
String[] country = line.split(cvsSplitBy);
String[] a=country[1].split(splits);
i = 0;
n = 0;
while(i<a.length) {
b[j][n]+=a[i];
}
}
} catch (...) {}
What is the reason for this error and how to solve this?
The only two uses of b are
b = null;
...
*b[j][n] ...
You need to set b to an actual array before you can try indexing it.
String[][] b is null. Look like you should not use Array here as you don't know the size up front. You can use an ArrayList with some custom object.
In the Java programming language, arrays are objects (§4.3.1),
are dynamically created, and may be assigned to variables of type
Object (§4.3.2) [...] A component of an array is accessed by an array access expression
(§15.13) that consists of an expression whose value is an array
reference followed by an indexing expression enclosed by [ and ], as
in A[i].
How do array access expression work? Like this.
Relevant bit:
Otherwise, if the value of the array reference expression is null,
then a NullPointerException is thrown.
Long story short: arrays are objects, and b is a reference to an (array) object - like basically everything in Java except primitive types.
A reference can point to something or be a null reference.
A null-reference is something entirely different from any other sort of object in the heap, including an empty array: you can't do anything with it, including trying to access its elements, except assigning a value to it (imagine it as a blank "phone" line in an address book: before calling you have to have a number to call!)
So, you have to first make your reference point to an actual array, with
b = new String[10][10].
Using this right after
String[][] b = null;
would be a good idea; or you can just String[][] b = new String[10][10]().
At this point, b points to a string array in the heap, and you can do things with it.
Note that you have to specify a size.
If you don't know it yet you might be better off with other containers, for example ArrayList, which grows dynamically.

Pointer to pointer equivalent in java [duplicate]

This question already has answers here:
C++ Pointers to Pointers in Java
(5 answers)
Closed 7 years ago.
For last some day I am learning Java while I have some knowledge in C. Now I am trying to convert code written in C to a Java code. There I found a pointer to pointer (pptr)variable declaration like this -
int n;
int *ptr;
int **pptr;
n = 13;
ptr = &n;
pptr = &ptr;
As far as I know, in Java there is no pointer type variable. My question is there any way to represent pptr or anything equivalent of pptr in Java?
Let's look at some of the use cases for multiple indirection in C, and see how they apply to Java.
Use Case #1: you want a function or method to change the value of a pointer or reference parameter such that it points to a new object, and have that change reflected in the caller.
In C, that would look something like this:
void foo( T **p )
{
*p = new_value(); // update the thing p points to
}
void bar( void )
{
T *var; // for any type T
foo( &var ); // foo will set var to point somewhere else
}
var is a pointer to something, and we want the function foo to change var such that it points to something else. Since C passes all function arguments by value, if we want foo to update var, we must pass a pointer to var, giving us a pointer to pointer type in foo.
Java doesn't expose operations on pointer types (no unary & address-of or * indirection operators), so we can't do this directly. We'd have to wrap the reference we want to change in another reference type and pass that wrapper type to the method, and even then I'm not sure it would do the same thing as the C code above:
public class thing
{
// attributes
}
public class thingWrapper {
{
public thing t;
}
public void pointToNewThing( thingWrapper tw )
{
tw.t = newThing();
}
public void bar()
{
thing t = new thing();
...
thingWrapper tw = new thingWrapper();
tw.t = t;
pointToNewThing( tw );
t = tw.t;
...
}
Use Case #2: you want to allocate a multi-dimensional array in a piecemeal fashion, rather than in a single operation. This is useful if you want a "jagged" array (where the number of elements in each row isn't uniform) or if you're trying to allocate a lot of memory and don't have a single available block large enough for the whole thing.
In C, you'd do something like
T **arr = malloc( N * sizeof *arr );
if ( arr )
{
for ( int i = 0; i < N; i++ )
{
arr[i] = malloc( M * sizeof *arr[i] );
}
}
because C arrays are not "first class" objects, and cannot be manipulated and assigned directly, so you have to do this through pointers.
Java treats arrays completely differently such that you don't need to do the pointer-to-pointer dance at all:
T arr[][] = new arr[N];
for ( i = 0; i < N; i++ )
{
arr[i] = new arr[M];
}
I can't think of other use cases off the top of my head, but that should give you a flavor of how you'd translate the C concept to Java.
The short answer is yes. But first, a lesson in Java...
In Java, whenever you use objects, pointers are involved. If you have an object, the variable that "holds" that object is actually a pointer to that object. So if you are working with objects, you are already using pointers.
Now for primitive data types (e.g., integers, chars, or floating point numbers), Java does not use pointers, though. So if you want pointers for primitive data types, you need to use a wrapper class, such as Integer, which effectively promotes the value to an object.
Note, however, that the default wrapper classes are immutable.
If you want double-pointers (a pointer to a pointer) or triple pointers, you will need to create custom wrapper classes, like an ObjectWrapper class, that allows you to set up an arbitrary number of objects each pointing to (or "holding") the next.
What you can do is create an int array even with a size of 1 this way when you access the array it will always refer to the same place in memory as far as your programming is concerned.

calling constructor through array of objects

class A
{
static int i;
A()
{
System.out.println(++i);
}
public static void main(String h[])
{
A obj[] = new A[30];
}
}
A obj[30] = new A[30]; :- this line should invoke the default
constructor 30 times ?
The line
A obj[30] = new A[30];
does not call the constructor for A. It creates 30 uninstantiated references to A;
To instantiate the 30 object references, you can use:
A obj[] = { new A(), new A(), ..28 more ->
};
or better in this case given the number of elements:
for (int i=0; i < obj.length; i++) {
obj[i] = new A();
}
Note, the first use of 30 in the array size declaration is illegal.
A obj[30] = new A[30];
^
No, this line does not invoke constructor at all. It just creates 30 elements long array of type A. Each element of array is null.
There is no way to do exactly what you want to do, but here are two things that come very close, both calling the default constructor 30 times:
A *obj = new A[30];
or
A obj[30];
The first answer will create an array of 30 A objects on the heap, calling the default constructor for each one of them. obj can be passed back to callers of this function since it is not on the stack. The problem is, obj no longer has a type of A[30], so sizeof(obj) will be different from the code in the original question. (Note that "delete []" must be used for obj, not just "delete".)
The second answer will create an array of 30 A objects on the stack. Now the compiler will understand the obj has 30 elements, and sizeof(obj) will be the same as in your question. However, obj can only be used within this function (or functions that it calls) because once the function returns, it will be eliminated from the stack, calling 30 destructors in the process. (It is a local variable only.)
With C++ (or any good object oriented language), creating an object always means both allocating the space and calling the constructor. Otherwise, you really don't have a useful object. So, when an object is created in any supported way (local variable or "new" for C++), it always calls the default constructor for every object you created and now have access to. (Note that if there were no default constructor, then neither answers would even compile!)

Java Array of Objects crashes

Java noob question:
Consider the following C array and initializer code:
struct {
int x;
int y;
} point_t;
point_t points[1000];
Easy. This gets created and memory allocated at load time.
Now consider the similar in Java:
public class point_t
{
public int x;
public int y;
}
point_t points[] = new point_t[1000];
// Without this loop, java will crash when you run this
for (int i=0; i<1000; i++)
{
points[i] = new point_t;
}
points[0].x = 10; // Crash would occur here without above loop
points[1].x = 10;
Initially my java program was crashing with a null pointer dereference. The problem was that, coming from C++, I was not aware that you have to create the 1000 point_t objects. Just a comment but this seems INSANE. Suppose the array size was 1 million or 1 billion. It would literally take seconds simply to "create" this array with empty entries at run time. In C++ it all happens at load time. I admit that you don't always know what would be in the C++ array's cells, but in embedded systems where I work, quite often the memory is auto initialized to zeros so it works.
So is there any easier, quicker, more efficient way in Java to create an array and allocate the memory when you have an array of objects? Or am I doing something wrong in the code above?
Since you are coming from a C++ background, this may help. In Java, when you write
point_t points[] = new point_t[1000];
This is similar to writing, in C++,
point_t* points[] = new point_t*[1000];
That is, in Java, when you create the array, you are not creating an array of point objects, but rather and array of point references, the same as if you would have created an array of point pointers in C++.
Java is a managed (garbage-collected) language; that is what Java programmers would expect.
As for the second part of your question, how one would create the objects themselves, what you did is fine. Create 1000 point objects in a loop and load them up. If you want shorter code, you can write a nice method to do this work. :)
You can also look into other collection libraries that might have these kind of convenience factory methods.
Writing
point_t[] points = new point_t[ 1000 ];
is allocating a thousand references to point_t objects. (In C parlance, it's allocating pointers to structs of that type.)
That loop
for (int i=0; i<1000; i++)
{
points[i] = new point_t;
}
allocates a new point_t object, and puts the references (pointer) to it in the array. Until you did that, the array was nothing but nulls, and it probably gave you null exceptions.
That's not an array of point_t instances; those live out on the heap.
It's really an array of references to those point_t instances out on the heap.
Any reference that is not initialized by being assigned to a reference value (e.g. by calling new) is set to null.
It's true for non-array reference types, too.
public class Person {
private String name; // not initialized; that means it's null
public Person() {} // oops; constructor should have initialized name, but now it's null
public String getName() { return name; } // returns null unless you set it properly
public void setName(String newName) { this.name = newName; }
}
You can use the Flyweight pattern to share the same data between different objects and defer the creation of the point object until it is really necessary

Arrays in Java and how they are stored in memory

I'm trying to understand the array setup in java. Why must you initialize space for each each object in the array, after you have created the array. How is it stored in memory like this:
[object][object]
or like this:
[*class]->[object]
[*class]->[object]
In other words, what is actually being done in memory. Does array[0] = new class() just return a reference to a reserved location in memory, and the class[] array = new class[10] statement create something along the lines of 10 pointers, which are later assigned to by the new statements?
Arrays in Java store one of two things: either primitive values (int, char, ...) or references (a.k.a pointers).
So, new Integer[10] creates space for 10 Integer references only. It does not create 10 Integer objects (or even free space for 10 Integer objects).
Incidentally that's exactly the same way that fields, variables and method/constructor parameters work: they too only store primitive values or references.
If you are familiar with C/C++ you can think of Java object references as pointers to objects (or pointers to structs). So:
Person p = new Person();
p.setName("Helios");
is:
declare a p pointer to a Person struct (in the stack)
reserve memory for and initialize Person struct
assign its address to p
execute method setName on object referenced by p
So when you are doing:
Person[] ps = new Person[5];
you are reserving an array of 5 references to Person. Next you will have to create each real person and assign each reference to a place in the array.
Edit: the (almost) C/C++ version of the previous code
class Person { ... };
typedef PersonStruct* Person; // I don't remember if this declaration is ok
Person p = new PersonStruct();
p -> setName(...);
Person[] ps = new Person[5];
// ps is a variable in the stack pointing to the array in the heap
// (being the array five references to the PersoStruct)
and you could do
ps[3] = p;
Arrays are continuous space of memory, so they look like more your first sketch:
[object-reference][object-reference]
array[0] = new class() will store in array[0] a reference to the new created object.
class[] array = new class[10] will create an array of ten empty slots (or ten null references).

Categories