Java:子类中父类的变量未初始化并保留 null

发布于 10-12 22:17 字数 1466 浏览 7 评论 0原文

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 在这一行中作为 null 传递给 frm

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

How can i create frm instance,with not-null fileName,例如已经在父级中初始化了吗?

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;
            }
          }
    ...

Child class:

    ...
   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) {
    ...
      }
     }

The problem is that fileName is passed as null to frm in this line:

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

How can i create frm instance,with not-null fileName,e.g. already initialized in parent?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

恰似旧人归2024-10-19 22:17:19

如果我正确理解你的问题,你可以执行以下操作之一:

  • 在子类的构造函数中调用 setFile(file)
  • 实现放置在子类构造函数中的 setFile() 方法中的逻辑(顺便说一句,这将是代码重复)
  • 如果父类提供构造函数,接受文件参数,在子类的构造函数中使用 super(file) 调用父类的构造函数

UPDATE

AFAIU,问题出在字段初始化顺序上。将“frm”字段初始化移动到子类构造函数中应该可以解决问题:

public FileAppender(String fileName) {
    setFile(fileName);
    frm  = new FileResourceManager(fileName, tempDir, false, loggerFacade);
    ...
}

If I understand your question correctly, you can do one of the following:

  • call setFile(file) in constructor of child class
  • implement logics placed in setFile() method in child's constructor (BTW, that'll be code duplication)
  • if parent class provides constructor, which accepts file parameter, call parent's constructor with super(file) in constructor of child class

UPDATE

AFAIU, the problem is in fields initialization order. The moving "frm" field initialization into child class constructor should solve the problem:

public FileAppender(String fileName) {
    setFile(fileName);
    frm  = new FileResourceManager(fileName, tempDir, false, loggerFacade);
    ...
}
浅笑轻吟梦一曲2024-10-19 22:17:19

setFile 是您从父类构造函数调用的重写吗?在这种情况下:父类构造函数在子构造函数的有用部分之前运行。因此,从父类构造函数中调用 setFile ,然后将控制权返回到已将该变量清空的子类构造函数。

实例字段初始化程序和实例初始化程序实际上是构造函数的一部分,在可能隐式调用 super 之后(但如果它们调用 this() 则不是)。我相信 C Sharp 在调用 super 之前插入实例初始化程序(但它们不能引用 this)。

该怎么做:避免继承总是好的。特别是避免受保护的变量和从构造函数调用可重写的方法。保持构造函数简单。并且不要将 = null 添加到实例字段。

Is setFile an override that you are calling from the parent class constructor? In that case: The parent class constructor runs before the useful part fo the child constructor. So setFile is called from the parent class constructor, and then control is returned to the child class constructor which you have nulling out that variable.

The instance field initialisers and instance initialisers are actually part of constructors, after the possibly implicit call to super (but not if they call this()). I believe C sharp inserts instance initialisers before the call to super (but they can't reference this).

What to do: Avoiding inheritance is always good. In particular avoid protected variables and calling overridable methods from constructors. Keep constructors simple. And don't add = null to instance fields.

花开浅夏2024-10-19 22:17:19

使用以下代码解决:

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() 方法中初始化(不为空)。
不是很优雅,但在我的情况下看起来是最简单的解决方案。

Resolved with following code:

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 is initialized(not null) within writeOut() method.
Not very gracefully,but looks like simplest solution in my case.

没有伤那来痛2024-10-19 22:17:19

您必须调用父类中的 setFile() 方法。

You have to call the setFile() method in the parent class.

梦回梦里2024-10-19 22:17:19

假设您的“父类”是 SomeClass 类,请覆盖那里的默认构造函数:

public Someclass(String fileName) {
   this.fileName = fileName;
}

Assuming that your "parent class" is the SomeClass class, overwrite the default constructor there:

public Someclass(String fileName) {
   this.fileName = fileName;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文