реализация стека для инструкций ijvm JAVA [дубликат]

Другое событие NullPointerException возникает, когда объявляется массив объектов, а затем сразу же пытается разыменовать его внутри.

String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

Этот конкретный NPE можно избежать, если порядок сравнения отменяется ; а именно, использовать .equals для гарантированного непустого объекта.

Все элементы внутри массива инициализируются их общим начальным значением ; для любого типа массива объектов, это означает, что все элементы null.

Вы должны инициализировать элементы в массиве перед доступом или разыменованием их.

String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

60
задан Duncan Jones 9 November 2013 в 09:34
поделиться

4 ответа

Эта проблема имеет две типичные причины:

  • Статические поля, используемые объектами, которые вы сохранили в списке
  • Случайно добавив тот же объект в список

Статические поля

Если объекты в вашем списке хранят данные в статических полях, каждый объект в вашем списке будет казаться одним и тем же, поскольку они удерживают одинаковые значения. Рассмотрим следующий класс:

public class Foo {
  private static int value; 
  //      ^^^^^^------------ - Here's the problem!

  public Foo(int value) {
    this.value = value;
  }

  public int getValue() {
    return value;
  }
}

В этом примере есть только один int value, который разделяется между всеми экземплярами Foo, поскольку он объявлен static. (См. учебник «Знакомство с членами класса» .)

Если вы добавите несколько объектов Foo в список, используя приведенный ниже код, каждый экземпляр вернет 3 из вызова to getValue():

for (int i = 0; i < 4; i++) {      
  list.add(new Foo(i));
}

Решение прост - не используйте ключевые слова static для полей вашего класса, если вы действительно не хотите, чтобы значения были разделены между каждым экземпляром этого класса.

Добавление одного и того же объекта

Если вы добавите временную переменную в список, вы должны создать новый экземпляр каждый раз, когда вы выполняете цикл. Рассмотрим следующий ошибочный фрагмент кода:

List<Foo> list = new ArrayList<Foo>();    
Foo tmp = new Foo();

for (int i = 0; i < 3; i++) {
  tmp.setValue(i);
  list.add(tmp);
}

Здесь объект tmp был создан вне цикла. В результате один экземпляр объекта добавляется в список три раза. Экземпляр будет содержать значение 2, потому что это значение было передано во время последнего вызова setValue().

Чтобы исправить это, просто переместите конструкцию объекта внутри цикла:

List<Foo> list = new ArrayList<Foo>();        

for (int i = 0; i < 3; i++) {
  Foo tmp = new Foo(); // <-- fresh instance!
  tmp.setValue(i);
  list.add(tmp);
}
108
ответ дан 6 revs, 5 users 93% 18 August 2018 в 23:20
поделиться
  • 1
    Привет @Duncan хорошее решение, я хочу спросить вас, что в "Добавление того же объекта" почему три разных экземпляра будут содержать значение 2, не все ли три экземпляра должны содержать 3 разных значения? надеюсь, что вы ответите в ближайшее время, спасибо – Dev 10 December 2014 в 10:20
  • 2
    @Dev Поскольку один и тот же объект (tmp) добавляется в список три раза. И этот объект имеет значение два, из-за вызова tmp.setValue(2) в последней итерации цикла. – Duncan Jones 10 December 2014 в 10:22
  • 3
    ОК, так что проблема возникает из-за того же объекта, не так ли, если я добавлю один и тот же объект три раза в список массивов, все три местоположения arraylist obj будут ссылаться на один и тот же объект? – Dev 10 December 2014 в 10:33
  • 4
    @Dev Yup, вот и все. – Duncan Jones 10 December 2014 в 10:34

Ваша проблема связана с типом static, который требует новой инициализации каждый раз, когда цикл повторяется. Если вы находитесь в цикле, лучше сохранить конкретную инициализацию внутри цикла.

List<Object> objects = new ArrayList<>(); 

