Literally BUILD my own Multidemensional Jagged Array - java

Can anyone tell me what is wrong with this approach of creating an array, it seems still works :
Object [] a = new Object[5];
Object [] b = new Object[5];
Object [] c = new Object[5];
Object [] d = new Object[6];
Object [] e = new Object[5];
a[1] = b;
a[2] = c;
b[1] = d;
d[1] = e;
a[1][2] = c; // error, how do I make this work if I insist of building my array like this?
What exactly I just did? Is this technically a multidimensional Array? Why can't I use for example a[1][2][2] to access the element, how can I access my data in a similar fashion?

I assume you know that obj[] is actually a reference value, so, I am looking to "bring the object out of that reference value", so I can use the array operator[] to access the value. For example, I declare a 1D array, like what I have in my original question, so I can use a[1].[2] to acess the value store in the array stored in a[1]
Object [] a= new Object[5];
Object [] b= new Object[5];
a[1] = b;
So maybe a[1] then something that bring the OBJECT out of reference value in a[1], which is b[], then use [2] to bring out the value store at b[2].

Related

Why it's wrong when the variable of Object[] as elements of Object[] transfrom to Object[][]

I want to use object[] as the element of object[] to transform it to Object[][], but it can't run. So I want to know why it is wrong. And how can I achieve that giving a number k, and create a array that is k dimensional.
Here is the wrong code:
public static void main(String[] args) {
Object[] s = new Object[3];
s[0] = new Integer[1];
s[1] = new Integer[1];
s[2] = new Integer[1];
Object m = s;
Integer[][] t = (Integer[][])m;
System.out.println(Arrays.toString(t));
}
The type Object[][] is saying that the array can only contain other Object[] instances.
But an Object[] can also contain things that are not arrays of Object.
Note that when you cast from one reference type to another, no value conversion occurs, and the actual type of the object doesn't change. All that happens is that the runtime system checks that the object's actual runtime type is assignment compatible with the type you are casting to.
To illustrate why it has to be like this, consider the following:
Object[] s = new Object[2];
s[0] = new Integer[1];
Integer[][] t = (Integer[][]) s; // ONE
s[1] = "Hello";
Integer[] u = t[1]; // TWO
If (hypothetically!) the cast at "ONE" is allowed to succeed, then at "TWO" we would assign a String to a variable of type Integer[].
That cannot be allowed to happen. The cast must fail.
The second part of your question is this:
And how can I achieve that giving a number k, and create a array that is k dimensional.
It depends on what you mean:
You can create a custom class that behaves like a K-dimensional array, though you won't be able use Java array syntax to access and update cells.
You can construct a K-dimensional array out of Object[] objects, though you will need to do a lot of type-casting to use it. And under no circumstances will you be able to cast it to an array with a higher number of dimensions.
You can use java.lang.reflect.Array.newInstance(Class, int...) to create an array with K dimensions. The only problem that the declared type is Object so you still need a type cast:
Integer[][][] array = Array.newInstance(Integer.class, 3, 3, 3);
However, if you want K to be a parameter, then
int[] dimensions = new int[K];
for (int i = 0; i < K; i++) {
dimensions[i] = 2;
}
Object array = Array.newInstance(Integer.class, dimensions);
The problem is that when K is a parameter, you cannot declare a variable whose Java type is a K-dimensional array of Integer. If you want to subscript the array using [], you will need to resort to something like this:
switch (K) {
case 1:
Integer[] oneD = (Integer[]) array;
oneD[1] = 42;
break;
case 2:
Integer[][] twoD = (Integer[][]) array;
twoD[1][1] = 42;
break;
// etcetera
}
To answer the part
And how can I achieve that
You can do the below transform
Integer[][] t = Arrays.stream((Object[])m).map(Integer[].class::cast).toArray(Integer[][]::new);

java.lang.ClassCastException - Accessing Java array of Object arrays like 2 dimensional object array

