Can we create an object without parentheses? - java

According to this site the syntax for creating a Java object is:
<JavaType> <variable> = new <JavaObject>();
Though you don't use any parantheses when creating an Array object and instead type brackets which contains the length of each dimension.
Example:
String[][] stringMatrix = new String[5][10];
What I am wondering is if this syntax is specifically and only for creating an Array object or I can make a custom class whose objects are created in a different way then usual
new <JavaObject>();
statement.

new keyword is used to allocate memory for the specific type, which is followed by new keyword.
MyClass obj = new MyClass();
Above line will create an object (allocate memory) for MyClass and initialize member variable by invoking default constructor.
But, below line of code will only allocate memory and initialize each element of array with default value null.
MyClass[][] objMatrix = new MyClass[5][10];
So, we are just declaring an array of size 5x10(allocating memory), but each element in array need some object reference (since, currently they have null reference). So, for that reason, you need to initialize each objMatrix array element by creating object of MyClass and assigning them to each element.
objMatrix[0][0] = new MyClass();

It is specifically for creating arrays. You're stuck with parentheses for your classes.

You can not create a custom class that changes the way the new operator works. However, there are some special cases where an object can be created without the usual new operator.
E.g.
String[] array = { "foo", "bar", "baz" };
Integer value = 42;
demonstrating that you can create arrays without the new keyword in a variable initializer, use String objects using literals and autobox primitive values to their object counterpart without the usual new syntax, but of course, this is not possible with custom types.
Another possibility to create objects without the new operator is deserializing them, which also works for custom types if they are Serializable.
Starting with Java 8, you can use constructor references if you have an appropriate context, e.g.
BigDecimal[] array = new BigDecimal[20];
Arrays.setAll(array, BigDecimal::new);
System.out.println(Arrays.toString(array));
Here, BigDecimal::new is a reference to a constructor of BigDecimal and it is implied from the context, i.e. Arrays.setAll that the function must be able to consume an int value, as the setAll method will evaluate it for every array element, passing the array index, so we initialize the array with ascending numbers in this example.
Another example would be
BigDecimal[] array = Stream.of("1.23", "4.56", "7.89")
.map(BigDecimal::new)
.toArray(BigDecimal[]::new);
System.out.println(Arrays.toString(array));
where it is implied from the context that the constructor used in the .map(BigDecimal::new) step must consume a String, as it will be evaluated for every stream element, ending up at a different constructor than in the first example.
BigDecimal is an ordinary class and these examples would work with a custom class as well, if it has matching constructors.

Related

Creating a Generic array without using Arraylist

In order to complete one of my Java assignments, I have to do what seems like the impossible.
I have to create a method that takes in different stuff and plugs it into an array. We don't necessarily know what is being put into the array and thus the array must be able to accept Strings, Double, Integer, etc...
Of course, the obvious solution would be to use ArrayList<E> (i.e. a generic array). However, that's partly the complication of the problem. We cannot use an ArrayList, only a regular array. As far as I can find, when creating an array its intake value must be declared. Which leads me to believe that this assignment is impossible (yet I doubt the teacher would give me an impossible assignment).
Any suggestions?
You can always use an array of Object - Object[].
Object[] objects = new Object[2];
objects[0] = "ABC";
objects[1] = Integer.valueOf("15");
Are you sure you need a generic array or an array that can hold anything?
If the former, then create a class that will act as wrapper of Object[] array and use a <T> generic for type cast when getting the elements of the array, which is similar to the implementation of ArrayList class. If the latter, use Object[] directly.

Object type in Java and referencing arrays

