简体   繁体   中英

Why am I getting NullPointerExceptions after assigning references in arrays in a loop?

Why this is not working:

//...
Integer[] array=new Integer[5];
for(Integer x: array){x=-1;}
printArray(array);
//...

// the print function is the following
public static String printArray(Object[] array){
    String str="";
    for(Object obj : array){
         str+=obj.toString()+" ,";
    }
    System.out.println(str);
}

I got NullPointerException at the for-each statement from the printArray function, why?

Because you never initialized the array with any values, so it just contains a bunch of null s. You need to give it values before you can call .toString() on them.

For example:

Integer[] array = new Integer[5] { 1, 2, 3, 4, 5 };

Your initial loop ( x = -1 } is not changing the array, but rather the transient object x in your loop. It would be like doing this:

for (int i = 0; i < array.length; i++) {
    Integer j = array[i];
    j = -1;
}

Instead, do this if you want to use a loop to initialize:

for (int i = 0; i < array.length; i++) {
    array[i] = -1;
}
Integer[] array=new Integer[5];
for(Integer x: array){x=-1;} 

The code above doesn't update the array. If you want to update it, you'll need to assign values to the array elements, like this.

for( int i = 0; i < array.length; i++ )
  array[ i ] =-1;

The reason the first snippet doesn't do anything useful is that Java is pass by value only. When you create a local variable x and assign an array element to it as its value (as you do in your code), it will contain a reference to the value (the Integer object), but not to the location it's in the array. When you change the value of x , you simply make x point to a different object.

The assignment is done to the local variable x, it is not automatically propagated to the array variable. Try this:

for(int i = 0; i < array.length; i++) {
     array[i] = -1;
}

When you do x=-1, you are assigning a new instance to the variable x and not altering the value of the object in the array. So, your array is effectively uninitialized.

for(Integer x: array){x=-1;}不会初始化数组,它只是将临时变量x设置为-1的五倍。

what is going wrong with this java code

Since you asked.... I would

 int[] array=new int[5];
 Arrays.fill(array);
 System.out.println(Arrays.toString(array));
  • Use int for integer types.
  • Use the build-in Arrays methods to fill and toString the array.
  • Use StringBuilder rather than += on a String
  • Have the printString print a String or printArray print the array OR return a String as you might ignore the result, as you did in your example. Call it toString() or asString() if it returns a String.
  • Use a varargs on the parameters.
  • Don't call object.toString() as toString() is called for you. Apart from being shorter, null doesn't thrown an exception!!
  • Use ", " instead of " ,"
  • Remove the last " ,".

however say you wanted to write your own printArray ...

// the print function is the following
public static void printArray(Object... objects) {
    StringBuilder str = new StringBuilder();
    for (Object obj : objects)
        str.append(obj).append(", ");
    if (str.length() > 1) str.delete(str.length() - 2, str.length());
    System.out.println(str);
}

public static void printArray(int... ints) {
    StringBuilder str = new StringBuilder();
    for (int i : array)
        str.append(i).append(", ");
    if (str.length() > 1) str.delete(str.length() - 2, str.length());
    System.out.println(str);
}

Assigning to x doesn't write through to the array. You'll have to do something like this

for(int i = 0; i < array.length; i++) {
    array[i] = -1;
}

You never initialized the vales form array.

1.

Integer[] array = new Integer[5];

Here you have reserved space in memory for five Integer objects let say five boxes with an unique addresses;

  1. for(Integer x :array) { x = -1; }

Here the things are quite more complicated, what you are actually doing is this

2.1 You allocate memory (another box) for Integer object called x 2.2 You assign (put) value* from table (which is null) to it; 2.3 You assign value -1** to it; 2.4 You repeat from step 2.2 till reserved memory is not finished ( five times).

So the main problem is that you never assign the values into array in other word you are not inserting anything into boxes.

To solve this situation you should allocate to each box a value and then you can use them as you wish.

for(int i=0; i< array.length; i++) {
  array[i] = new Integer("-1");
}

Now in each loop we are referring to boxes and there we store the value;

*By value I mean the addresses of those boxes because you are using reference type .

**You also are creating and box in memory and allocate an address for this -1 (that is retrieve from the cache). And in advance the compiler change that x=-1; into x = Integer.valueOf(-1);

Next thing is the method printArray(Object[] array):

You should remember that operations on are very let say expensive because the use a lot of memory. What you are doing there is called concatenation and usually the are not welcome.

The next thing what is wrong is the division of labor You have called the method print array but you are also creating there the string that in fact will be printed. Good approach would be to separate this operations.

public static String arrayToString (Object... array) { //... varags  

  if(array == null) {
    return "null"; //If is null we just return String null.
  }

  int max = array.length - 1;

  if(max == -1) { //We check that array is empty length
   return "[]";
  }

  StringBuilder sb = new StringBuilder("[");

  int i = 0;

  while(i <= max) {

    sb.append(String.valueOf(array[i])); //String.valueOf method is a helper, in situation when in array are null we will get from that method "null" if we wrote array[i].toString; in case when in box i there was no element set we would get null pointer exception. That was your real last problem. But when you are using string builder this is not necessary.

    if(i < max) {
      sb.append(", ");
    }

    i++;
  }

  return sb.append(']').toString();

}

  public static String print(String str) {
     System.out.println(str);
  }

Ps.

For simpler way you could use:

Arrays.fill(array,new Integer(-1));
Arrays.toString(arrays);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM