1

I want derived classes to have their own loggers, but it looks like I cannot:

abstract class C {
  final protected static Logger l;
  C (...) {
    l.emit("C");
  }
}
class C1 extends C {
  final protected static Logger l = new Logger("C1");
  C1 (...) {
    super(...);
    l.emit("C1");
  }
}

I want a Logger in C1 but not in C, so that new C1() produces this output:

C1: C
C1: C1

(the first line comes from the C constructor and the second line from the C1 constructor). Instead I get a nullPointerException in C because l there is null.

I cannot make l into abstract in C, and I do not want to init it there either because then the output would be

C: C
C1: C1

What are my options?

Thanks!

4

2 回答 2

6

Solution 1 (the classic)

A possible approach would be to have an abstract getLogger() method in your abstract class, so that derived classes are forced to provide their own logger.

public class AbstractClass {
  abstract Logger getLogger();

  public void someMethodInAbstractClass() {
    getLogger().debug("something"); // will output using provided child logger
  }
}

public class ConcreteClass extends AbstractClass {
  private static final Logger LOGGER = Logger.getLogger(ConcreteClass.class);

  @Override
  Logger getLogger() {
    return (LOGGER);
  }

  public void someMethod() {
    getLogger().debug("something"); // will output using local logger
  }
}

You could also provide a default implementation in the abstract class to not force the child to implement an override. You make it easier on the consumers of your abstract class (developing concrete classes), but you won't enforce the fine graining of the method.

Solution 2 (long-winded...)

Another, more violent solution would be to have a getMagicLogger() method in the abstract class, that will determine at runtime the concrete type of the current instance to return a new logger instance, either every time or by lazy loading it and storing it in a field.

This way the abstract class handles it all and it's very easy for consumers, but it's kind of a crazy thing to do. AND, that means the Logger won't be a static field, obviously.

于 2012-06-07T18:33:57.130 回答
4

There's no attribute overriding for static members, the l logger in C is the one declared in C (which is null) and not the one from the C1 subclass.

于 2012-06-07T18:35:35.280 回答