public class RefMix {
public static void main(String[] args) {
Object[] a = {null, "foo"};
Object[] b = {"bar", b};
a[0] = b;
System.out.println(a[0][0]);
}
}
My understanding is that arrays are objects in Java, and therefore a subclass of the Object type. My further understanding is that a 2-dim array is implemented as an array of references to arrays. Therefore I don't understand why my a[0][0] does not produce bar in the code above. Instead it doesn't compile:
RefMix.java:7: array required, but java.lang.Object found
My understanding is that arrays are objects in Java, and therefore a subclass of the Object type. My further understanding is that a 2-dim array is implemented as an array of references to arrays.
This is all correct and explains why you can do the assignment
a[0] = b;
without any complaints from the compiler.
Therefore I don't understand why my a[0][0] does not produce bar in the code above.
Okay, let's take a look at the types in this expression:
a is a Object[] -- that is an array of Objects
a[0] is an Object
a[0][0] -- Now you are trying to use an array subscript on an Object. The compiler does not know that the Object is in fact an array, so it complains.
The runtime type of an object instance differs from the statically inferred type. The compiler will try to estimate what type each variable could be in the program, in order to catch certain types of errors early. In this case, a[0] will always be an array, but the compiler doesn't know this. Since you are getting an object out of an object array, all the compiler knows is that a[0] is an object. Therefore it raises an error.
In cases where you know something will always be a certain type but the compiler can't figure it out, you can get around this by inserting an explicit cast.
System.out.println(((Object[])a[0])[0]);
You are right, arrays are always Objects in Java, but Objects are not always arrays, therefore you get a compile error, because a is an Object[] (one dimensional). You can not access
a[0][0];
because a is not a two dimensional array (at least it's not declared as such). However in this case, you are sure, that a[0] is an array of Objects. Therefore, you can do this:
Object[] c = (Object[]) a[0];
System.out.println(c[0]);
// or directly:
System.out.println(((Object[])a[0])[0]);
This casts the return type of a[0] (which is Object), into a Object[] and you can then access the "second layer" of the array.
Since array in Java is an object, so the 1st and 2nd assignment, will store your array as the 1st element of your Object array..
Object[] a = {null, "foo"};
Object[] b = {"bar", b};
Now, you have changed your 1st element of a object array to contain value b instead of array.. But since it is an array of object. Everything coming out of it will be object..
Since a[0] is an object..
So, you clearly can't access something like this: -
System.out.println(a[0][0]);
You can try to typecast your object a[0] to object array..: -
System.out.println(((Object[])a[0])[0]);
Do:
System.out.println(((Object[])a[0])[0]);
This will "cast" the object to an object array at runtime.
As I do a lot of C++ coding lately, I find that Java is a lot more strict in type checking then C++ is. Java sees everything but primitive types as Object but Java goes one step further in distinguishing Array and non-Array types. During assignment like "a[0] = b;" , Java first check to see if it is an Array type or not, after that it goes through regular polymorphic type checking procedure. If you wish to make your code work, you should do...
Object[][] a = {{null}, {"foo"}};
Object[] b = {"bar", new java.util.Date()};
a[0] = b;
You can see how java take special care on array types by looking into Java Class signature that is passed to Class.forName() as parameter. For example, data type ..
com.foo.Bar[][] barsIn2D;
can be loaded with signature below...
// [ => Array
// [[ => Array of Array type
// L<object>; => Object, not Array
Class.forName("[[Lcom/foo/Bar;");
As you see, signature starts with either '[' or 'L'.
This tells us whether its an array or not takes precedence over "Lcom/foo/Bar;".
Everything that you are doing is equivalent to this
Object a = {"bar", "foo"};
System.out.println(a[0]);
which doesn't compile either.

Resolving ClassCastException in this code

I have this method getData as shown .
It is expecting an array of bag Objects as shown
please see the code below :
public static String getData(Bag[] bag)
{
}
public class Bag
{
public char side;
}
But , when i tried i am getting ClassCastException .
I have done this way :
Object bagArray[] = new Object[1];
Bag bagData = new Bag();
bagData.side = 'S';
bagArray[0]=bagData;
String bagData = ApplicationUtil.getData(Bag[]) bagArray);
Please let me , how to resolve this error ??
Why are you creating an Object array rather than an array of Bag objects?
Try just changing the first line to Bag[] bagArray = new Bag[1].
As an Object array can hold any kind of object, so I don't think it can be cast to a Bag array. You could however cast bagArray[0] to a Bag object.
In future, try using a List or other collection rather than an array for stuff like this.
The problem is that bagArray is an array of Object and not an array of Bag.
Either change that to Bag bagArray[] = new Bag [1]; or use a Collection (e.g. List) instead - note that you can cast List<Object> to List<Bag> but that is an unsafe operation and not recommended unless you know what you're doing.
You're trying to cast an Object[] into a Bag[]. Not allowed.
You bagArray is an Object array and not a Bag array. Just because it is capable of holding an object of type Bag (which is a subclass of Object), does not mean the vice versa. You are trying to cast Object to Bag type, which is not allowed. Define you bag array in the following way
Object bagArray[] = new Bag[];
See this question: Quick Java question: Casting an array of Objects into an array of my intended class
As others have said, you can't cast an Object[] to, well, anything. In this case, you have a Bag inside an Object array, so in this specific instance it seems like it might work. But imagine that you had a larger array, full of objects of different types. In that case, the cast wouldn't work. The program has to work for the general case.
You can solve this by:
1) Using a Bag[] type instead of Object[]
2) Using a List - collections are nearly always better
3) Using the Arrays class to create a new Bag[]: Arrays.copyOf(bagArray,bagArray.length,Bag[].class)

