Ошибка нулевого указателя в Java?

#java #nullpointerexception #pass-by-reference

#java #исключение nullpointerexception #передача по ссылке

Вопрос:

Я довольно новичок в этом форуме. Я всегда с опаской относился к публикациям на форумах, но после двух недель битья головой о свой код, пытаясь заставить его работать, я, наконец, сдался. Приведенный ниже код является важной частью некоторого большего кода, но я думаю, что я вроде как точно определил проблемный раздел. У меня есть 2D массив объектов, которые должны быть инициализированы по умолчанию, как только он будет создан. Однако, похоже, этого не происходит, и значение остается нулевым. Может ли это быть результатом того, что Java не может передавать по ссылке? Если это так, то почему примитивные 2D-массивы создаются отлично? Заранее благодарю тебя, Ласц.

     class ObjectThing
    {
        int someInt;
        double someDouble;

        public ObjectThing()
        {
            someInt = 0;
            someDouble = 0;
        }

        synchronized private void someIntIncrement ()
        {
           someInt  ;
        }

        synchronized public void addSomeDouble (double sd)
        {
            someDouble  = sd;
            someIntIncrement ();
        }

        synchronized public String toString ()
        {
            return someInt   ","   someDouble;
        }
  }


  class AnotherObject
  {
          String name;
          ObjectThing [][] someObjectMAtrix;
          double [][] someDoubleMAtrix01;
          double [][] someDoubleMAtrix02;   

          public AnotherObject()
          {
          }

          private void initDouble (double [][] mat)
          {
             for (double [] i: mat)
                for (double j: i)
                   j = 0;
          }

          private void initObject (ObjectThing [][] so)
          {
              for (ObjectThing [] i: so)
                 for (ObjectThing j: i)
                    j = new ObjectThing ();
          }         

          public void init (int r, int c)
          {
              someObjectMAtrix =  new ObjectThing [r][c];
              someDoubleMAtrix01 = new double [r][c];
              someDoubleMAtrix01 = new double [r][c];         
          initObject (someObjectMAtrix);
              initDouble (someDoubleMAtrix01);
              initDouble (someDoubleMAtrix02);
          }
   }

   class Driver
   {
       public static void main (String [] args)
       {
            initializeMethod();
       }

       public void initializeMethod ()
       {
            AnotherObject [] anotherObjectArray = new AnotherObject [1];
            for (AnotherObject i: anotherObjectArray)
            {
                i.init(72,72);
            }
       }
   } 
  

Комментарии:

1. Если вы получили исключение NullPointerException, как следует из названия, полезно, если вы также включите его в свой вопрос.

2. » Может ли это быть результатом того, что Java не может передавать по ссылке?» Нет. Вы делаете это неправильно. Также может предоставить меньшую выборку с воспроизводимой ошибкой?

3. Не могли бы вы также предоставить трассировку стека, пожалуйста?

4. Пожалуйста, пожалуйста, пожалуйста, хотя бы НАМЕКНИТЕ, где в вашем коде возникает исключение нулевого указателя. Java создает очень хорошую трассировку стека исключений, и было бы очень полезно просмотреть несколько верхних строк этого с некоторыми подсказками относительно того, какие строки соответствуют строкам # s в трассировке.

Ответ №1:

Проблема в вашем initializeMethod:

         AnotherObject [] anotherObjectArray = new AnotherObject [1];
        for (AnotherObject i: anotherObjectArray)
        {
            i.init(72,72);
        }
  

Переход Object[] myArray = new Object[1] только выделяет пространство для массива. На самом деле это не создает эти объекты. Ваш блок кода должен быть

         AnotherObject [] anotherObjectArray = new AnotherObject [1];
        anotherObjectArray[0] = new AnotherObject();
        for (AnotherObject i: anotherObjectArray)
        {
            i.init(72,72);
        }
  

Это немного неуклюже. Я предполагаю, что у вас есть какая-то потребность поместить AnotherObject в массивы, и вы просто не показываете это. Если вам нужен только один из этих объектов, просто создайте его напрямую. Вероятно, вам следует взглянуть на Списки

Ответ №2:

Я считаю, что это сделано специально. Примитив будет выделен в стеке и всегда будет иметь какое-то значение по умолчанию. Объект выделяется в куче и будет передаваться по ссылке. Эти ссылки по умолчанию ни на что не будут указывать, пока вы не инициализируете их.

Ответ №3:

Вы только что инициализировали массив объектов AnotherObject…но в первом поле массива нет AnotherObject… Это значение равно нулю, поскольку вы его не инициализировали. В initializeMethod вы должны выполнить следующее:

 AnotherObject [] anotherObjectArray = new AnotherObject [1];
 for (AnotherObject i: anotherObjectArray)
    {
        i = new AnotherObject();
        i.init(72,72);
    }
  

приветствия!

Ответ №4:

Компилятор Java заставит вас инициализировать переменные, примитивы или ссылочные типы (например, объекты), или он сгенерирует ошибку компилятора и завершится сбоем.

Однако при инициализации массива будет создан массив желаемого размера, для каждого элемента которого установлено значение по умолчанию. Для примитивов это что-то вроде 0 для числовых типов, false для логических значений. Для ссылочных типов значение по умолчанию равно null . Это источник вашей проблемы.

Вы правильно инициализируете массив, но не заполняете его допустимыми значениями. Итак, это связано не с передачей по ссылке, а с правильной инициализацией массива и знанием значений по умолчанию для вновь инициализированного массива.

В частности, вы используете конструкцию for-each для перебора массива. Эта конструкция выполняет операцию над каждым объектом в коллекции / массиве.

Следовательно, этот код:

 AnotherObject [] anotherObjectArray = new AnotherObject [1];
for (AnotherObject i: anotherObjectArray){
    i.init(72,72);
}
  

эквивалентно этому коду:

 AnotherObject [] anotherObjectArray = new AnotherObject [1];
for(int count=0; count <  anotherObjectArray ; count  ){
    AnotherObject tempObj = anotherObjectArray[i]; // This is null, because anotherObjectArray[i] hasn't been initialised yet
    tempObj.init(72,72); // This is where we get the NullPointerException :(
}
  

Вы видите проблему? Вы пытаетесь выполнить операцию над null, следовательно NullPointerException

Я полагаю, что вы на самом деле намеревались сделать это:

 AnotherObject [] anotherObjectArray = new AnotherObject [1];
for(int count=0; count <  anotherObjectArray ; count  ){
    AnotherObject tempObj = new AnotherObject(); // Here we create the new object
    tempObj.init(72,72); // Initialise the newly created object
    anotherObjectArray[i] = tempObj; // Now we store in the array :)
}
  

Надеюсь, я объяснил это достаточно ясно, но, пожалуйста, попросите разъяснений, если я этого не сделал 🙂

Комментарии:

1. Если мой ответ помог, принятие / голосование за него — хороший способ выразить свою признательность 🙂