Differences Between System.Out.Println() and Return in Java

Differences between System.out.println() and return in Java

Your last sentence is effectively correct, but the distinction between these two operations is HUGE, so I'd like to provide a more in depth explanation of their differences.

The Difference:

return is an instruction that controls the flow of your program's execution. It is a fundamental part of the Java syntax. It tells the computer what part of your code to execute, and what values to use during that execution. When you return a value, you are saying "The result of calling this method is XXXX" (with 'XXXX' being the value you returned).

System.out.println is not used to control how your program executes. It is a merely way to inform the user of what is going on inside your program. System.out.println (syso for short) can print any information to the console; it doesn't matter if it's a variable, an expression, or the result of a method call. There is no limitation to "static" data.

Let's look at both of them in action:

int addInts(int arg0, int arg1)
{
return arg0 + arg1;
}

This means that wen we call addInts in our program, it will evaluate to the sum of its arguments. So when we write addInts(3, 7), it's the same as if had simply written 3 + 7 or 10 in our source code. Nothing is printed to the console; all we've done is give our program a way of calculating something.

However, any calculations we might make are ultimately useless if all they do is sit inside the computer, so we need a way to display this information to the user. Enter syso:

System.out.println(addInts(22, 16));

The addInts method is called and returns 38. This value is placed somewhere in the computer's memory such that our program can find it.

Next, syso takes that value (38) and prints it to the console, letting the user know what value was calculated. Nothing new is calculated from this procedure, and our program continues to the next statement.

So which do I use?

