views:

180

answers:

9

I was looking at someone's code and saw that he repeatedly declared

PrintStream out = System.out;

and later called

out.println("blah");

I actually thought this was kind of neat. Is this a common practice? Was he just being fancy?

A: 

It's a shortcut if you're doing a lot of println. I've seen it done in places before, though I tend not to do it because I think System.out.println is clearer since you don't need to figure out where out was assigned. I setup an eclipse template so I can autocomplete println to System.out.println and it's pretty quick.

Jeff Storey
Eclipse has a built-in template "sysout", so you didn't even need to create your own :)
benjismith
True, but I write a lot of groovy code and this way I can use println in either language.
Jeff Storey
A: 

Nope. Never seen that before.

I agree. It's not too shabby...

benjismith
+6  A: 

This is a reasonable approach. He is basically creating an alias for System.out. There are a number of advantages:

  • Less typing.
  • Easier to later change the code to output to a different PrintStream.
  • Possibly a performance improvement, although it will be negligible.
Mark Byers
point 1, not less than sysout<ctrl-space> which will insert "System.out.println()". Point 2, yes but that also means you may make the mistake of assuming that "out" means System.out.println because that is how it was done everywhere else in the code. It's also more explicit, like not using short variable names. Point 3--no. The compile is smarter than you. NEVER make a decision based on what you think the compiler is going to do without basing it on testing--your guess is almost always wrong, the compiler optimizes based on you not being tricky--on writing the clearest code possible.
Bill K
@Bill K: The compiler is smart, but the semantics of field access vs. local variable access are different, so it can't optimize this out in general. Who's to say println() didn't change the value of System.out? (Final fields aren't as final as you'd think -- look at System.setout().)
Adam Crume
@Adam Crume I suppose I should have said that the compiler+runtime is smarter than you think. It can look at the fact that System.out is not changing and in-line the code to write to it. In fact, it can inline the entire block of code to do the actual output if it wants to--it probably doesn't but I wouldn't be too surprised if it did. If you were to alias "out", it might prevent such a runtime optimization. Basically, all I was saying is that if you EVER make a programming decision based on theoretical performance advantages instead of tested advantages you really need to rethink that.
Bill K
+2  A: 

To avoid typing System.out.println specially when performing small test ( without an IDE ) I use import static java.lang.System.out instead

But that may make sense if you want to substitute the value of System.out later, perhaps to a wrapper to redirect to a file

 PrintStream out = new FilePrintStream("MyLogs.log"); // // System.out

And silence the standard output at once. I repeat it may make sense on some scenarios, because for this I would use a Logging framework.

BTW, it would be better to declare it as final and static also:

class YourClass  {
    private final static PrintStream out = System.out;
}
OscarRyz
A: 

If you look at Throwable.printStackTrace in the documentation you can call it without arguments, and it just passes System.out to the version which takes a PrintStream.

It's quite common to find situations where a number of different PrintStream objects could be passed around and it makes printing code much simpler.

Geoff
A: 

It's a cute trick, but like most cute tricks it might be better just to do it right.

Once you get to the point where you are sure you want logging (sure enough to add something like that), why not just get Log4J or some other logging system that has even more flexibility and power?

Aliasing stuff is kind of cute and fun if you are alone, but even if you are a really slow typist and it saves you a whole 5 seconds every time you type it (over System.out or "sysout +<ctrl-space>" in eclipse/netbeans), you will lose that time ten-fold the first time someone--possibly you--sees "out." and doesn't know immediately what it means.

I mean, in one program let's say that you did what some other poster suggested and redirected "out" to go to a file instead of STDOUT but In some classes, maybe "out" still goes to System.out. or maybe you just forget that you redirected it to a file. Later you come in and say "well, it says:

out.println("WE MADE IT");

but I don't see that line in STDOUT, what the hell?"

Then you spend 4 hours tracking a bad indication instead of fixing the bug.

Bill K
If you were using Eclipse and saw 'out' wouldn't you just press F3 on it and see exactly where it was going with no time wasted? I'm all for removing duplication and removing the System.out call every where it is used is removing duplication. The reasons are well outlined by the answer http://stackoverflow.com/questions/3041482/plain-old-system-out-question/3041495#3041495
Alb
Not if you didn't think to, which is the whole point. Explicit beats brief when you are working with others. When you are alone, your code can be as fun as you like, but I get really tired of working on other peoples cute tricks. This attitude is getting some love/hate with Java variable naming conventions. I mean, you'd save as much space using yalvn instead of typing yetAnotherLongVariableName, but some people are starting to get the importance of explicit over brief (at least in the Java world--I still see a lot of "yalvn" c variable names, as though they took up memory or something)
Bill K
Sure I appreciate a decent method name, but in this case the original method name is just 'out'. Firstly I don't think anyone should assume this would be System.out without checking it, secondly I don't think adding the package to it at every invocation is the best way to deal with it though. Extracting all System.out calls to a, for example, 'printToConsole' or 'printToLogStream' method is better than leaving them inline in my opinion as it removes the duplication but retains clarity of intention.
Alb
@Alb--It doesn't really remove duplication--It bugs me when people don't get that. In programming, the important duplication to watch is not duplicate typing or explicit code, it's duplicate logic (which forces you to make changes in multiple locations to fix one problem). Although in a way this allows that changing your logging destination in one place--I still think that if you are going to go so far as to alias out why wouldn't you use a real logger package?
Bill K
A: 

Whether this is a good idea is debatable, and probably depends on the circumstances.

On the plus side:

  • It makes the application code look neater.
  • It may simplify changing the destination for output.

On the minus side:

  • It potentially increases cross-coupling; e.g. if the out variable is an instance variable or has to be passed as a parameter.
  • It potentially causes trouble if your application needs to call System.setOut().
  • If the System.out code is just debugging, this makes it harder to notice and remove. Indeed, it probably nullifies PMD (etc) code quality checks that report this kind of thing.

It should be noted that there are potentially other ways to do this; e.g. replacing System.out.println(String) with a utility method printLine(String) achieves a similar effect without the cross coupling.

Stephen C
A: 

since System.out is a final variable, what he did would be identitcal to referencing System.out directly.

unless somebody called System.setOut() which reassigned System.out.

wait, what?

irreputable
+1  A: 

It might be because in general it is not recommended to delve in and use objects which are members of other objects. It is seen like someone reaching for your pocket to get your money out of your wallet instead of asking you to lend him some money.

There might be a slight advantage to this which would be to be able to change the Output stream if needed to a file, socket or whatever. So he would be able to replace:

PrintStream out = System.out;

with

PrintStream out = new PrintStream(new FileOutputStream(filename));

However if he is repeatedly declaring it over and over again he is really losing the above advantage, because the whole point would be to have it somewhere centralised and decide where to output the logs in one place.

Note that this is a very crude way and the real standard practice is to use logging. Java has its own package java.util.logging out of the box, log4j is another very powerful alternative (and very popular) and there are others.

jbx