javac allows below syntax,
int[][][] i = new int[4][0][2];
which has zero length index that prevents access beyond.
1) There is no way to access third dimension. zero length dimension as last dimension(int[][][] i = new int[4][2][0];) looks fine.
2) It is not possible to write an initialiser for a multi-dimensional array with a zero length dimension unless that dimension is the last( for instance int[2][3][0]).
Why java allows such syntax?
Note: this question has nothing to do with int[0]
Because nothing in the multianewarray bytecode instruction prevents you from doing so.
There is really no better answer than that... The fact is that for any X, even if X is a primitive, then X[] is a class, X[][] is a class and so on; and you are free to choose the "dimensions" of the array.
Note how declaring a X[n][] and a X[n][m] array differ: in the first you'll declare a anewarray of X[] whereas in the second you'll declare a multianewarray of X.
Of course, in X[m][n][p], there is no possibility to ever have a "third dimension" (p) if n is 0, but... Well, the programmer knows what he's doing, right?
Just another bizarreness of arrays in the JVM... Think nothing of it except that "it can happen" ;)
I agree with #m0skit0 - I think this is a duplicate questions. However I will give a brief answer anyways.
Basically its an alternative for null. Consider simply, you have a method that returns an array, but it has no value to return. You could return null, but then you have to check for null in your code. On the other hand, you could return a 0 length array. Code such as the follows would automatically be skipped.
for(int p = 0; p < array.length; p++) {
So you can do perfectly acceptable stuff like:
public static final int[][][] EMPTYARRAY = new int[0][0][0];
note also things a much worse than you suppose because this is also legal:
public static final int[] SCREWEDARRAY = new int[-1];
which causes a runtime error:
java.lang.ExceptionInInitializerError
Caused by: java.lang.NegativeArraySizeException
First of all, it's not just in "the middle". You can easily define a one dimensional array just as easily:
int[] a = new int[0];
Second, an array with zero length is a bit like an empty collection. It's a legal data structure which might be returned by a method, but which happens to be empty.
Related
So for my research group I am attempting to convert some old C++ code to Java and am running into an issue where in the C++ code it does the following:
method(array+i, other parameters)
Now I know that Java does not support pointer arithmetic, so I got around this by copying the subarray from array+i to the end of array into a new array, but this causes the code to run horribly slow (I.e. 100x slower than the C++ version). Is there a way to get around this? I saw someone mention a built-in method on here, but is that any faster?
Not only does your code become slower, it also changes the semantic of what is happening: when you make a call in C++, no array copying is done, so any change the method may apply to the array is happening in the original, not in the throw-away copy.
To achieve the same effect in Java change the signature of your function as follows:
void method(array, offset, other parameters)
Now the caller has to pass the position in the array that the method should consider the "virtual zero" of the array. In other words, instead of writing something like
for (int i = 0 ; i != N ; i++)
...
you would have to write
for (int i = offset ; i != offset+N ; i++)
...
This would preserve the C++ semantic of passing an array to a member function.
The C++ function probably relied on processing from the beginning of the array. In Java it should be configured to run from an offset into the array so the array doesn't need to be copied. Copying the array, even with System.arraycopy, would take a significant amount of time.
It could be defined as a Java method with something like this:
void method(<somearraytype> array, int offset, other parameters)
Then the method would start at the offset into the array, and it would be called something like this:
method(array, i, other parameters);
If you wish to pass a sub-array to a method, an alternative to copying the sub-array into a new array would be to pass the entire array with an additional offset parameter that indicates the first relevant index of the array. This would require changes in the implementation of method, but if performance is an issue, that's probably the most efficient way.
The right way to handle this is to refactor the method, to take signature
method(int[] array, int i, other parameters)
so that you pass the whole array (by reference), and then tell the method where to start its processing from. Then you don't need to do any copying.
I have this method:
//not related to the error, but included for reference
ArrayList<ArrayList<Color>> a = new ArrayList<ArrayList<Color>>();
void addColorToList(float[] j) //this array always length 3
{
float[] k = Arrays.copyOf(j, 3);
Arrays.sort(k);
//Error in the following line
a.get(Arrays.asList(j).indexOf(k[0])).add(new Color(j[0], j[1], j[2]));
}
and this error:
Exception in thread "AWT-EventQueue-1"
java.lang.ArrayIndexOutOfBoundsException: -1
I've determined that my code always calls a.get() with -1, because Arrays.asList(j). indexOf(k[0]) does not find the element. However, I cannot figure out why this doesn't work as I would expect it to. I tried printing out the result of Arrays.asList(j), but I'm not really sure what to make of the result: [[F#307af497]. Can anybody tell me what the issue is?
Lets start with this:
I tried printing out the result of Arrays.asList(j), but I'm not really sure what to make of the result: [[F#307af497].
You are printing a list using (effectively) the toString() method. So ...
The outer '[' and ']' are from the list formatting.
You have a list consisting of one element.
That element is an array of float. (The [F#307af497 is produced by Object.toString(), and [F is how the type float[] is rendered ...)
This is actually an important clue. Arrays.asList(float[]) is returning a "list of float[]" ...
But why?
Well, because that's what it is supposed to do!!
The Arrays.asList signature is Arrays.asList<T>(T ...). That means it expects either an explicit T[] ... or a sequence of zero or more T instances, which it will then wrap as an Object[]. The Object[] is then wrapped as a List<Object> (roughly speaking).
The critical thing here is that the actual type T must be a reference type ... not a primitive type.
But your code seems to be expecting an overloaded method like this Arrays.asList(float ...) ... and expecting that that will give you your float[] wrapped as a List<Float>.
Unfortunately, there is no such overload for asList.
So what is actually happening is that:
your call is binding to Arrays.asList<float[]>(float[] ...)
the varargs is causing j to be wrapped in an array; i.e. equivalent to new float[][]{j}
the result is an instance of List<float[]> ... with one element.
So what is the solution?
In general ...
One solution would be to represent your floats as a Float[] rather than a float[]. Ideally, you would push this change back through the code that created the array in the first place, etcetera.
A second solution would be to convert the float[] to a Float[] before calling asList. The simple way to do that is with a simple loop. (There may also be a 3rd-party library for doing this.) The downsides are:
the conversion needs to happen each time you call this method which could be expensive if you call it a lot, and
there is no connection between the original array and the array that you have wrapped ... if you wanted to update the array through the list wrapper.
But in this case, the best solution is to simply replace this:
Arrays.asList(j).indexOf(k[0])
with a simple loop that iterates over the original float[] testing for an entry that matches k[0].
The moral of this story: you can easily shoot yourself in the foot by striving for an elegant solution in Java.
Often, dumb code is better. (Both faster, and more correct.)
This question already has answers here:
length and length() in Java
(8 answers)
Closed 6 years ago.
I've noticed that when doing the length of an array you write something like:
arrayone.length;
However, for such things as array lists or a string, you write a bracket on the end, such as the following for the length of the String:
stringone.length();
What is the key reason for this and how do you know when to put the brackets or now?
.length;
directly accesses a field member.
.length();
invokes a method (i.e. an accessor) to access a field member.
in the case of String, this is to be expected since it's immutable.
Arrays are handled differently than Strings or ArrayLists or anything else that can be counted in Java. An Array is pretty much a native type and it's length can never be changed after it is initialized, so there's no need for encapsulation. The length variable can be directly exposed with no side effects.
The reason why String uses a method instead of a variable is because it internally uses a char[] that it doesn't want to expose publicly (for immutability/encapsulation), so it wraps the length variable in a length() method. It's the same reason ArrayList has a size() method instead of a length variable.
The only time you'll use the variable instead of the method is with arrays. Everything else will be methods. That is, you'll use the brackets for everything except arrays.
The only true way to know when to use which one is experience. Though an IDE with autocompletion will usually help you out when you don't remember.
For the most part (not always) array.length, System.out, and System.err are the most common 3 you'll run into that are actually member access instead of method calls.
int[] myArray = new int[10];
String myString = "hello world!";
List<int> myList = new ArrayList<int>();
myArray.length //gives the length of the array
myString.length() //gives the length of the string
myList.size() //gives the length of the list
Its very likely that strings and arrays were designed at different times and hence ended up using different conventions. One justification is that since Strings use arrays internally a method length() was used to avoid duplication of the same information. Ultimately this is just an inconsistently that evolved that would definitely be fixed if the language were ever redesigned from the ground up. :D
The main difference is that in the A) first case its Array Type for example int[], Object[], double[], ect.. that has a public field called lenght and the B) second case is a Object String that has a function called length(), the function could of been called getLength() or something else. The array type public field length is probably a hangover from C++ way of doing things.
Array Types have the following:
The public final field length, which contains the number of
components of the array (length may be positive or zero)
The public method clone, which overrides the method of the same name
in class Object and throws no checked exceptions
All the members inherited from class Object; the only method of
Object that is not inherited is its clone method
Take a look at this, Array Types.
.length() is a method of a String class and which returns the number of characters in the string.
.length will give the number of elements stored in an array.
public class length
{
public static void main(String args[])
{
String x="test";
int a[]={1,2,3,4};
System.out.println(x.length());
System.out.println(a.length);
}
}
// output
4
4
length is a pseudo-data member reference, and only works for (small-a) arrays (ignoring classes that you may define that implement the member).
Everything else is an object of a class, and all JDK classes that have this concept define either length() or size() instance methods. (I do wish they'd been consistent and picked one or the other, but that's water over the bridge.)
Array.length is a property of that Array, similar to a variable reference.
ArrayList.size() is an actual method call to the array list object.
Are these two constructs equivalent?
char[] arr = new char[5];
for (char x : arr) {
// code goes here
}
Compared to:
char[] arr = new char[5];
for (int i = 0; i < arr.length; i++) {
char x = arr[i];
// code goes here
}
That is, if I put exactly the same code in the body of both loops (and they compile), will they behave exactly the same???
Full disclaimer: this was inspired by another question (Java: are these 2 codes the same). My answer there turned out not to be the answer, but I feel that the exact semantics of Java for-each has some nuances that needs pointing out.
While often the two constructs are interchangeable, THEY ARE NOT 100% EQUIVALENT!!!
A proof can be constructed by defining // code goes here that would cause the two constructs to behave differently. One such loop body is:
arr = null;
Therefore, we are now comparing:
char[] arr = new char[5];
for (char x : arr) {
arr = null;
}
with:
char[] arr = new char[5];
for (int i = 0; i < arr.length; i++) {
char x = arr[i];
arr = null;
}
Both code compiles, but if you run them, you will find that the first loop terminates normally, while the second loop will throw a NullPointerException.
This means that they are not 100% equivalent! There are scenarios where the two constructs will behave differently!
Such scenarios are likely to be rare, but this fact should not be forgotten when debugging, because otherwise you might miss some really subtle bugs.
As an addendum, note that sometimes the for-each construct is not even an option, e.g. if you need the index. The crucial lesson here is that even if it's an option, you need to make sure that it's actually an equivalent substitute, because it's not always guaranteed
Similarly, if you start with a for-each loop and later realized that you need to switch to the indexed for loop, make sure that you're preserving the semantics, because it's not guaranteed.
In particular, _be wary of any modification to the reference of the array/collection being iterated_ (modification to the content may/may not trigger ConcurrentModificationException, but that's a different issue).
Guaranteeing semantics preservation is also a lot more difficult when you use collections that use custom iterators, but as this example shows, the two constructs are different even when simple arrays are involved.
They are pretty much equivalent. But there can be few cases where they are not. It is best to make it final.
final char[] arr = new char[5]; // Now arr cannot be set null as shown
// in above answer.
Even then you can do i-- in the second loop. If you don't do some these unlikely things they are mostly equivalent.
The first one is more readable and so more preferable, if you're going to need the index anyway then plump for the second.
Please note that the most important difference is implied by the answer that "polygenelubricants" gave, but not explicitly stated: for-each iterates through the array but you can't modify any of the elements using the instance that the loop gives you (in this case, the variable "char x"). The classic loop allows you to use the index and alter an element of the array.
Edit: quick correction.
In Java, is there a way to truncate an array without having to make a copy of it? The common idiom is Arrays.copyOf(foo, n) (where the new array is n elements long). I don't think there is an alternative, but I'm curious as to whether there is a better approach.
An array's length in Java cannot be altered after initialization, so you're forced to make a copy with the new size. Actually, the length parameter of a Java array is declared as final, so it cannot be changed once it's set.
If you need to change an array's size, I'd use an ArrayList.
I was thinking about it some more... and just for kicks, how about something like the below.
Note: This is just a "can it be done?" intellectual exercise in Java hacking. Anybody who attempts to actually use this idea in production code will deserve all the pain that will undoubtedly follow.
public class Foo
{
private static byte[] array = new byte[10];
public static void main(String[] arg) throws Exception
{
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get(null);
Field arrayField = Foo.class.getDeclaredField("array");
long ptr = unsafe.staticFieldOffset(arrayField);
// doesn't work... there's gotta be a way though!
unsafe.reallocateMemory(ptr, 5);
System.out.println("New array size is: " + array.length);
}
}
I don't believe so. An array is allocated as a contiguous block of memory, and I can't imagine that there is any way of releasing a part of that block.
Succinctly: No, There isn't, as far as I know. A Java array is a fixed-size data-structure. The only way to "logically" resize it is create a new array and copy the wanted elements into the new array.
Instead: You could (possibly) implement a class which wraps an array into a collection and uses a "size" variable to logically reduce the length of the array without actually copying the values. This an approach has limited utility... The only case I can imagine where it's practical is when you're dealing with a huge array, which just can't be copied because of memory limitations.
Copying an array is relatively inexpensive time-wise... unless you're doing it millions of times, in which case you probably need to think up an algorithm to avoid this, and not waste your time mucking around with a "variable length array".
And of course... you could just use an ArrayList instead. Yes?