views:

584

answers:

3

Here's what I am trying to determine...

I have a utility class to append lines to a textfile. This must be used by a number of other classes, like a common logging file.

In my first implementation, I had all the classes that wanted to use it make a referenceless instance, e.g.

new Logger(logline,logname);

The constructor creates a PrintWriter, appends the line and closes the file.

This seemed wasteful, since a new instance gets made for every line appended.

The alternative was to use a static method, called "writeln" in this common class, since I had understood that static methods and data re-use the same memory over & over...but

this static method creates an instance of PrintWriter to do its job, so doesn't that mean that a new instance of PrintWriter is created for every line, like #1?

Anyway, (I am relatively new to Java ) is there a well-known, approved way of doing this, or do we just create away, and let the garbage-collector clean up after us?

Thanks,

+2  A: 

You shouldn't be doing any work in your contructor.

Constructors are for object setup.

You should create a Log() method to do the actual logging.

Logger l = new Logger();
l.Log(logline,logname);
l.Log(logline,logname);

or you can setup the logger as a Singleton.

Logger.getInstance().Log(logline, logname);

Singleton Pattern in Java: http://www.javaworld.com/javaworld/jw-04-2003/jw-0425-designpatterns.html

Chad Grant
+1  A: 

There are several kinds of state that this object might want to hold onto, particularly the PrintWriter. If your Logger class were to store these as instance data, then the method for doing the logging needs to be an instance method, not a static method. Hence you need to separate out the logging from the construction:

// Pass only the PrintWriter into the constructor, not the line to be logged.
Logger myLogger = new Logger(filename);

...

// Log a message
myLogger.log("This is a message to be logged.");

// Log another message, just for kicks.
myLogger.log("this shows that myLogger can be used repeatedly.");

I haven't shown any of the implementation details, but I hope this is enough to get you going.

Dan Breslau
+4  A: 

The sensible answer is that you should use a "serious" logging package, such as Commons Logging.

However, to answer your question, in this case you should use a static method (unless you're wanting to maintain logging class instances in your code, in which case you should follow the other answers in this thread). Additionally, you should have a static field that's initialised to, say, a Map<String, PrintWriter>. (You don't have to use String as the key: if you want a finite number of logging target types, use an enum.)

Then, when your method sees a key that's not existent in the map yet, it'd create the PrintWriter on the spot, and sticks it in the map. You probably want to use a ConcurrentHashMap as the backing map type, so it's thread-safe.

You also need to provide a way to close a logging target (which will also clear the associated entry from the map).

Good luck!

Chris Jester-Young
Thank you, Chris! This was the suggestion that resonatedmost with me. There are 2 "log" files - one for regularlogging and one for errors - so keeping the references in aHashMap ( a dispatch table ) is great. The key could be the filename. One thing I did not catch..About closing a logging target...the file is closed after each line.Do I also have to release memory? Thought this happsn when JVMexits ( at program termination).
javaphild
Closing the logging file for each log line means that you have to reopen for each log line. This is going to be a serious performance hit. You should consider using flush(), if the aim is to make sure the logging data hits the disk; that still carries some performance penalty, but not as much.However, if you still insist on closing the file after every line, then you don't have to worry about closing it elsewhere. The map can be left to release automatically, yes.
Chris Jester-Young
Using the filename as key could be fine, as long as clients refer to the file names via string constant fields only, rather than as direct string literals. This reduces the effect that typos might have, and means that your file names are kept in one place only, making them easy to change should that be required.
Chris Jester-Young