difference between null object and null string

G

gokul.b

please look at the code snippet below:-

public class PowerSupply {

public PowerSupply(Object voltage){
System.out.println ("PowerSupply(Object) executed");
}
public PowerSupply(String voltage){
System.out.println ("PowerSupply(String) executed");
}
public PowerSupply(){
System.out.println ("No argument constructor execute");
}
public static void main(String[] args) {
PowerSupply ps = new PowerSupply(null);
}
}

which is the constructor invoked?

The answer is the String constructor is invoked. I do not understand
why the Object constructor wasnt invoked.
in the case of" ps = new PowerSupply((Object)null)", the Object
constructor is invoked.

Any insight into the java' interpretation of null is greatly
appreciated!
thx
g
 
R

Roedy Green

The answer is the String constructor is invoked. I do not understand
why the Object constructor wasnt invoked.
in the case of" ps = new PowerSupply((Object)null)", the Object
constructor is invoked.

Print out what was passed. The mystery might become clear. null does
not have a type so (Object) null is meaningless
 
E

Eric Sosman

Roedy Green wrote On 10/10/05 16:17,:
Print out what was passed. The mystery might become clear. null does
not have a type so (Object) null is meaningless

`(Object)null' is meaningFUL, since using it changes
the behavior of the program. I'm not enough of a language
lawyer to say whether `null' has "no type" or "all types"
or "an inifintely flexible pseudo-typish sort of wossname,
seewatimean?" However, the expression `(Object)null' most
certainly has a type, namely, "reference to Object."
 
G

gokul.b

After I enabled printing of the input,if I pass a null, the output is
displayed as "null".

Interestingly, if I modify the constructor that takes an Object to a
constructor that takes an Integer, I get a compilation error (ambigous
definition of constructor).


I was expecting the ambigous definition of constructor in the very
first place. Dont know why java simpley "ignores" a constructor that
takes an Object
 
S

Stefan Ram

Eric Sosman said:
the behavior of the program. I'm not enough of a language
lawyer to say whether `null' has "no type" or "all types"

The type of the null literal is "null". JLS3, 3.10.7.
 
E

Eric Sosman

After I enabled printing of the input,if I pass a null, the output is
displayed as "null".

Interestingly, if I modify the constructor that takes an Object to a
constructor that takes an Integer, I get a compilation error (ambigous
definition of constructor).


I was expecting the ambigous definition of constructor in the very
first place. Dont know why java simpley "ignores" a constructor that
takes an Object

Java does not "ignore" the (Object) constructor. Java
has a whole lot of rules to determine how overloaded methods
and constructors are resolved. They're spelled out in great
detail in the Java Language Specification, but the informal
notion is that Java uses the "most specific" overloading that
it can. Consider these three methods with the same name:

void method(Object o) { System.out.println(1); }
void method(Number n) { System.out.println(2); }
void method(Integer i) { System.out.println(3); }

When you write `method(new HashMap())' which method is
called? Well, a HashMap is not an Integer and not a Number,
but it is an Object and so method #1 is called; it's the
only possible candidate.

Things get more interesting when more than one candidate
might be applicable, as in `method(new Integer(42))'. All
three methods could conceivably apply, since an Integer is
an Integer (duh...), but is also a Number and also an Object.
Java resolves this in favor of method #3, because Integer is
the "most specific" description for an Integer reference.

Finally, consider `method(new Double(42.0))'. A Double
is not an Integer so method #3 isn't called, but a Double is
a Number and is an Object. Number is "more specific" than
Object, so method #2 is called.

Now to your case. You wrote `method(null)' (in essence)
and since `null' itself carries no type information it's not
immediately clear what should happen. Java considers Object,
Number, and Integer, and finds that all three of them could
match `null'. However, Integer is still the "most specific,"
so method #3 is used. You could get different results (which
ones?) by writing `method((Long)null)' or `method((URL)null)'.

But then you changed things by adding yet another method:

void method(String s) { System.out.println(4); }

