• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Tim Cooke
  • Campbell Ritchie
  • paul wheaton
  • Ron McLeod
  • Devaka Cooray
Sheriffs:
  • Jeanne Boyarsky
  • Liutauras Vilda
  • Paul Clapham
Saloon Keepers:
  • Tim Holloway
  • Carey Brown
  • Piet Souris
Bartenders:

toString() and null

 
Ranch Hand
Posts: 1026
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


/* Please explain the print statements

"null" which is returned from toString() implementation is itself of type String. Then why we need to use toString() method in first print statement.
Why without toString() method in second print statement (which is commented) is producing a null pointer exception.
Why t3 which is asssigned a "null" value is producing an output null without a call to toString() method.
Why t4 is producing null without a call to toString() method.

*/
 
Greenhorn
Posts: 15
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
//System.out.println(t1); // Will produce NullPointerException

Here the effect is same as System.out.println(null).Actual null object is returned not the string "null"
When the commented line is called it calls the overloaded method
System.out.println(Object). In all other cases System.out.println(String)
is called.
 
Ranch Hand
Posts: 45
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Kedar,

Confused with the overloaded versions of System.out.println(). Let me know which versions are being called in the following print statements :


All t1, t2, obj, str are returning null. But error is with only t1. How?

Thanks,
Lalitha.
 
Ranch Hand
Posts: 1282
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
i'm not sure, but i guess the reason why if you uncomment you'll obtain a NPE is because of your toString() method

there you say to return null in case i == 0; so that's what you get
 
Kedar Savarkar
Greenhorn
Posts: 15
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Lalita,

My explanation seems to be wrong. After looking at your code it is clear that the NPE is thrown only when the overridden toString() is called. But I wonder why ?

Another thing

System.out.println(null); //Compile Time error Will produce NPE

final Test01 t1 = null;
System.out.println(t1); // No Compile time error. Why ?


As t1 is a compile time constant the behavior should be same as above since compiler would substitute null for t1 in the SOP() statement.
 
Ranch Hand
Posts: 42
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I don't think Miguel's explanation is correct.

Because the other string objects are also null here and it is not giving nullpointerexception. Can someone please explain this?

Thanks
 
miguel lisboa
Ranch Hand
Posts: 1282
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
try reruning with toString() commented out
 
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think the issue lies with the println method. When you use println with a String type reference variable println figures out that it should actually call the toString() method to get the string of characters. So if you have a variable String x = null, System.out.println("x is " + x) will compile and will run, printing 'x is null'.

However if you make the parameter a call to a method then this functionality is lost. So, System.out.println("X is " + x.toString()) will give NullPointerException.

When you call the method the result will be the value null, and the value null will be passed to println. However if you place a reference variable in the argument list then a copy of the reference variable (from which its type can be determined) is passed instead. From the value null println can have no way of knowing if the null has come from an object of type String or some other object type and so it decides that it must self destruct and give a NPE.

--Andrew
 
Chitra AP
Ranch Hand
Posts: 42
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It should give the NullPointerException for this line also, correct?
(the code as mentioned in the first topic)

Test01 t3 = null;
System.out.println("t3 = " + t3);
 
Ranch Hand
Posts: 1608
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You have found some interesting (apparantly undocumented? I find nothing in the JLS or API Specification and assume nothing in the VM Specification) behaviour.

I stepped through your code using a debugger, and it's quite clear that java.io.Writer.write does indeed dereference a null reference. I'd be keen to know if anyone can find any further reference to this behaviour - my search, though not conclusive was in all the obvious places. I have to shoot off to squash now anyway. The behaviour of the String concatenation (+) is specified in the JLS and explicitly specified how a null reference is handled.

Here is your test case trimmed to reproduce the problem:

[ May 30, 2005: Message edited by: Tony Morris ]
 
miguel lisboa
Ranch Hand
Posts: 1282
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
i guess the following code states my point:
 
Ranch Hand
Posts: 193
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello All,
The reason for this behavior is due to the fact that String concatenation is done internally using StringBuffer.

One more point is passing an object to print will internally invoke it's toString method. So "t1: " + t1 is has similar effect as "t1: " + t1.toString().

Now coming to the concatenation part, when u call println with "t1: " + t1, this is internally converted to something like

StringBuffer temp = new StringBuffer("t1: ").append(t1);

Now when a null is passed to the append method, which inturn calls the String.valueOf(obj) method and this method returns the "null" String.

public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
So finally u get the string "t1: null" as the output.

But when a null is passed directly to the println method, it throws a null pointer exception since println inturn makes a call to the overloaded String.valueof(char[] data) and not String.valueof(Object obj) and since data is null, a null pointer exception is generated.

Hope this helps.
 
Reghu Ram Thanumalayan
Ranch Hand
Posts: 193
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Now i am wondering what type is null.

Since the call String.valueOf(null) matches String.valueOf(char[] data) and not String.valueOf(Object obj), it is clear that null is not an object.

Then is it a primitive ( char array ) ???
 
Greenhorn
Posts: 12
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Chitra and Lalitha,

pls here me....

when u r printing the object directly..it will call toString() internally... so that value will be null.so it is showing Null Pointer Exception..
SYstem.Out.println(t);

in this case :
System.out.println("T1:"+t1);
t1 is null..but ist is adding with String.. so it will show T1:null;
in this Case :

