Использование «this» в качестве параметра для вызова метода в конструкторе

StackOverflow https://stackoverflow.com/questions/127205

Вопрос

У меня есть конструктор, подобный следующему:

public Agent(){

    this.name = "John";
    this.id = 9;
    this.setTopWorldAgent(this, "Top_World_Agent", true);

}

Здесь, при вызове метода, я получаю исключение нулевого указателя.Похоже, это потому, что я использую «это» в качестве аргумента в методе setTopWorldAgent.При удалении вызова этого метода все выглядит нормально.Почему это происходит?Кто-нибудь еще испытал это?

Это было полезно?

Решение

Вы можете передать это методам, но setTopWorldAgent() не может быть абстрактным.Вы не можете сделать виртуальный вызов в конструкторе.

В конструкторе объекта вы можете вызывать методы, определенные в этом объекте или базовых классах, но вы не можете рассчитывать на вызов чего-то, что будет предоставлено производным классом, поскольку части производного класса еще не созданы.Я бы ожидал какой-то ошибки компилятора, если бы setTopWorldAgent() был абстрактным.

В Java вы можете получить удивительное поведение с помощью конструктора и производных классов — вот пример

http://en.wikipedia.org/wiki/Virtual_functions#Java_3

Если вы привыкли к C# или C++, вы можете подумать, что безопасно вызывать виртуальные функции, а не вызывать переопределенные.В Java виртуальный вызов выполняется, даже если производный класс не полностью создан.

Если это не то, что происходит, то, по-видимому, все части этого, которые нужны setTopWorldAgent(), инициализированы - если нет, то, вероятно, необходимо инициализировать один из членов этого.

Редактировать:думал это C#

Другие советы

Из любопытства, почему вы передаете «это» функции-члену того же класса?setTopWorldAgent() может использовать this напрямую.Не похоже, что ваш конструктор или setTopWorldAgent() являются статическими, поэтому я не уверен, зачем вам передавать функции-члену то, к чему у нее уже есть доступ.

Если я чего-то не упускаю...

Почему бы setTopWorldAgent нуждаться this в качестве аргумента?Судя по вызову, это метод экземпляра, поэтому он может ссылаться на this без необходимости получать его в качестве параметра.

Я думаю, что более важно: с какой стати вы передаете «это» в качестве параметра методу в «этом»?

Следующее проверит то, что, по вашим словам, происходит с вами, и у меня нет с этим проблем.

public class Test {
  public Test() {
    this.hi(this);
  }
  public void hi(Test t) {
    System.out.println(t);
  }

  public static void main(String[] args) throws Exception {
    Test t = new Test();
  }
}

Учитывая, что setTopWorldAgent выглядит как метод экземпляра, почему вы все равно передаете ему это?

«это» никогда не должно быть нулевым.Вы уверены, что из-за этого выдается исключение?

Следует остерегаться того, что если метод является виртуальным или вызывает какие-либо виртуальные методы, то метод, принадлежащий подклассу, может быть запущен до инициализации переменных подкласса.

Ошибка должна быть где-то еще, поскольку приведенный выше код определенно работает, нулевая ссылка должна быть чем-то другим.

Если ваш агент реализует ITopWorldAgent, вам следует сделать следующее:


Agent agent = new Agent("John", 9);
agent.setTopWorldAgent(agent, "Top_World_Agent", true);

Если нет, то почему вы что-то настраиваете именно так?

Я предполагаю, что что-то в методе setTopWorldAgent использует значение, которое еще не было инициализировано в вашем конструкторе.

this не равно нулю, это точно.Оно выделено.

Тем не менее, нет необходимости проходить this в метод, он автоматически доступен во всех методах экземпляра.Если метод статический, вы можете реорганизовать его в метод экземпляра.

Правила Java гласят, что вы никогда не должны передавать «это» другому методу из его конструктора по той простой причине, что объект не был полностью создан.Объект, на который он ссылается, может находиться в несогласованном состоянии.Я удивлен, что фактическая ссылка «this» равна нулю, но совсем не удивлен, что какой-то член «this» имеет значение null, когда он передается в setTopWorldAgent, и что из-за этого метод выдает исключение.

Обычно вам может сойти с рук передача «this» из конструкторов, пока вы фактически не получаете доступ к каким-либо членам или методам вызова, например, если вы хотите установить ссылку на «this» в другом объекте.

В этом случае, конечно, аргумент не нужен, поскольку метод уже имеет ссылку на «это».

Рад, что вы получили ответ.Я хотел бы добавить, что передача this в качестве параметра может привести к неожиданным проблемам с параллелизмом.По сути, вы предоставляете возможность небезопасного манипулирования состоянием объекта с помощью потенциально непотокобезопасного кода.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top