Java: переменная из родительского класса в дочернем классе не инициализирована и содержит ноль - PullRequest
1 голос
/ 19 января 2011
Parent class(*ch.qos.logback.core.FileAppender*):

     ...

   protected String fileName = null;

   public FileAppender() {
      }

          public void setFile(String file) {
            if (file == null) {
              fileName = file;
            } else {
              // Trim spaces from both ends. The users probably does not want
              // trailing spaces in file names.
              String val = file.trim();
              fileName = val;
            }
          }
    ...

Дочерний класс:

    ...
   public class FileAppender<E> extends ch.qos.logback.core.FileAppender<E> {

     private FileResourceManager frm  = new FileResourceManager(fileName, tempDir, false, loggerFacade);


     public void writeOut(E event) throws IOException {
      Object txId = null;
      try {
       frm.start();
       txId = frm.generatedUniqueTxId();
       frm.startTransaction(txId);
       outputStream = frm.writeResource(txId, fileName, true);
       outputStream.write(event.toString().getBytes());
       frm.commitTransaction(txId);

      }

      catch (Exception e) {
    ...
      }
     }

Проблема в том, что fileName передается как ноль в frm в этой строке:

private FileResourceManager frm  = new FileResourceManager(fileName, tempDir, false, loggerFacade);

Как я могу создатьfrm экземпляр, с ненулевым fileName, например, уже инициализированный в parent?

Ответы [ 5 ]

2 голосов
/ 19 января 2011

Является ли setFile переопределением, которое вы вызываете из конструктора родительского класса?В этом случае: конструктор родительского класса запускается перед полезной частью дочернего конструктора.Таким образом, setFile вызывается из конструктора родительского класса, а затем управление возвращается в конструктор дочернего класса, который обнуляет эту переменную.

Инициализаторы полей экземпляров и инициализаторы экземпляров фактически являются частью конструктороввозможно неявный вызов super (но не если они вызывают this()).Я считаю, что C sharp вставляет инициализаторы экземпляра перед вызовом super (но они не могут ссылаться на this).

Что делать: избегать наследования всегда хорошо.В частности, избегайте защищенных переменных и вызова переопределенных методов из конструкторов.Сохраняйте конструкторы простыми.И не добавляйте = null к полям экземпляра.

2 голосов
/ 19 января 2011

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

  • вызовите setFile (файл) в конструкторе дочернего класса
  • реализовать логику, размещенную в методе setFile () в дочернем конструкторе (кстати, это будет дублирование кода)
  • если родительский класс предоставляет конструктор, который принимает параметр файла, вызвать конструктор родительского класса с super (file) в конструкторе дочернего класса

UPDATE

AFAIU, проблема в порядке инициализации полей. Перемещение инициализации поля "frm" в конструктор дочернего класса должно решить проблему:

public FileAppender(String fileName) {
    setFile(fileName);
    frm  = new FileResourceManager(fileName, tempDir, false, loggerFacade);
    ...
}
1 голос
/ 19 января 2011

Разрешается с помощью следующего кода:

private static FileResourceManager frm;
    public void writeOut(E event) throws IOException {
        ...

        if (frm == null) {
            frm = new FileResourceManager(fileName, tempDir, false, loggerFacade);
        }

        Object txId = null;
        try {
...
        }

        catch (Exception e) {
...
}
    }

fileName инициализируется (не ноль) в методе writeOut ().Не очень изящно, но выглядит как самое простое решение в моем случае.

0 голосов
/ 19 января 2011

Предполагая, что ваш "родительский класс" является классом SomeClass, перезапишите там конструктор по умолчанию:

public Someclass(String fileName) {
   this.fileName = fileName;
}
0 голосов
/ 19 января 2011

Вы должны вызвать метод setFile () в родительском классе.

...