aspose file tools*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes toString() and null Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "toString() and null" Watch "toString() and null" New topic
Author

toString() and null

Vishnu Prakash
Ranch Hand

Joined: Nov 15, 2004
Posts: 1026


/* 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.

*/


Servlet Spec 2.4/ Jsp Spec 2.0/ JSTL Spec 1.1 - JSTL Tag Documentation
Kedar Savarkar
Greenhorn

Joined: May 02, 2005
Posts: 15
//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.
Lalitha Gottumukkula
Ranch Hand

Joined: May 24, 2005
Posts: 45
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.
miguel lisboa
Ranch Hand

Joined: Feb 08, 2004
Posts: 1281
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


java amateur
Kedar Savarkar
Greenhorn

Joined: May 02, 2005
Posts: 15
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.
Chitra AP
Ranch Hand

Joined: May 25, 2005
Posts: 42
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

Joined: Feb 08, 2004
Posts: 1281
try reruning with toString() commented out
Andrew Moores
Greenhorn

Joined: May 28, 2005
Posts: 12
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

Joined: May 25, 2005
Posts: 42
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);
Tony Morris
Ranch Hand

Joined: Sep 24, 2003
Posts: 1608
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 ]

Tony Morris
Java Q&A (FAQ, Trivia)
miguel lisboa
Ranch Hand

Joined: Feb 08, 2004
Posts: 1281
i guess the following code states my point:
Reghu Ram Thanumalayan
Ranch Hand

Joined: Oct 21, 2003
Posts: 193
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.


Cheers,<br />Reghu Ram T<br /> <br />SCJP 1.4 - 98 %, SCBCD 1.3 - 94 %, SCMAD 1.0 - 92 %
Reghu Ram Thanumalayan
Ranch Hand

Joined: Oct 21, 2003
Posts: 193
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 ) ???
SomeswaraRao Vudattula
Greenhorn

Joined: Mar 28, 2005
Posts: 12
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
Yafeng Guo
Greenhorn

Joined: May 27, 2005
Posts: 1
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

Joined: Feb 08, 2004
Posts: 1281
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

Joined: Sep 24, 2003
Posts: 1608
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 ]
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
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.


"I'm not back." - Bill Harding, Twister
Soni Prasad
Ranch Hand

Joined: Mar 09, 2005
Posts: 97
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.


SCJP 1.4, SCBCD 1.3
Tony Morris
Ranch Hand

Joined: Sep 24, 2003
Posts: 1608

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
shiva rao
Ranch Hand

Joined: May 26, 2005
Posts: 31
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.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: toString() and null