My Background is C++ and in c++ we can easily create array of object using simple syntax. className obj[n]; and also constructor will call n time.
But When I tried to create array of object in java className[] obj=new className[n]; no constructor call. After searching I found the answer of this question on stackoverflow that it just create n Reference that can point to n objects and I need to create objects again for each reference like. obj[0]=new className();
Now I just want to ask why java do this? is there any reason even C++ allows but java not allows to create array of objects in same way?
I searched for this but still didn't get exact answer.
In C++ you have flexibility to choose a memory in which you create the object. You can create objects in automatic area (on the stack), in the static area, or in the dynamic area. In the last case you get an object pointer, and become responsible for freeing it after you are done.
In contrast, all Java has is the dynamic area option, because all objects are reference objects. In C++ that would be equivalent to using objects only through pointers, and always creating them with new. When you do this in C++, you also have to fill your array of pointers with new-ed objects:
myclass *array[10];
for (int i = 0 ; i != 10 ; i++) {
array[i] = new myclass();
}
...
for (int i = 0 ; i != 10 ; i++) {
delete array[i];
}
Allowing creation of object arrays in C++ was a choice dictated by need to let programmers allocate arrays of objects in the automatic area. It came with a tradeoff, because objects from which you make arrays must have a default constructors. This is not ideal, because the requirement of default constructor sounds arbitrary.
Java, on the other hand, was free from the automatic memory requirement, so they went for a simple solution that requires you to initialize objects individually.
Not so often need you to create objects of the same type as array with default constructor. Sometimes you want to call the custom constructor. Sometimes you want to instantiate the subclasses and store them in the array.
Note that Java array className[] obj is more equivalent to C++ array className* obj[n], not just className obj[n], because it's an array of references to the objects, not the array of objects themselves. As of Java-8 you cannot create an array of objects themselves (they are discussed as part of project Valhalla, but will not appear even in Java-9). When the objects themselves are stored in the array in C++, you must initialize the array. You cannot keep "nulls" or something like this there, because null is not an object, it's the reference (or pointer). When you create className* obj[n] array in C++ (which is more similar to Java className[] obj array), it's uninitialized as well.
Finally note that in Java-8 you can quite easily create all the objects instantiating them with default constructor like this:
className[] array = Stream.generate(className::new).limit(n).toArray(className[]::new);
What is allowed or not do is up to the language designers.
If you want to initialize all elements of an Array with a reference to the same object in Java you can use :
className[] obj = new clasName[2];
Arrays.fill(obj, new className());
or to create different objects and pass different arguments to each constructor
className[] obj = new className[] {new className(), new className()};
In Java, whenever you declare a variable, be it a member of an object or a local variable, it's either of primitive type (byte, char, ...) or of reference-type (pointer to object of some type).
Thus, there are no arrays of objects, only arrays of references.
In C++ you have the freedom and responsibility to choose how many indirections you do, how to allocate, free, construct and destroy objects, adding much complexity:
dereference-operator (*pointer)
dereference-and-use-member (pointer->member)
address-of-operator (&object)
a way to derive a pointer-to-type from other types (type* var).
placement-new (`new(pointer) type(arg1, arg2);
explicit delete-operator (delete pointer)
much more.
Related
Array DS requires all its members to have the same time. Java throws ArrayStoreException when an attempt has been made to store the wrong type of object into an array of objects. Don't remember what C++ does.
Is my understanding correct that it's important to have all objects of the same type in array because it guarantees constant time element access through the following two operations:
1) element size * element index = offset
2) array pointer address + offset
If objects are of different types and consequently different size, the above mentioned formula won't work.
Because: we want it like this.
What I mean is: people using the Java language (probably the same for C++) are using a statically typed language for a purpose.
And when such people starting thinking in plurals; they typically think in plurals of "similar" things.
Caveat: in Java, everything is an Object, so you can always declare an Object[] and stuff anything into that. Strings, Numbers, whatever.
And that also leads to the other important aspect: in C++, your array represents an area in memory. And you better have same sized elements in that area; to avoid data corruption.
In Java on the other hand, an array is not pointing to raw memory.
Long story short: there are real differences between Java and C++ in this context (that one has to understand to make an informed decision); and then there is the "language" thing itself. In other words: this is not Ruby land, where you just put ducks, numbers, plants and quack sounds in the same "list" without further thinking.
Final thought, based on that joke in the last paragraph: in my eyes, an array is an implementation of the list concepts, thus it is about a collection of things of the same nature. If you want a collection of unrelated things, I would rather call that a tuple.
Yes, you are right. All that is required for constant time random access.
Also, you can have an array of void pointers if you want to store different data types in a single array. For instance in c++, do
void * a[N]
a[i] = (void *)(&YourClass)
Similarly, use Object[] in java.
The C++ language (and compiler) requires the type of the elements to be stored in an array for various reasons, like pointer arithmetics and array subscription (e.g. x[i]), default initialisation of the elements, dealing with alignment restrictions, ...).
int x[3] = { 1,2,3 }; // array of 3 int values, each being properly aligned concerning processor architecture;
myObjectType objs[10]; // array of 10 objects of type myObjectType, each being default initialised (probably the default constructor), each being properly aligned
myObjectType *objs[10]; // array of 10 pointers to objects of type myObjectType (including subclasses of myObjectType; allowing dynamic binding and polymorphism). Note: all pointers have the same size, the object to which they point may differ insize.
int *intptr = x;
bool isEqual= (intptr[2] == x[2]); // gives true
intptr += 2; // increases the pointer by "2*sizeof(int)" bytes.
So, yes, you are right: one reason is because of calculating offsets; But there are other reasons as well, and other issues like alignment, array to pointer decay, default initialisation logic are probably more subtle but essential, too.
The Java language specification specifies that
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). All methods of class Object may be invoked on an array.
So, considering arrays are objects — why did the Java designers make the decision not to allow inherit and override from it, for example, toString() or equals()?
The current syntax wouldn't allow creating anonymous classes with an array as the base class, but I don't think that was the reason for their decision.
Java was a compromise between non-object languages and very slow languages of that time where everything was an object (think about Smalltalk).
Even in more recent languages, having a fast structure at the language level for arrays (and usually maps) is considered a strategic goal. Most people wouldn't like the weight of an inheritable object for arrays, and certainly nobody wanted this before JVM advances like JIT.
That's why arrays, while being objects, weren't designed as class instances ("An object is a class instance or an array"). There would be little benefit in having the ability to override a method on an array, and certainly not a great-enough one to counterbalance the need to check for the right method to apply (and in my opinion not a great-one enough to counterbalance the increased difficulty in code reading, similar to what happens when you override operators).
I came across UNDER THE HOOD - Objects and arrays which explains almost anything you need to know about how JVM handles arrays. In JVM, arrays are handled with special bytecodes, not like other objects we are familiar with.
In the JVM instruction set, all objects are instantiated and accessed
with the same set of opcodes, except for arrays. In Java, arrays are
full-fledged objects, and, like any other object in a Java program,
are created dynamically. Array references can be used anywhere a
reference to type Object is called for, and any method of Object can
be invoked on an array. Yet, in the Java virtual machine, arrays are
handled with special bytecodes.
As with any other object, arrays cannot be declared as local
variables; only array references can. Array objects themselves always
contain either an array of primitive types or an array of object
references. If you declare an array of objects, you get an array of
object references. The objects themselves must be explicitly created
with new and assigned to the elements of the array.
Arrays are dynamically created objects, and they serve as a container that hold a (constant) number of objects of the same type. It looks like arrays are not like any other object, and that's why they are treated differently.
I'd like to point out this article. It seems as though arrays and objects follow different opcodes. I can't honestly summarize it more than that however it seems, arrays are simply not treated as Objects like we're normally used to so they don't inherit Object methods.
Full credits to the author of that post as it's a very interesting read, both short & detailed.
Upon further digging into the topic via multiple sources I've decided to give a more elaborate version of my previous answer.
The first thing to note that instantiation of Objects and Arrays are very different within the JVM, their follow their respective bytecode.
Object:
Object instantiation follows a simple Opcode new which is a combination of two operands - indexbyte1 & indexbyte2. Once instantiated the JVM pushes the reference to this object onto the stack. This occurs for all objects irrespective of their types.
Arrays:
Array Opcodes (regarding instantiation of an array) however are divided into three different codes.
newarray - pops length, allocates new array of primitive types of type indicated by atype, pushes objectref of new array
newarray opcode is used when creating arrays that involve primitive datatypes (byte short char int long float double boolean) rather than object references.
anewarray - pops length, allocates a new array of objects of class indicated by indexbyte1 and indexbyte2, pushes objectref of new array
anewarray opcode is used when creating arrays of object references
multianewarray - pops dimensions number of array lengths, allocates a new multidimensional array of class indicated by indexbyte1 and indexbyte2, pushes objectref of new array
multianewarray instruction is used when allocating multi-dimensional arrays
Object can be a class instance or an array.
Take from Oracle Docs
A class instance is explicitly created by a class instance creation expression
BUT
An array is explicitly created by an array creation expression
This goes hand in hand with the information regarding the opcodes. Arrays are simply not developed to be class interfaces but are instead explicitly created by array creation expression thus naturally wouldn't implicitly be able to inherit and/or override Object.
As we have seen, it has nothing to do with the fact that arrays may hold primitive datatypes. After giving it some thought though, it isn't very common to come across situations where one might want to toString() or equals() however was still a very interesting question to try and answer.
Resources:
Oracle-Docs chapter 4.3.1
Oracle-Docs chapter 15.10.1
Artima - UnderTheHood
There are many classes in standard java library that you cannot subclass, arrays aren't the only example. Consider String, or StringBuffer, or any of the "primitive wrappers", like Integer, or Double.
There are optimizations that JVM does based on knowing the exact structure of these objects when it deals with them (like unboxing the primitives, or manipulating array memory at byte level). If you could override anything, it would not be possible, and affect the performance of the programs very badly.
I'm designing an API function of a class which will return an array for client to use.But I'm not quite sure whether I should make it a return value or make it as an argument of the function.See below:
Method I:
MyObject[] getMyObject() {... return someObject;}
Method II:
void getMyObject(MyObject[] someObject) {...//assign value to someObject[index]};
In Android API I saw it is very common to return a List<MyObject> or Set<MyObject>. Does it indicate Method I is better? So what are the pros and cons of these two methods in Java?
Update: In method II I mean to assign value to someObject[index], not someObject. My question is not regarding "does Java pass reference or value". It's just simply comparing two feasible way of doing things.
Arrays are not resizeable. So with method 1, you can create a new array with just the right size and return that. With method 2, if the incoming array is the wrong size, you're sunk.
Java does not have pass-by-reference. So assigning something to someObject in method 2 won't do anything for the caller. You can only alter the elements of someObject.
Both ways have advantages and disadvantages.
Version #1
MyObject[] getMyObject() {... return someObject;}
Pros:
This allows you to return an arbitrary number of results.
It is arguably easier for the caller.
Cons:
The called method has to allocate an array. (Alternatively, it has to manage / recycle arrays, which is going to be difficult to do in general. Note that reusing a static array is liable to make the method non-reentrant, etcetera.)
Version #2
void getMyObject(MyObject[] someObject) {...//assign value to someObject[index]};
Pros:
This is potentially better in terms of objects allocated because the caller will be in a better position to recycle / reuse the array.
It allows you to pass values in ... if that is a requirement.
Cons:
The caller has to provide the array, which makes the method more work to use.
The called method has no control over the array size. That means that there is a potential error case if the supplied array is too small ...
There is also a third way, where an array is passed and returned. If the array size is not correct (or maybe if a null is passed) the called method allocates or reallocates an array. The result is either the original array or the reallocated array.
Which is better?
IMO, the first version is better under most circumstances because it is easiest to get right. IMO, you should only consider the alternatives in an API design if there is a demonstrable need to minimize new object allocation. (If you are coding for a Hotspot Java implementation or equivalent, new object allocation is cheap ...)
Finally, a simpler / cleaner way than all of the above is to use a Collection rather than a bare array. Using a standard Collection type allows you to avoid the messiness of preallocating something of the correct size.
Return is more natural to write and read, also pass by "reference" as you call it has more complications than meets the eyes..
someObject[i] = a; //works
someObject = a; // doesnt work
Java has one parameter passing mechanism: everything is passed by value, not by reference.
It's subtle, but true. The implications matter.
You can certainly return any time from that method, be it array, List, or Set. You may or may not be able to alter the contents of the List or Set, because the implementation underneath might have been made unmodifiable by the developer who wrote the method.
Personally, I tend to prefer the collections over arrays. They are more expressive than raw arrays. If I get a Set back, I know that all the entries are unique in some way.
This question already has answers here:
Is an array an object in Java?
(14 answers)
Closed 9 years ago.
We know that Arrays are objects in Java. I believe to create an object in Object oriented languages(if not we can have it in a separate discussion), we need a blueprint of it(a class). But I'm not sure or cannot find the class for which the object is being created for arrays when the new operator is used. If there is a class for arrays in java, then how will the hierarchy look like?
If there is no class, then how are the objects instantiated? And what is the reason behind having an object type without a class?
Arrays are created by virtual machine with a special instruction called newarray, so think them as a special construct.
From JVM Spec:
3.9. Arrays
Java Virtual Machine arrays are also objects. Arrays are created and manipulated using a distinct set of instructions. The newarray instruction is used to create an array of a numeric type. The code:
Also read more from JLS for class hierarchy of an array.
The direct superclass of an array type is Object.
An array, let's say an Object[], is a special kind of variable, just as primitives are. Its type is Object[], not Object. Java is not a "fully" object oriented language, such as Ruby is; it has some special data types like arrays and primitives.
The logic is reverse to your.
An object is a class instance or an array.
But as Java is OOP language, everything must be represented as object. When you reflect your code you can use class java.lang.reflect.Array that represent Array.
arrays are not primitive in java. An array is a container object that holds a fixed number of values of a single type.
System.out.print(int[].class.toString());
It successfully prints and proves it has a concrete class in background and same applied for all other array types.
Find documentaion in detail.
Yes, Java has classes for arrays, see http://docs.oracle.com/javase/specs/jls/se7/html/jls-10.html#jls-10.8 Class Objects for Arrays, e.g.
Class<int[]> cls = int[].class;
These classes are dynamically created by JVM.
There is no hierarchy among arrays of primitive types
int[] a = new long[1];
Produces compile time error. The hiearchy of Object array types is the same as with Object types
Object[] a = new String[1];
Are arrays in Java pass by reference or pass by value?
Suppose I have an array called data that contains objects of some type. Now let us suppose that I pass and store that array in class A and then I pass it to class B and class B changes one of the entries of the array. Will class A's version of the array change? Does it matter if this was an array of primitives (such as int) instead? What about ArrayLists?
Everything in Java is pass-by-value. However, if you're passing a reference, it's the value of the reference.
Since Java methods can't reach into the caller's stack to reassign variables, no method call can change the identity of a reference (address) there. This is what we mean when we say Java is not pass-by-reference. This contrasts with C++ (and similar languages), which allows this in some cases.
Now let's look at some effects.
If I do:
Object[] o = ...
mutateArray(o);
the contents can be different afterwards, since all mutateArray needs is the address of an array to change its contents. However, the address of o will be the same. If I do:
String x = "foo";
tryToMutateString(x);
the address of x is again the same afterwards. Since strings are immutable, this implies that it will also still be "foo".
To mutate an object is to change the contents of it (e.g. successfully changing the last element of o, or trying to change the last letter of "foo" to 'd'). This should not be be confused with reassigning x or o in the caller's stack (impossible).
The Wikipedia section on call by sharing may shed additional light.
Arrays, like all other objects, are pass by reference (technically, you are passing a reference by value, but from the objects point of view, it is passed by reference). If you pass an array to a method and the method changes the array, the caller will see the changes. If you want to avoid having your copy modified, you need to copy it yourself. It doesn't matter whether the array contains primitives or objects. In general, this is the behavior you want, since passing by value would involve unnecessarily copying the (potentially large) array every time you use it as an argument.
The Jist of it is - everything in Java is passed by reference, unless it is a primitive.