-6

The default return of an object in Java is to return the toString method, is there a way to change this behavior to for example return a number or some other type or is this just a core unchangeable component of the language?

Test test = new Test();
blankMethod(test);

I am not sure why people are saying my assumption is wrong... if I Override the toString method of object it will output that new toString method...

@Override
public String toString() {
    System.out.println("This method is run when the object is used as a parameter");
    return "test";
}
CodeCamper
  • 6,609
  • 6
  • 44
  • 94
  • 2
    Your assumption is wrong. The value of reference type is the value of a reference to the object. Separately, there is an overloaded `println` method which accepts an argument of type `Object` and invokes its `toString` method. – Sotirios Delimanolis Mar 11 '15 at 02:18
  • 1
    `"The default return of an object in Java is to return the toString method"` -- where did you find this bit of information? – Hovercraft Full Of Eels Mar 11 '15 at 02:18
  • 2
    Your confusing what `PrintStream#println(...)` does, which is to call `toString()` on an object, with an innate property of an object. These are two completely different things. – Hovercraft Full Of Eels Mar 11 '15 at 02:19
  • 2
    It could be improved by getting rid of the bad premise, and giving more information about what CodeCamper is trying to achieve. – Patricia Shanahan Mar 11 '15 at 02:20
  • @PatriciaShanahan: you are right, apologies to CodeCamper. – Hovercraft Full Of Eels Mar 11 '15 at 02:22
  • To be fair, this is a real edge case of the language and for newcomers I can see how this would trip them up. – Dave Swartz Mar 11 '15 at 02:24
  • 1
    And in my comment, it should be should be `"You're ..."`. Ugh. – Hovercraft Full Of Eels Mar 11 '15 at 02:26
  • @SotiriosDelimanolis if my assumption is wrong then how come when I overload the toString method of object it outputs my new toString method? – CodeCamper Mar 11 '15 at 02:29
  • Read up on inheritance. – Sotirios Delimanolis Mar 11 '15 at 02:31
  • @SotiriosDelimanolis I understand inheritance, I understand abstract classes, classes, interface.... I am not sure why you are saying my assumption is wrong. In my code example if you just pass object as a parameter it magically runs the toString method... I added code to show you as an example... I was only using the System.out.println to demonstrate the behavior of calling "object"... ugh... semantic confusion... – CodeCamper Mar 11 '15 at 02:33
  • [Here's](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/io/PrintStream.java#PrintStream.print%28java.lang.Object%29) the implementation of `PrintStream#println(Object)`. – Sotirios Delimanolis Mar 11 '15 at 02:36
  • @HovercraftFullOfEels read the code I added, when you pass an object into a parameter it runs the toString method... just a trivial question of whether you can change this default behavior. – CodeCamper Mar 11 '15 at 02:37
  • When you pass a object as an argument **to `PrintStream#println(Object)`**. This is specific to this method. – Sotirios Delimanolis Mar 11 '15 at 02:38
  • @CodeCamper: no, you can only change the `toString()` returned, that's all. But regardless, `toString()` is not to be used in production code, but rather mainly for debugging purposes, so for an end product, this is a moot question. – Hovercraft Full Of Eels Mar 11 '15 at 02:38
  • @SotiriosDelimanolis I don't think you understand my question... not sure how to reword this... I guess the answer is no, I remember there was a way to do this in C#... – CodeCamper Mar 11 '15 at 02:38
  • @CodeCamper I **know** I don't understand your question. It might be helpful to go up a level, and explain what you are trying to achieve, or even show the C# code that does what you want. – Patricia Shanahan Mar 11 '15 at 02:52
  • @PatriciaShanahan in C# it can be accomplished using `static implicit operator`. It is interesting in Java that the only implicit operator of an object is actually a String and that behavior cannot be changed. Would have been a nice thing to add in Java 8... – CodeCamper Mar 11 '15 at 03:03
  • @CodeCamper Try Scala. – Dave Swartz Mar 11 '15 at 03:07
  • I am a fan of Scala School by Twitter (https://twitter.github.io/scala_school/). – Dave Swartz Mar 11 '15 at 03:13

3 Answers3

2

The default return of an object in Java is to return the toString method

That's how PrintStream.println works. Any object in java extends java.lang.Object and therefore inherits Object behavior. In particular, any method which takes Object as an argument, also can take any object of another type. However, you can override any public or protected method defined in Object. In your case you should override toString() method in Test class, otherwise if you pass Test object to PrintWriter.println(), it'll use toString from superclass (Object in your case). So, if i understood your question correctly, the answer is no.

Update: your terminology is wrong. There is no default return of an object in java. Returning Object.toString is the default behavior only for PrintStream.println(Object).

Update2: more widely, Java doesn't support implicit type conversion except upcasting. In your case, Test extends Object, but it doesn't extend String (actually, String is final and therefore you can't extend it). So, if you try to pass Test object to method which only takes String, you'll get compilation error because String and Test belong to different branches of class hierarchy.

Community
  • 1
  • 1
Everv0id
  • 1,862
  • 3
  • 25
  • 47
  • If you create a blank method and pass the object in I am pretty certain it still runs the toString method. – CodeCamper Mar 11 '15 at 02:59
  • If you pass `Test` object to a method which only takes `String`, you'll get compilation error. No implicit `toString()` calls. – Everv0id Mar 11 '15 at 03:03
  • You are right, that is really strange... when you pass an object parameter the default behavior of every object is to return a String via toString... but you can't implicitly return an object where a String is required even though I can't change it and every object MUST return a String when the object is requested... Not very logical to me... – CodeCamper Mar 11 '15 at 03:07
  • Nothing strange. You're saying about [automatic type convertion](http://stackoverflow.com/questions/2406155/automatic-type-conversion-in-java). So, the answer is simple: java doesn't support implicit type convertion except upcasting. – Everv0id Mar 11 '15 at 03:14
1

You are actually calling

PrintStream.println(Object x)

instead of

public void println(String x)

The PrintStream.println(Object x) implementation is below:

public void println(Object x) {
     String s = String.valueOf(x);
     synchronized (this) {
        print(s);
        newLine();
    }
}

The method calls String.valueOf(x) whose implementation is below:

public static String valueOf(Object obj) {
   return (obj == null) ? "null" : obj.toString();
}

Note that the Object.toString() method is being called.

Notes on implicit conversion

An Object is only implicitly converted to a String using the toString method when the string concatenation operator (+) is invoked. More exactly the conversion works as follows:

A value x of primitive type T is first converted to a reference value...

This reference value is then converted to type String by string conversion. Now only reference values need to be considered.

If the reference is null, it is converted to the string "null" (four ASCII characters n, u, l, l). Otherwise, the conversion is performed as if by an invocation of the toString method of the referenced object with no arguments; but if the result of invoking the toString method is null, then the string "null" is used instead.

The toString method is defined by the primordial class Object"

Java Language Specification 15.18.1

One language (of many) that expand on the idea of implicit conversions is Scala which allows one to bring a conversion (e.g., A -> B) into scope which is then invoked whenever some type (A) is passed as an argument when a different type (B) is required.

Community
  • 1
  • 1
Dave Swartz
  • 910
  • 6
  • 14
  • I don't think this is correct, because use my override method in my updated question. You will see the toString method is always run. When you use the object as any parameter. – CodeCamper Mar 11 '15 at 02:43
  • This answer also contradicts the documentation. Ultimately, the conversion is done by [String.valueOf(Object)](http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#valueOf%28java.lang.Object%29): "if the argument is null, then a string equal to "null"; otherwise, the value of obj.toString() is returned.". In this case, it is not null. – Patricia Shanahan Mar 11 '15 at 02:45
  • I was paraphrasing, but since it is creating confusion I will update the answer. – Dave Swartz Mar 11 '15 at 02:47
  • @CodeCamper I updated my answer to hopefully clarify. I expanded on implicit conversions in Java and other languages. – Dave Swartz Mar 11 '15 at 03:09
1

This answers "why people are saying my assumption is wrong".

Here is a simple program:

public class Test {
  public String toString(){
    return "I am a Test object.";
  }

  public int add(int a, int b){
    return a+b;
  }
  public static void main(String[] args) {
    Test object = new Test();
    System.out.println(object);
    System.out.println(object.add(2,2));
    System.out.println(adder(object));
  }

  public static int adder(Test test){
    return test.add(3,5);
  }
}

Output:

I am a Test object.
4
8

The System.out.println method has to turn its argument into a String, one way or another. If it is passed an object reference, it uses its toString() method. If it is passed a primitive, such as an int expression, it converts it in an appropriate way.

It is nothing to do with what is being returned.

It also has nothing to do with any automatic conversion on passing a reference as an argument. See the third line of output, which depends on using the Test reference I passed to adder as a Test, not a String.

If you want to change what println prints, do what I did above, and pass it something different.

Patricia Shanahan
  • 25,849
  • 4
  • 38
  • 75