How is length implemented in Java Arrays?

I was wondering about the implementation of length of a Java Array. I know that using arrayName.length gives us the number of elements in the array, but was wondering if this is a method / function or it is just a data member of Array?
I guess it must be a data member as we do not use parenthesis() when invoking it. But if it is a data member how/when is the value of this length assigned/computed?
According to the Java Language Specification (specifically §10.7 Array Members) it is a field:
The public final field length, which contains the number of components of the array (length may be positive or zero).
Internally the value is probably stored somewhere in the object header, but that is an implementation detail and depends on the concrete JVM implementation.
The HotSpot VM (the one in the popular Oracle (formerly Sun) JRE/JDK) stores the size in the object-header:
[...] arrays have a third header field, for the array size.
You're correct, length is a data member, not a method.
From the Arrays tutorial:
The length of an array is established when the array is created. After creation, its length is fixed.
If you have an array of a known type or is a subclass of Object[] you can cast the array first.
Object array = new ????[n];
Object[] array2 = (Object[]) array;
System.out.println(array2.length);
or
Object array = new char[n];
char[] array2 = (char[]) array;
System.out.println(array2.length);
However if you have no idea what type of array it is you can use Array.getLength(Object);
System.out.println(Array.getLength(new boolean[4]);
System.out.println(Array.getLength(new int[5]);
System.out.println(Array.getLength(new String[6]);
Yes, it should be a field. And I think this value is assigned when you create your array (you have to choose the length of array while creating, for example: int[] a = new int[5];).
I believe its just a property as you access it as a property.
String[] s = new String[]{"abc","def","ghi"}
System.out.println(s.length)
returns 3
if it was a method then you would call s.length() right?
From the JLS:
The array's length is available as a
final instance variable length
And:
Once an array object is created, its
length never changes. To make an array
variable refer to an array of
different length, a reference to a
different array must be assigned to
the variable.
And arrays are implemented in the JVM. You may want to look at the VM Spec for more info.
It is a public final field for the array type. You can refer to the document below:
http://java.sun.com/docs/books/jls/third_edition/html/arrays.html#10.7
Every array in java is considered as an object. The public final length is the data member which contains the number of components of the array (length may be positive or zero)
Java arrays, like C++ arrays, have the fixed length that after initializing it, you cannot change it. But, like class template vector - vector <T> - in C++ you can use Java class ArrayList that has many more utilities than Java arrays have.

Convert ArrayList<String> to String[] array [duplicate]

This question already has answers here:
Converting 'ArrayList<String> to 'String[]' in Java
(17 answers)
Closed 8 years ago.
I'm working in the android environment and have tried the following code, but it doesn't seem to be working.
String [] stockArr = (String[]) stock_list.toArray();
If I define as follows:
String [] stockArr = {"hello", "world"};
it works. Is there something that I'm missing?
Use like this.
List<String> stockList = new ArrayList<String>();
stockList.add("stock1");
stockList.add("stock2");
String[] stockArr = new String[stockList.size()];
stockArr = stockList.toArray(stockArr);
for(String s : stockArr)
System.out.println(s);
Try this
String[] arr = list.toArray(new String[list.size()]);
What is happening is that stock_list.toArray() is creating an Object[] rather than a String[] and hence the typecast is failing1.
The correct code would be:
String [] stockArr = stockList.toArray(new String[stockList.size()]);
or even
String [] stockArr = stockList.toArray(new String[0]);
For more details, refer to the javadocs for the two overloads of List.toArray.
The latter version uses the zero-length array to determine the type of the result array. (Surprisingly, it is faster to do this than to preallocate ... at least, for recent Java releases. See https://stackoverflow.com/a/4042464/139985 for details.)
From a technical perspective, the reason for this API behavior / design is that an implementation of the List<T>.toArray() method has no information of what the <T> is at runtime. All it knows is that the raw element type is Object. By contrast, in the other case, the array parameter gives the base type of the array. (If the supplied array is big enough to hold the list elements, it is used. Otherwise a new array of the same type and a larger size is allocated and returned as the result.)
1 - In Java, an Object[] is not assignment compatible with a String[]. If it was, then you could do this:
Object[] objects = new Object[]{new Cat("fluffy")};
Dog[] dogs = (Dog[]) objects;
Dog d = dogs[0]; // Huh???
This is clearly nonsense, and that is why array types are not generally assignment compatible.
An alternative in Java 8:
String[] strings = list.stream().toArray(String[]::new);
I can see many answers showing how to solve problem, but only Stephen's answer is trying to explain why problem occurs so I will try to add something more on this subject. It is a story about possible reasons why Object[] toArray wasn't changed to T[] toArray where generics ware introduced to Java.
Why String[] stockArr = (String[]) stock_list.toArray(); wont work?
In Java, generic type exists at compile-time only. At runtime information about generic type (like in your case <String>) is removed and replaced with Object type (take a look at type erasure). That is why at runtime toArray() have no idea about what precise type to use to create new array, so it uses Object as safest type, because each class extends Object so it can safely store instance of any class.
Now the problem is that you can't cast instance of Object[] to String[].
Why? Take a look at this example (lets assume that class B extends A):
//B extends A
A a = new A();
B b = (B)a;
Although such code will compile, at runtime we will see thrown ClassCastException because instance held by reference a is not actually of type B (or its subtypes). Why is this problem (why this exception needs to be cast)? One of the reasons is that B could have new methods/fields which A doesn't, so it is possible that someone will try to use these new members via b reference even if held instance doesn't have (doesn't support) them. In other words we could end up trying to use data which doesn't exist, which could lead to many problems. So to prevent such situation JVM throws exception, and stop further potentially dangerous code.
You could ask now "So why aren't we stopped even earlier? Why code involving such casting is even compilable? Shouldn't compiler stop it?". Answer is: no because compiler can't know for sure what is the actual type of instance held by a reference, and there is a chance that it will hold instance of class B which will support interface of b reference. Take a look at this example:
A a = new B();
// ^------ Here reference "a" holds instance of type B
B b = (B)a; // so now casting is safe, now JVM is sure that `b` reference can
// safely access all members of B class
Now lets go back to your arrays. As you see in question, we can't cast instance of Object[] array to more precise type String[] like
Object[] arr = new Object[] { "ab", "cd" };
String[] arr2 = (String[]) arr;//ClassCastException will be thrown
Here problem is a little different. Now we are sure that String[] array will not have additional fields or methods because every array support only:
[] operator,
length filed,
methods inherited from Object supertype,
So it is not arrays interface which is making it impossible. Problem is that Object[] array beside Strings can store any objects (for instance Integers) so it is possible that one beautiful day we will end up with trying to invoke method like strArray[i].substring(1,3) on instance of Integer which doesn't have such method.
So to make sure that this situation will never happen, in Java array references can hold only
instances of array of same type as reference (reference String[] strArr can hold String[])
instances of array of subtype (Object[] can hold String[] because String is subtype of Object),
but can't hold
array of supertype of type of array from reference (String[] can't hold Object[])
array of type which is not related to type from reference (Integer[] can't hold String[])
In other words something like this is OK
Object[] arr = new String[] { "ab", "cd" }; //OK - because
// ^^^^^^^^ `arr` holds array of subtype of Object (String)
String[] arr2 = (String[]) arr; //OK - `arr2` reference will hold same array of same type as
// reference
You could say that one way to resolve this problem is to find at runtime most common type between all list elements and create array of that type, but this wont work in situations where all elements of list will be of one type derived from generic one. Take a look
//B extends A
List<A> elements = new ArrayList<A>();
elements.add(new B());
elements.add(new B());
now most common type is B, not A so toArray()
A[] arr = elements.toArray();
would return array of B class new B[]. Problem with this array is that while compiler would allow you to edit its content by adding new A() element to it, you would get ArrayStoreException because B[] array can hold only elements of class B or its subclass, to make sure that all elements will support interface of B, but instance of A may not have all methods/fields of B. So this solution is not perfect.
Best solution to this problem is explicitly tell what type of array toArray() should be returned by passing this type as method argument like
String[] arr = list.toArray(new String[list.size()]);
or
String[] arr = list.toArray(new String[0]); //if size of array is smaller then list it will be automatically adjusted.
The correct way to do this is:
String[] stockArr = stock_list.toArray(new String[stock_list.size()]);
I'd like to add to the other great answers here and explain how you could have used the Javadocs to answer your question.
The Javadoc for toArray() (no arguments) is here. As you can see, this method returns an Object[] and not String[] which is an array of the runtime type of your list:
public Object[] toArray()
Returns an array containing all of the
elements in this collection. If the collection makes any guarantees as
to what order its elements are returned by its iterator, this method
must return the elements in the same order. The returned array will be
"safe" in that no references to it are maintained by the collection.
(In other words, this method must allocate a new array even if the
collection is backed by an Array). The caller is thus free to modify
the returned array.
Right below that method, though, is the Javadoc for toArray(T[] a). As you can see, this method returns a T[] where T is the type of the array you pass in. At first this seems like what you're looking for, but it's unclear exactly why you're passing in an array (are you adding to it, using it for just the type, etc). The documentation makes it clear that the purpose of the passed array is essentially to define the type of array to return (which is exactly your use case):
public <T> T[] toArray(T[] a)
Returns an array containing all of the
elements in this collection; the runtime type of the returned array is
that of the specified array. If the collection 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
collection. If the collection fits in the specified array with room to
spare (i.e., the array has more elements than the collection), the
element in the array immediately following the end of the collection
is set to null. This is useful in determining the length of the
collection only if the caller knows that the collection does not
contain any null elements.)
If this collection makes any guarantees as to what order its elements
are returned by its iterator, this method must return the elements in
the same order.
This implementation checks if the array is large enough to contain the
collection; if not, it allocates a new array of the correct size and
type (using reflection). Then, it iterates over the collection,
storing each object reference in the next consecutive element of the
array, starting with element 0. If the array is larger than the
collection, a null is stored in the first location after the end of
the collection.
Of course, an understanding of generics (as described in the other answers) is required to really understand the difference between these two methods. Nevertheless, if you first go to the Javadocs, you will usually find your answer and then see for yourself what else you need to learn (if you really do).
Also note that reading the Javadocs here helps you to understand what the structure of the array you pass in should be. Though it may not really practically matter, you should not pass in an empty array like this:
String [] stockArr = stockList.toArray(new String[0]);
Because, from the doc, this implementation checks if the array is large enough to contain the collection; if not, it allocates a new array of the correct size and type (using reflection). There's no need for the extra overhead in creating a new array when you could easily pass in the size.
As is usually the case, the Javadocs provide you with a wealth of information and direction.
Hey wait a minute, what's reflection?

Categories

Resources