for (int i = 0; i < length_you_want; i++) {
    SomeStaticClass myStaticObject = new SomeStaticClass();
    myStaticObject.tag = i;
    // Do stuff with myStaticObject
    objects.add(myStaticClass);
}

Вместо:

List<Object> objects = new ArrayList<>(); 

SomeStaticClass myStaticObject = new SomeStaticClass();
for (int i = 0; i < length; i++) {
    myStaticObject.tag = i;
    // Do stuff with myStaticObject
    objects.add(myStaticClass);
    // This will duplicate the last item "length" times
}

Здесь tag является переменной в SomeStaticClass проверить правильность приведенного выше фрагмента; у вас может быть другая реализация, основанная на вашем случае использования.

3
ответ дан 4castle 18 August 2018 в 23:20
поделиться
  • 1
    Что вы имеете в виду под «type static»? Что будет для вас нестационарным? – 4castle 3 February 2017 в 04:55
  • 2
    например нестатический: public class SomeClass{/*some code*/} & amp; static: public static class SomeStaticClass{/*some code*/}. Надеюсь, теперь это становится яснее. – Shashank 4 February 2017 в 12:37
  • 3
    Поскольку все объекты статического класса совместно используют один и тот же адрес, если они инициализируются в цикле и устанавливаются с разными значениями на каждой итерации. Все они будут иметь одинаковое значение, которое будет равно значению последней итерации или когда последний объект был изменен. Надеюсь, теперь это становится яснее. – Shashank 4 February 2017 в 12:46

Имела ту же самую проблему с экземпляром календаря.

Неверный код:

Calendar myCalendar = Calendar.getInstance();
for (int days = 0; days < daysPerWeek; days++){
            myCalendar.add(Calendar.DAY_OF_YEAR, 1);

            // In the next line lies the error
            Calendar newCal = myCalendar;
            calendarList.add(newCal); }

Вам нужно создать НОВЫЙ объект календаря, который можно выполнить с помощью календаря. clone ();

Calendar myCalendar = Calendar.getInstance();
for (int days = 0; days < daysPerWeek; days++){
                myCalendar.add(Calendar.DAY_OF_YEAR, 1);

                // RIGHT WAY
                Calendar newCal = (Calendar) myCalendar.clone();
                calendarList.add(newCal);

                }
2
ответ дан basti12354 18 August 2018 в 23:20
поделиться

Каждый раз, когда вы добавляете объект в ArrayList, убедитесь, что вы добавили новый объект, а не уже использованный объект. Случается, что при добавлении одной и той же копии объекта этот объект добавляется в разные позиции в ArrayList. И когда вы вносите изменения в один, поскольку одна и та же копия добавляется снова и снова, все копии становятся затронутыми. Например, предположим, что у вас есть ArrayList:

ArrayList<Card> list = new ArrayList<Card>();
Card c = new Card();

Теперь, если вы добавите эту карту c в список, она не будет добавлена ​​никаких проблем. Он будет сохранен в месте 0. Но когда вы сохраните ту же Карту c в списке, она будет сохранена в местоположении 1. Так что помните, что вы добавили один и тот же 1 объект в два разных местоположения в списке. Теперь, если вы внесете изменения в объект Card c, объекты в списке в местах 0 и 1 также отражают это изменение, потому что они являются одним и тем же объектом.

Одним из решений было бы сделать конструктор класса Card, который принимает другой объект карты. Затем в этом конструкторе вы можете установить такие свойства следующим образом:

public Card(Card c){
this.property1 = c.getProperty1();
this.property2 = c.getProperty2(); 
... //add all the properties that you have in this class Card this way
}

И скажем, что у вас есть одна и та же 1 копия Карты, поэтому во время добавления нового объекта вы можете сделать это:

list.add(new Card(nameOfTheCardObjectThatYouWantADifferentCopyOf));
2
ответ дан Faraz Durrani 18 August 2018 в 23:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: