Указатель NULL
- это тот, который указывает на никуда. Когда вы разыскиваете указатель p
, вы говорите «дайте мне данные в месте, хранящемся в« p ». Когда p
является нулевым указателем, местоположение, хранящееся в p
, является nowhere
, вы говорите «Дайте мне данные в месте« нигде ». Очевидно, он не может этого сделать, поэтому он выбрасывает NULL pointer exception
.
В общем, это потому, что что-то не было правильно инициализировано.
Эта проблема имеет две типичные причины:
Если объекты в вашем списке хранят данные в статических полях, каждый объект в вашем списке будет казаться одним и тем же, поскольку они удерживают одинаковые значения. Рассмотрим следующий класс:
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);
}
Ваша проблема связана с типом 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
проверить правильность приведенного выше фрагмента; у вас может быть другая реализация, основанная на вашем случае использования.
static
»? Что будет для вас нестационарным?
– 4castle
3 February 2017 в 04:55
public class SomeClass{/*some code*/}
& amp; static: public static class SomeStaticClass{/*some code*/}
. Надеюсь, теперь это становится яснее.
– Shashank
4 February 2017 в 12:37
Имела ту же самую проблему с экземпляром календаря.
Неверный код:
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);
}
Каждый раз, когда вы добавляете объект в 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));
tmp
) добавляется в список три раза. И этот объект имеет значение два, из-за вызоваtmp.setValue(2)
в последней итерации цикла. – Duncan Jones 10 December 2014 в 10:22