In simple programs, you have so few values to keep track of that it can be tempting to just print everything that you want to know where you calculate it. For instance, if you were writing a program to do your algebra homework (I've been there) and you wrote a method to solve the quadratic equation, it might be tempting to structure it like this:

class Algebra
{
static void quadSolve(double a, double b, double c)
{
double result = /* do math... we're ignoring the negative result here*/;

System.out.println("The solution to the quadratic equation is: " + result);
}

public static void main(String[] args)
{
quadSolve(1.0, -6.0, 9.0);
}
}

However, this approach quickly becomes a very bad idea if you want to make your program a little more complex. Let's say one problem requires you to solve the quadratic equation and then use the result of that calculation to calculate the volume of a cylinder. In the above example, we can't do that: after we dump the value of result to the console via syso, it disappears when the quadSolve method ends. It would make much more sense if we have quadSolve return result and let the "caller" (the place quadSolve was called from) deal with handling that value. This is a much more flexible design that allows us to make our programs much more complicated with relative ease. This increased flexibility and modularity is really what makes methods useful. Here is the implementation:

class Algebra
{
static double quadSolve(double a, double b, double c)
{
double result = /* do math... we're ignoring the negative result here*/;

return result;
}

public static void main(String[] args)
{
double x = quadSolve(1.0, -6.0, 9.0);
//now we can do whatever we want with result:
//print it, negate it, pass it to another method-- whatever.
System.out.println("The solution to the quadratic equation is: " + x);
System.out.println("And it's square is: " + (x * x));
}
}

I hope this clears things up. Feel free to ask if you need additional clarification.

a return vs System.out.println ?

In fact, the second piece of code won't run at all. This is because the function isn't returning anything despite the fact that in the function header it says it will return a double. It should actually be this (note the void):

public static void max(double num1, double num2) { 
System.out.println (Math.max(num1, num2));
}

Besides that, the point of the first one is that it only does what it says it does. It returns the max of the two numbers; nothing else. The second one is called max but for some reason it writes to the console. With the first one, you can do anything you like with the max value. With the second, you can only print it to console.

How to get a system.out.println to return in a method

Firstly, the declaration of displayMenus is invalid. You need to give it a return type (even if that is void), e.g.:

public static void displayMenus () {

If you make it void, you would need to invoke displayMenus() without calling System.out.println:

displayMenus();

If you make it String, you would need to build a String in displayMenus and return it, e.g.:

public static String displayMenus() {
return "First - 1" + ...;
}

then you can invoke System.out.println(displayMenus()).

The connection between 'System.out.println()' and 'toString()' in Java

System.out is a PrintStream. Printstream defines several versions of the println() function to handle numbers, strings, and so on. When you call PrintStream.println() with an arbitrary object as a parameter, you get the version of the function that acts on an Object. This version of the function

...calls at first String.valueOf(x) to get the printed object's string value...

Looking at String.valueOf(Object), we see that it returns

if the argument is null, then a string equal to "null"; otherwise, the value of obj.toString() is returned.

So, long story short, System.out.println(someObject) calls that object's toString() function to convert the object to a string representation.

If your object defines its own toString() function, then that is what will be called. If you don't provide such a function, then your object will inherit toString() from one of its parent classes. In the worst case, it will inherit Object.toString(). That version of toString() is defined to return

a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object.

Or, in other words:

getClass().getName() + '@' + Integer.toHexString(hashCode())

So, when you call System.out.println() on an object that doesn't define its own version of toString(), you might get the Object version which looks like "classname@someHexNumber".

Mutithreading with System.out.format and System.out.println

There is no difference in whether you use System.out.print or System.out.format: they're basically doing the same thing.

The deadlock occurs here if execution of Gaston.bow(Alphonse) is started between the start of Alphonse.bow(Gaston) and bower.bowBack(Alphonse) (or vice versa): the two threads are waiting for a monitor held by the other, and thus deadlock occurs.

This happens inconsistently, because it depends upon a subtle timing issue, depending upon how the threads are scheduled - it is possible that Alphonse.bow and bower.backBack(Alphonse) complete before Gaston.bow is executed, so it looks like there is no deadlock.

The classic way to fix this is to order the lock acquisition, so that the first the same lock is acquired first every time; this prevents the possibility of deadlock:

public void bow(Friend bower) {  // Method no longer synchronized.
int firstHash = System.identityHashCode(this);
int secondHash = System.identityHashCode(bower);

Object firstMonitor = firstHash < secondHash ? this : bower;
Object secondMonitor = firstHash < secondHash ? bower : this;
synchronized (firstMonitor) {
synchronized (secondMonitor) {
// Code free (*) of deadlocks, with respect to this and bower at least.
}
}
}

(*) It's not quite guaranteed to be deadlock free, since System.identityHashCode can return the same value for distinct objects; but that's reasonably unlikely.

It's an application of the Birthday paradox: if you've got just two monitors, the chance of collision is something like 10^-18; but if you've got >77k monitors, a collision is more likely than not.

How does System.out.print() work?

System.out is just an instance of PrintStream. You can check its JavaDoc. Its variability is based on method overloading (multiple methods with the same name, but with different parameters).

This print stream is sending its output to so called standard output.


In your question you mention a technique called variadic functions (or varargs). Unfortunately that is not supported by PrintStream#print, so you must be mistaking this with something else. However it is very easy to implement these in Java. Just check the documentation.


And if you are curious how Java knows how to concatenate non-string variables "foo" + 1 + true + myObj, it is mainly responsibility of a Java compiler.

When there is no variable involved in the concatenation, the compiler simply concatenates the string. When there is a variable involved, the concatenation is translated into StringBuilder#append chain. There is no concatenation instruction in the resulting byte code; i.e. the + operator (when talking about string concatenation) is resolved during the compilation.

All types in Java can be converted to string (int via methods in Integer class, boolean via methods in Boolean class, objects via their own #toString, ...). You can check StringBuilder's source code if you are interested.


UPDATE: I was curious myself and checked (using javap) what my example System.out.println("foo" + 1 + true + myObj) compiles into. The result:

System.out.println(new StringBuilder("foo1true").append(myObj).toString());

What is the difference between void and return even though I can get same output on both?

The point is not to get the result but the way we get the result

consider

public static void getSum(int x, int y)
{
int sum = x + y;
System.out.println("sum = " + sum);
}

will print the output to the screen after calculation

but when we use return
as you have done it later

public static int getSum(int x, int y)
{
int sum = x + y;
return sum;
}

this function will respond back the sum. that sum can be stored in a variable
can be used afterwards
like in recursion



Related Topics



Leave a reply



Submit