This muddies the waters. The calls with HashMap, Integer,
and Double and with `null' cast to a type work just as before,
but what about the call with plain `null' as an argument? All
four methods might apply, but now Java can't decide what to
do because String and Integer are "equally specific." javac
throws up its hands and tells you to stop speaking in riddles.

Things get more complex when there are multiple arguments,
when you've got classes that implement several interfaces, and
so on. The exact rules are in the JLS, but mostly they just
try to formalize this notion of "more specific."
 
Z

zero

Java does not "ignore" the (Object) constructor. Java
has a whole lot of rules to determine how overloaded methods
and constructors are resolved. They're spelled out in great
detail in the Java Language Specification, but the informal
notion is that Java uses the "most specific" overloading that
it can. Consider these three methods with the same name:

void method(Object o) { System.out.println(1); }
void method(Number n) { System.out.println(2); }
void method(Integer i) { System.out.println(3); }

<snipped>

Excellent explanation :) One question though: what happens when you use
method call method(1) - ie with an int. Does it, as I would expect, get
converted to Integer, calling the third method?
 
R

Ross Bamford

Print out what was passed. The mystery might become clear. null does
not have a type so (Object) null is meaningless

Actually I think the compiler uses it as a hint as to which method
descriptor to generate the call to. If, in the source, you just have
'null' , evidently it creates an INVOKESPECIAL
<init>(Ljava/lang/String;)V. If, however, in your source you
specify (Object)null, then the generated instruction points instead to
<init>(Ljava/lang/Object;)V .

It's true that null has no type in the JVM, but obviously it helps the
compiler decide which (non-virtual) constructor to dispatch to.

I'm not sure what the order of preference is if unspecified, though I
imagine it's defined in the spec.
 
J

John C. Bollinger

Stefan said:
The type of the null literal is "null". JLS3, 3.10.7.

That's not quite what the referenced material says, but it is true that
formally speaking the null literal has a type, the null type. Per JLS3,
4.1:

"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.
The null reference can always be cast to any reference type. In
practice, the programmer can ignore the null type and just pretend that
null is merely a special literal that can be of any reference type."

Note: when the text says "the null type has no name" it is referring to
a name recognized by Java; it certainly does have a name by which the
JLS refers to it ("the null type").

Every rvalue expression in Java, including the null literal, has one and
only one type.
 
J

John C. Bollinger

Ross said:
Actually I think the compiler uses it as a hint as to which method
descriptor to generate the call to. If, in the source, you just have
'null' , evidently it creates an INVOKESPECIAL
<init>(Ljava/lang/String;)V. If, however, in your source you
specify (Object)null, then the generated instruction points instead to
<init>(Ljava/lang/Object;)V .

It's more than a hint. "(Object) null" is a typecast expression whose
/type/ is Object and whose /value/ is null. The compiler uses the type
of the expression to select the appropriate method.
It's true that null has no type in the JVM

No, it isn't. See other posts in this thread, or read JLS3 section 4.1.
, but obviously it helps the
compiler decide which (non-virtual) constructor to dispatch to.

I'm not sure what the order of preference is if unspecified, though I
imagine it's defined in the spec.

Naturally; See JLS3 section 15.12. Be warned: this is a lengthy and
complicated section of the spec. For the less intrepid, Eric Sosman
gave a good run-down of how all that applies to this particular case.
 
R

Roedy Green

It's true that null has no type in the JVM, but obviously it helps the
compiler decide which (non-virtual) constructor to dispatch to.

It seems to me that (Integer)null might either be a compile time error
or invalid cast exception at run time. From the discussions, I gather
neither happens.

I guess what Eric's findings mean is :

Integer n = null;
someMethod ( n );

has the same effect as

someMethod ( (Integer) null );
 
H

Hendrik Maryns

zero schreef:
@news1brm.Central.Sun.COM:




<snipped>

Excellent explanation :) One question though: what happens when you use
method call method(1) - ie with an int. Does it, as I would expect, get
converted to Integer, calling the third method?

Only if you use 5.0, which does autoboxing. In 1.4, you'd get an error.

--
Hendrik Maryns

==================
www.lieverleven.be
http://aouw.org
 
