Использование this в качестве параметра для вызова метода в конструкторе - PullRequest
6 голосов
/ 24 сентября 2008

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

public Agent(){

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

}

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

Ответы [ 11 ]

8 голосов
/ 24 сентября 2008

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

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

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

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

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

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

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

5 голосов
/ 24 сентября 2008

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

Если я что-то упустил ...

2 голосов
/ 24 сентября 2008

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

1 голос
/ 24 сентября 2008

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

1 голос
/ 24 сентября 2008

Я думаю, что более конкретно, с какой стати вы передаете '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();
  }
}
0 голосов
/ 25 сентября 2008

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

0 голосов
/ 24 сентября 2008

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

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

В этом случае, конечно, аргумент не нужен, так как метод уже имеет ссылку на 'this'.

0 голосов
/ 24 сентября 2008

Если ваш агент внедряет ITopWorldAgent, вы должны сделать это:


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

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

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

0 голосов
/ 24 сентября 2008

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

0 голосов
/ 24 сентября 2008

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

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

...