In order to troubleshoot the Object array created in C code with JNI, I have created the pure Java code with an array of Object arrays as follows.
I would like to access this array in the manner like two dimensional Object array (Object[][]) using [][] operator. However the code crashes when casting the array to Object[][] with the following exception.
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to
[[Ljava.lang.Object
Object[] outerArray = new Object[3];
outerArray[0] = new Object[] {1,2,3,4,5};
outerArray[1] = new Object[] {10,20,30,40,50};
outerArray[2] = new Object[] {100,200,300,400,500};
Object o = ((Object[])outerArray[0])[0]; // (1) OK but awkward
Object[][] = (Object[][])outerArray; // (2) Runtime error!!
o = outerArray[0][0]; // (3) I want to do this
Can anyone help me?
When declaring an array with one dimension, then adding arrays inside each cell, you're building this:
[ [][][] ] [ [][][] ] [ [][][] ]
Which cannot be accessed using [][] since it has only 1 row and each cell has another row of objects, therefor it needs to be accessed with the "awkward cast"
If you want a column structure:
[] [] []
[] [] []
[] [] []
It should be created with this:
Object[][] outerArray = new Object[3][5];
When an array is created it always has a type. The purpose is to protect you from a class of programming errors, when the items stored in the array are later read and "used" as another type (*). The type of your array is Object[].class and you can't cast it to Object[][].class just because the objects inside the array are Object[]. You could put Integer's as well, and the system would not throw ArrayStoreException because Integer is a subtype of Object.
Either you create (and declare) your array as Object[][] or use the "awkward" cast.
(*) still this can happen and you don't know until runtime
public class ArraysQuirks {
public static void main(String... args) {
String[] strings = {"a", "b", "c"};
Object[] objects = strings;
objects[0] = 1; // ArrayStoreException here
}
}
Object[][] = (Object[][])outerArray; // (2) Runtime error!!
here is a Syntax Error.Object[][] means you will declare an multiple Array of Object.just change like this:
Object[][] temp= (Object[][])outerArray; //it works

Multiple types on a Java multi-dimensional array

From what I know, only one type of object/literal can be stored on a multi-dimensional Java array.
so for instance, on a 2-dim'l array a[][], I can not store
a Type-1 array on a[0] and Type-2 array on a[1] unless there's some polymorphic relationship between Type-1 & Type-2 and I put it into use there.
I'm looking to verify that there's no way to get around this. so, I cannot somehow put an int array on a[0], a char array on a[1]-- Java arrays are single-type.
I'm aware that I can declare 2 parallel arrays-- one int[] and one char[] and that solves it.
Thanks in advance.
//=====================
Edit: The good old object class solves it-- as the useful answers below pointed out. Thank you for your input.
You can use Object[].
Object[] arrays = new Object[2];
arrays[0] = new int[10];
arrays[1] = new char[10];
You can use an array of Objects:
Object[] x = new Object[2];
x[0] = new Integer[3];
x[1] = new String[3];

why can't cast Object[] to String[]

No error
Object[] a = new String[]{"12","34","56"};
String[] b = (String[]) a;
No error
Object a = new String[]{"12","34","56"};
String[] b = (String[]) a;
Run time error : ClassCastException
Object[] a = new Object[3];
a[0] = "12";
a[1] = "34";
a[2] = "56";
String[] b = (String[]) a;
Run time error : ClassCastException
Object[] a = {"12","34","56"};
String[] b = (String[]) a;
Of course, we can downcast an Object[] variable back to String[] if it was created as an String[].
My question is why we can not cast Object[] to String[] when it was created as Object[] but all its members are String? Is it because of security reason or just not that useful to implement this?
Here's two reasons I can think of.
Firstly, if you change the original array, the casted array can become invalid. e.g.
Object[] a = {"12","34","56"};
String[] b = (String[]) a; // pretend this is legal. a and b now point to the same array
a[0] = new Object(); // clearly ok
String x = b[0]; // No longer a string! Bad things will happen!
Secondly, the example you have chosen is very simple, but if you have a very large Object[] array and it's not clear to the compiler what is filling it, then it has no way of validating that every element of the array satisfies the cast.
Object[] a = new Object[10000];
// lots of weird and whacky code to fill the array with strings
String[] b= (String[]) a; // valid or no? The best-defined answer is to say no.
It is defined in the JLS #5.5.3. In substance, a cast:
r = new RC[]; TC[] t = (TC[]) r;
"works" at runtime iif RC is a subtype of TC (or TC itself). Whether RC actually only contains TCs is irrelevant and the compile-time type of r is not used either (what matters is the runtime type):
you can write: r = new String[]; Object[] t = (Object[]) r;, but
you can't write r = new Object[]; String[] t = (String[]) r;.
JLS extract:
If T is an array type TC[], that is, an array of components of type TC, then a run-time exception is thrown unless one of the following is true:
TC and RC are the same primitive type.
TC and RC are reference types and type RC can be cast to TC by a recursive application of these run-time rules for casting.
In your examples 3 and 4, RC = Object and TC = String and Object is not a subtype of String.
In your examples 1 and 2, RC = String and TC = String so it works.
Note: the type in this context is the runtime type.
Because you are not casting individual member of array, you are casting the whole array instance which is of type Object[] and not String[].
Object[] a = new String[]{"12","34","56"};
Here the instance is of type String[] and the compile time type is Object[].
And in the next line you are casting it back to String[] which is allowed as the actual type or runtime type is String[].
But Object[] a = new Object[3]; here the actual type and Compile time type is Object[] and it is not String[]. So an Object[] cannot be String[].
Object[] a = new Object[1];
a[0] = "a"; //Actual type String
So you can do this:
String aStr = (String)a[0];
Array objects are not just a collection of their elements, they have classes just like other objects. The class for array of strings is a subclass of array of objects. That's why there's no error in your 1 or 2, but the last two are equivalent to
Object o = new Object();
String s = (String) o;
If all members Object array were Strings at the moment of casting you still could assign objects that are not Strings to the elements of this array later. So you would have String array with elements which are not Strings.
This post provides a way to quickly create a String[] out of an Object[].
arrayOfUrls = imageUrls.toArray(new String[imageUrls.size()]);
Assuming of course that imageUrls is not null.

How to handle an object array of Object Arrays

I have this code:
Object [] array=new Object array [5];
array[0]= new Object[3];
array[1]=new Object [10];
array[2]=new Object [7];
...
How can I access the 5th element of array[1].
If it was a 2D array I would say:
Object o=array [1][5];
but I don't want 2D array because I don't want to waste memory since the size varies from array to array.
It would be great if someone could answer me this question..
Btw I don't want to use vectors etc...
Thank you
You could do it like this:
//This creates a 5 by ? array
Object[][] array = new Object[5][];
array[0] = new Object[3];
array[1] = new Object[10];
array[2] = new Object[7];
....
edit (thanks to the commenters) :
array is an array of arrays. Each element in array refers to an array of Objects.
The memory is not wasted on having more elements than needed.
It will look like this
[a00][a01][a02]
[a10][a11][a12][a13][a14][a15][a16][a17][a18][a19]
[a20][a21][a22][a23][a24][a25][a12]
If you now would like to access the 6th element of the 2nd array you would do this:
Object myObj = array[1][5];

Categories