R

Ross Bamford

It seems to me that (Integer)null might either be a compile time error
or invalid cast exception at run time. From the discussions, I gather
neither happens.
I guess what Eric's findings mean is :
Integer n = null;
someMethod ( n );
has the same effect as
someMethod ( (Integer) null );

Internally, CHECKCAST doesn't throw on null, and it does also influence
the runtime type of the reference. For example, if you have an Object on
top of the stack and want to return if from a String method, you have to
first do a checkcast on it. So yes, since a cast of null never actually
makes it into bytecode, and is just used by the compiler to decide which
overload to dispatch to before being discarded, they are equivalent. The
compiler uses the dynamic type of 'this', and the static types of the
arguments to select an overload to call. So in this case, although the
null cast is really nonsense, the compiler takes it as a hint about which
method descriptor to go for.

I just did a quick experiment, and this is borne out. Assuming the
existence of a String and Object overload, the statments:

aMethod(null);

aMethod((Object)null);

Object aNull = null;
aMethod(aNull);

come out as:

ALOAD 0
ACONST_NULL
// stack now - this .. null
INVOKEVIRTUAL aMethod(Ljava/lang/String;)V

ALOAD 0
ACONST_NULL
// stack now - this .. null
INVOKEVIRTUAL aMethod(Ljava/lang/Object;)V

L1:
ALOAD 0
ACONST_NULL
ASTORE 1
L2:
ALOAD 1
// stack now - this .. null
INVOKEVIRTUAL aMethod(Ljava/lang/Object;)V

Interestingly, adding a primitive 'int' overload and then casting the null
to (Integer), which you would expect to dispatch to the primitive overload
in Java 5 (thanks to unboxing) instead dispatches to the Object version.
That could be a nasty little gotcha I guess...
 
M

Mike Schilling

John C. Bollinger said:
Naturally; See JLS3 section 15.12. Be warned: this is a lengthy and
complicated section of the spec. For the less intrepid, Eric Sosman gave
a good run-down of how all that applies to this particular case.

If you can find JLS2, read the corresponding section there instead. It
answers the question about null as an argument without haveing to discuss
variable-length parameter lists, generics, etc. Still complex, but not
brain-damaging the way JLS3 is.
 
R

Ross Bamford

This is a reply, to a reply by John C. Bollinger, about the message below.
Something's gone a bit wrong here, and I've lost the reply itself - sorry!

Actually I think the compiler uses it as a hint as to which method
descriptor to generate the call to. If, in the source, you just have
'null' , evidently it creates an INVOKESPECIAL
<init>(Ljava/lang/String;)V. If, however, in your source you
specify (Object)null, then the generated instruction points instead to
<init>(Ljava/lang/Object;)V .

It's true that null has no type in the JVM,
<J.C. Bollinger refers me to JLS>

Well, granted, but I'm more of a nuts and bolts man so I try to keep out
of the JLS as much as possible (it hurts my head ;)). Thanks for boiling
down what it says :) What I was getting at, though, was that in real terms
inside the JVM itself, null has no _runtime type_ of it's own, and can be
cast to to any other type.

I see so much grossly incorrect and misleading information pass through
this newsgroup, that it's good to see the heavyweights still jumping on
the only-slightly-relevant detail from the occasional poster.
but obviously it helps the compiler decide which (non-virtual)
constructor to dispatch to.

I'm not sure what the order of preference is if unspecified, though I
imagine it's defined in the spec.

<J.C. Bollinger refers me to JLS>

When I said "I imagine it is", I meant say "It is, but I cannot be
bothered to find the reference. Go look if you're interested". Thanks for
covering my laziness ;)
 
M

Mike Schilling

Roedy Green said:
It seems to me that (Integer)null might either be a compile time error
or invalid cast exception at run time. From the discussions, I gather
neither happens.


I guess what Eric's findings mean is :

Integer n = null;
someMethod ( n );

has the same effect as

someMethod ( (Integer) null );

Yes. I think this is true in general, with any type substitued for Integer
and any value substituted for null.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top