Подтвердить что ты не робот

Передача "this" в java-конструкторе

Посмотрите на следующий код:

public class ClassA {
    private boolean ClassAattr = false;

    public ClassA() {    
        ClassAHandler handler = new ClassAHandler(this);
    }
}

public class ClassAHandler extends GeneralHandler {
    ClassA ca = null;

    public ClassAHandler(ClassA classa) {
        this.ca = classa;
    }
}

Мне нужно получить доступ к ClassAattr для некоторых методов ClassAHandler, среди других атрибутов. Есть ли способ сделать это без передачи класса origin в конструкторе обработчика. Мне не очень нравится, как это решение "выглядит".

4b9b3361

Ответ 1

Передача this другому методу/объекту изнутри конструктора может быть довольно опасной. Многие гарантии того, что объекты обычно выполняются, не обязательно верны, когда они просматриваются внутри конструктора.

Например, если ваш класс имеет поле final (не static), вы обычно можете зависеть от того, что оно установлено в значение и никогда не меняется.

Когда объект, на который вы смотрите, в настоящее время выполняет свой конструктор, эта гарантия больше не выполняется.

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

Ответ 2

На этой странице есть очень хорошее объяснение того, почему отказ справки "this" является плохой идеей:

http://www.ibm.com/developerworks/java/library/j-jtp0618.html#2

Проверьте флажок "Не публиковать ссылку "this" в процессе строительства"

Ответ 3

Создайте метод registerHandler (ClassA handler).

Невозможно создать обработчик для того, что обработчик не знает.

Ответ 4

Вы можете использовать внутренние классы, тогда есть неявные отношения между родителями и дочерними элементами между двумя экземплярами. (Но я не знаю, действительно ли это лучше).

public class ClassA {
    private boolean ClassAattr = false;

    public class ClassAHandler extends GeneralHandler {

       public ClassAHandler() {
           // can access ClassAattr
       }
    }

    public ClassA() {    
        ClassAHandler handler = new ClassAHandler();
    }
}

Если вы пройдете this, подкласс должен получить доступ к родительскому значению с помощью parent.classAattr. Мы можем задаться вопросом, будет ли он исправляться в соответствии с законом закона деметтера закона demeter.

public class ClassAHandler extends GeneralHandler {     
   boolean handlerAttr;

   public ClassAHandler() {       
   }
}

Ответ 5

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

public class ClassA {

    private boolean ClassAattr = false;

    public ClassA() {
    }

}


public class ClassAHandler {

    private ClassA ca = null;

    public ClassAHandler(ClassA classa) {
        this.ca = classa;
    }

}


public HandlerFactory {

    public ClassAHandler createClassAHandler(ClassA classa) {
        ClassAHandler handler = new ClassAHandler(classa);
        return handler;
    }

}

Ответ 6

public class ClassA {
    private boolean ClassAattr = false;
        public ClassA() {    
        ClassAHandler handler = new ClassAHandler(this);
        classAttr = true;
    }
}

public class ClassAHandler extends GeneralHandler {
    ClassA ca = null;

    public ClassAHandler(ClassA classa) {
        this.ca = classa;
        System.out.println(ca.classAttr);
    }
}

Итак, я добавил выражение classAttr = true;

Оператор System.out.println напечатает false. Это связано с тем, что построение ClassA не было полным в этой точке.

Итак, мое предложение состоит в том, чтобы добавить еще один метод в ClassA, который создаст ClassAHandler, а затем ClassAHandler получит полностью сконструированный объект ClassA

Итак, код будет выглядеть.

public class ClassA {
    private boolean ClassAattr = false;

    public ClassA() {    

        classAttr = true;
    }

    public init() {
        ClassAHandler handler = new ClassAHandler(this);
    }
}

Итак, последовательность кода будет new ClassA().init() и будет отлично работать

Ответ 7

Напишите метод getter для ClassAattr, как

            public boolean isClassAattr(){
                 return this.ClassAattr;
            }

Чтобы вы могли получить доступ к нему как ca.isClassAattr();

Ответ 8

Вы можете сделать ClassAHandler внутренним классом ClassA. Он будет иметь доступ к членам ClassA.

Ответ 9

нет ничего плохого в коде, который вы вставили, однако вы можете использовать нестатический внутренний класс, чтобы сделать вещи (возможно) более чистыми:

public class ClassA {
    private boolean ClassAattr = false;

    public ClassA() {    
        ClassAHandler handler = new ClassAHandler();
    }

    class ClassAHandler extends GeneralHandler {

        // magically sees the instantiating ClassA members and methods
    }
}

Ответ 10

prevNode.nex=this Что это значит?

public class DynamicList {
  private class Node { 
    Object element; 
    Node next; 

    Node(Object element, Node prevNode) { 
      this.element = element; 
      prevNode.next = this; 
    }
}