System.out.println("T1:"+t1.toString());
here also it returns null but it will concatinate with String and showing T1:null
 
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Reghu,
I think you are right. null is not an object. Together with "ture" and "false", they are called "manifest constants".

Regards,
Yafeng
[ May 30, 2005: Message edited by: Yafeng Guo ]
 
miguel lisboa
Ranch Hand
Posts: 1282
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
taken from java language specification:

The types of the Java programming language are divided into two categories: primitive types and reference types. The primitive types (�4.2) are the boolean type and the numeric types. The numeric types are the integral types byte, short, int, long, and char, and the floating-point types float and double. The reference types (�4.3) are class types, interface types, and array types. There is also a special null type.
(...)
4.1 The Kinds of Types and Values
There are two kinds of types in the Java programming language: primitive types (�4.2) and reference types (�4.3). There are, correspondingly, two kinds of data values that can be stored in variables, passed as arguments, returned by methods, and operated on: primitive values (�4.2) and reference values (�4.3).

Type:
PrimitiveType
ReferenceType

There is also a special null type, the type of the expression null, which has no name. Because the null type has no name, it is impossible to declare a variable of the null type or to cast to the null type. The null reference is the only possible value of an expression of null type

 
Tony Morris
Ranch Hand
Posts: 1608
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Let's get back on track.


This is undocumented behaviour, from both the JLS and API Specification. Many Java APIs have poorly specified, erroneous, or just plain silly behaviour. However, this behaviour seems to be quite fundamental and one that would almost certainly have had documentation attached to it.

Can anyone find it before I conclude that it doesn't exist? Admittedly, I have yet to search the Sun bug database. My existing speculation is the failure to acknowledge the concept of "fail early" by the Sun "engineers". That is, call .toString() and if null, fail immediately, and document it that way (@throws NullPointerException). Although "fail early" was overlooked, it should at least still be a documented behaviour.
[ May 30, 2005: Message edited by: Tony Morris ]
 
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Tony- I don't think there's any more relevant documentation than what you have doubtless already found. The trail is pretty clear up to String's print(Object) where it says to take String.valueOf() and then the value "is translated into bytes according to the platform's default character encoding". I suppose one could argue that Sun has specifically ceded control of this process to the platform. I don't know of any standard character encodings that allow the representation of a null (as distinct from an empty string), so it seems reasonable to me to expect that an NPE might very well result from this operation. But it would be nice if the API said so.

On the other hand, one could argue that the toString() method in this case has violated the basic contract of the toString() method. It's supposed to return "a string representation of the object". A null is not a string representation of the object. I suppose they could explicitly say "must not be null" but personally I think that's unnecessary. If a programmer is required to return a string, they shouldn't return a null -- else they shouldn't be surprised to get a NullPointerException shortly thereafter. The latter consequence does not appear to be explicitly documented, true. As for "fail early" - well, we do get a NullPointerException as soon as we call the println() method. Maybe it would be nice if it didn't have any other methods deeper in the call stack, and if it specifically identified which variable was the problem (a common issue with NPE of course). But the behavior doesn't seem too unreasonable to me.
 
Ranch Hand
Posts: 97
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
System.out.println("t1: " + t1.toString());

in the above case toString() is called on t1 which is not null and the toString() method of Test01 returns null String because i=0

public String toString(){
if(i == 0) return null;
else return "" + i;

}


and null String will be passed to

public void print(Object obj) {
write(String.valueOf(obj));
}

and further to

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

and it prints "t1: null"

but

System.out.println(t1); //t1.toString() but t1 is null so NPE

toString() is being called on a null object and calling a method on null object will throw NPE.

I think in the first case toString() method is never called on a null Object rather null object is passed as an argument to a method so it is not throwing NPE but in the second case a method (toString()) is being called on a null object so we got NPE .

soni.
 
Tony Morris
Ranch Hand
Posts: 1608
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


toString() is being called on a null object and calling a method on null object will throw NPE.


Objects cannot be null, only references*.
The only reference is t1, which is not null.

I think Jim Yingst pretty much hit it on the head. The only way I think any of this can be contradicted is by finding some source of information in any one of the specifications.

*What is the difference between an object and an object reference? http://qa.jtiger.org/GetQAndA.action?qids=75&showAnswers=true
 
Ranch Hand
Posts: 31
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
class Test01{
int i;

public Test01(int i) { this.i = i; }

public String toString(){
System.out.println("Entered into toString()"); // remark 1
if(i == 0) return null;
else return "" + i;

}
public String call() {
return null;
}

public static void main(String[ ] args){
Test01 t1 = new Test01(0);
Test01 t2 = new Test01(2);
Test01 t3 = null;
Test01 t4 = new Test01(0);
t4 = null;
System.out.println("t1: " + t1.toString()); // Will not produce NullPointerException
//System.out.println(t1); // Will produce NullPointerException
System.out.println("t2: " + t2);
System.out.println("t3: " + t3);
System.out.println("t4: " + t4);
System.out.println(null);
System.out.println("t1 method: " + t1.call());
}
}

I added a line to toString (remark 1), I found the interesting thing is for t1 and t2 it called the toString method but not for t3 and t4 S.O.P. And one more thing is when we pass null to the S.O.P it giving the ambitious method call.
reply
    Bookmark Topic Watch Topic
  • New Topic