Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / February 2006

Tip: Looking for answers? Try searching our database.

Java most wanted: Non-null variables

Thread view: 
Jacob - 30 Jan 2006 08:25 GMT
A well designed API normaly doesn't accept null as parameter
values, so as a programmer you are forced to test most inputs
against null and throw an IllegalArgumentException in case it
is null. All these cases must be properly documented in the
javadoc section with an appropriate @throws tag.

Likewise in private APIs you would do the same thing but possibly
by using asserts instead of exceptions.

All of this is good and has excellent documentation value, but
it is commonly ommited, in particular by inexperienced developers,
or by experienced developers in a hurry, and it just seams like
an issue that could be better supported by the language itself.

What about attaching a "&" character next to the variable to
indicate that it cannot be null. (Just kidding :-)

Any opinions?
Bart Cremers - 30 Jan 2006 09:01 GMT
Jetbrains added something like this to IntelliJ when using 1.5. They
added two annotations which can be used on different levels, @Nullable
and @NotNull.

@NotNull
public String myMethod(@NotNull String s, @Nullable Object o) {
...
}

means the method should not return null, s should not be null and o can
be null. The compiler could check on this.

Bart
Roedy Green - 30 Jan 2006 10:03 GMT
>Jetbrains added something like this to IntelliJ when using 1.5. They
>added two annotations which can be used on different levels, @Nullable
>and @NotNull.
>
>@NotNull
>public String myMethod(@NotNull String s, @Nullable Object o) {

Hey , my wish come true.
Now only  the money for  a copy of Intellij would appear.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Stefan Schulz - 30 Jan 2006 11:06 GMT
> >Jetbrains added something like this to IntelliJ when using 1.5. They
> >added two annotations which can be used on different levels, @Nullable
[quoted text clipped - 5 lines]
> Hey , my wish come true.
> Now only  the money for  a copy of Intellij would appear

IIRC: There is an Eclipse plugin that does much the same thing.
Dimitri Maziuk - 30 Jan 2006 17:04 GMT
Roedy Green sez:

>>Jetbrains added something like this to IntelliJ when using 1.5. They
>>added two annotations which can be used on different levels, @Nullable
[quoted text clipped - 5 lines]
> Hey , my wish come true.
> Now only  the money for  a copy of Intellij would appear.

They do give it away for free if your code comes with the source
(and they aren't as anal about the definition of "open source"
as GNU/"Free Software" crowd).

Note, however, that in a public method that only works if code
analyser has access to all code that will ever call the method.

(That's another thing that annoys me about Java: things that don't
work unless you have *all* your code under one root.)

Dima
Signature

Backwards compatibility is either a pun or an oxymoron.                  -- PGN

Stefan Schulz - 30 Jan 2006 11:10 GMT
> Jetbrains added something like this to IntelliJ when using 1.5. They
> added two annotations which can be used on different levels, @Nullable
[quoted text clipped - 9 lines]
>
> Bart

Like this?

TouringMachine tm = new TouringMachine(program);
String s = null;

if (tm.halts()){
 s = "Halts";
}

myMethod(s, null);

The best you will be able to get is capturing the obvious case of
calling myMethod with a direct null, but a null resulting in another
operation will not always be detected by the compiler, take my word for
it.

Also, i would not be quite as harsh as never allowing nulls. They can
sometimes be safely used (for example, you could provide some callback
as null if there is no callback needed).
Bart Cremers - 30 Jan 2006 12:02 GMT
I know the compiler can not check it all, but it can catch part of the
mistakes at compile time.

At runtime a lot more is possible using annotations. See
http://oval.sourceforge.net for info on @NotNull combined with aspects
(aspectj) to perform runtime validation.

Bart
David  Wahler - 30 Jan 2006 15:45 GMT
> > @NotNull
> > public String myMethod(@NotNull String s, @Nullable Object o) {
[quoted text clipped - 16 lines]
>
> myMethod(s, null);

In a properly checked implementation, this last line should be a
compile error. Notice that s is declared as a String, not an @NotNull
String, and therefore cannot be directly passed to myMethod without a
runtime check, perhaps something like this:

myMethod((@NotNull String) s, null); // may throw NullableCastException

> The best you will be able to get is capturing the obvious case of
> calling myMethod with a direct null, but a null resulting in another
> operation will not always be detected by the compiler, take my word for
> it.

If the implementation is designed correctly, the compiler can indeed
catch all attempts to pass a null parameter. This is no different from
the compile-time checks Java already does for uninitialized variables
or type-checking; for example, the compiler is guaranteed to make it
impossible to call myMethod(123, 456).

In particular, it is _not_ equivalent to the halting problem, as your
"TouringMachine" example seemed to be implying.

> Also, i would not be quite as harsh as never allowing nulls. They can
> sometimes be safely used (for example, you could provide some callback
> as null if there is no callback needed).

Sure; just declare that parameter as @Nullable, or whatever syntax the
Powers That Be decide on.

-- David
Dimitri Maziuk - 30 Jan 2006 17:11 GMT
David  Wahler sez:
...

>> TouringMachine tm = new TouringMachine(program);
>> String s = null;
[quoted text clipped - 7 lines]
> In a properly checked implementation, this last line should be a
> compile error.

Bull: s is a pointer and there's no way to check at compile time
whether it's pointing to valid data or to 0xdeadbeef.

>> The best you will be able to get is capturing the obvious case of
>> calling myMethod with a direct null, but a null resulting in another
[quoted text clipped - 3 lines]
> If the implementation is designed correctly, the compiler can indeed
> catch all attempts to pass a null parameter.

Bullshit again: if the method is public, anyone can call it, including
code that has not been written yet. Compiler will have to be prescient
to check that.

Dima
Signature

Backwards compatibility is either a pun or an oxymoron.                  -- PGN

David  Wahler - 30 Jan 2006 22:01 GMT
> David  Wahler sez:
> ...
[quoted text clipped - 13 lines]
> Bull: s is a pointer and there's no way to check at compile time
> whether it's pointing to valid data or to 0xdeadbeef.

Why not? Java doesn't have pointer arithmetic, so the only way for a
reference variable to be null is if it is explicitly set to null (which
should not be allowed for a non-nullable variable) or if it is an
uninitialized member (again, shouldn't be allowed). If you flag those
two cases as compile errors, then a non-nullable variable will never be
able to contain null. Once you check all the cases (and by the way, I
apologize in advance if I've forgotten any), this is a straightforward
inductive proof.

> >> The best you will be able to get is capturing the obvious case of
> >> calling myMethod with a direct null, but a null resulting in another
[quoted text clipped - 7 lines]
> code that has not been written yet. Compiler will have to be prescient
> to check that.

I was writing under the assumption that this feature would be
incorporated into standard Java, in which case all other code would be
checked in the same way. If you really want to be completely safe, the
same properties should be checked at class-loading time by the JVM's
bytecode verifier as well.

-- David
P.Hill - 31 Jan 2006 06:46 GMT
> Bull: s is a pointer and there's no way to check at compile time
> whether it's pointing to valid data or to 0xdeadbeef.

The idea is that compiler can check the _caller_, given an
analysis of where the values in call are coming from and
all of the information about possible arguments and return
values.

>>If the implementation is designed correctly, the compiler can indeed
>>catch all attempts to pass a null parameter.
>
> Bullshit again: if the method is public, anyone can call it, including
> code that has not been written yet. Compiler will have to be prescient
> to check that.

Despite knowing what the turing machine is, you seem to have missed the
idea of where an annotation would be used by the compiler. The compiler
would check the USE by the caller of such a method when compiling the
_caller_ time, thus no prescience is needed.

The problem is not with some CompSci problem of completeness, but with
the more nagging problem of completeness of the declarations of
_every_ library both standard libraries and third party ones.

The compiler would either identify false problems or have to give up if
presented with the declaration:

@NotNull
public String myMethod(@NotNull String s, @Nullable Object o)

but then tries to analyze a caller.

otherMethod() {
  Object o = new ...;
  String s = some.package.without.null.annotations.getAString();
  my.mymethod(s, o); // call to check
}

There might be lots of warnings of the flavor:

Warning: Can not analyze value s for NotNull; unknown nullable
declaration of getAString()...

or
spurious errors

"Error: s can not be used in mymethod(...), s is assumed to be nullable."

That is unless there is "don't worry I believe I know the results of
that call can't be null" annotation.

@NotNull String s = ...;
my.method(s, o);

then after all of the annotations are combined, the compiler
won't complain.

But that seems like a lot of work.

-Paul
Dimitri Maziuk - 31 Jan 2006 17:33 GMT
P.Hill sez:
... if the method is public, anyone can call it, including
>> code that has not been written yet. Compiler will have to be prescient
>> to check that.

...The compiler
> would check the USE by the caller of such a method when compiling the
> _caller_ time, thus no prescience is needed.

And it still won't work unless you make sure *no* variable
can ever be set to null: via function return, declaration
without initialization, RMI, RPC, socket read, etc. Oh, and
database fetch: did I mention all database types will have
to be NOT NULL?

Dima
Signature

Yes, Java is so bulletproofed that to a C programmer it feels like being in a
straightjacket, but it's a really comfy and warm straightjacket, and the world
would be a safer place if everyone was straightjacketed most of the time.
                                                     -- Mark 'Kamikaze' Hughes

David  Wahler - 31 Jan 2006 19:01 GMT
> P.Hill sez:
> ... if the method is public, anyone can call it, including
[quoted text clipped - 8 lines]
> can ever be set to null: via function return, declaration
> without initialization, RMI, RPC, socket read, etc.

I'm not sure I'm following you. Only the variables that are declared as
non-nullable would need to be checked. It's not hard for the compiler
to ensure that a String variable never has an Integer value; why would
it be any harder for it to check that a null value is never stored into
a non-null variable?

> Oh, and
> database fetch: did I mention all database types will have
> to be NOT NULL?

If the database table may contain nulls, the result would obviously
need to be stored in a nullable variable. But there are many situations
in which a null reference should never happen, and in those cases it
makes sense to enforce this constraint statically.

-- David
Thomas Hawtin - 31 Jan 2006 19:41 GMT
David Wahler wrote:

> I'm not sure I'm following you. Only the variables that are declared as
> non-nullable would need to be checked. It's not hard for the compiler
> to ensure that a String variable never has an Integer value; why would
> it be any harder for it to check that a null value is never stored into
> a non-null variable?

It's actually a minefield.

Consider constructors. They can call (possibly virtual) methods before
they are constructed. You then have an object loose with null non-null
fields.

ArrayLists. You might never store nulls, and declare it as such, but the
backing array is going to be full of nulls. How do you decipher that?
You can still get nulls from it, if it's used in a non-thread safe manner.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Chris Uppal - 01 Feb 2006 09:25 GMT
> Consider constructors. They can call (possibly virtual) methods before
> they are constructed. You then have an object loose with null non-null
[quoted text clipped - 3 lines]
> backing array is going to be full of nulls. How do you decipher that?
> You can still get nulls from it, if it's used in a non-thread safe manner.

I think that these issues could be resolved, if not quite perfectly.  The basic
idea would be that the programmer could tell the compiler that <such-and-such>
was /intended/ not be non-null (which the compiler would just believe), or that
<such-and-such> was /required/ to be non-null (which the compiler would verify
by static analysis where possible and by a runtime check otherwise).  The
latter case would be directly analogous to casts in the current type system;
the former has no direct analogue.

The case of ArrayLists is interesting.  One option that the programmer would
have would be to tell the compiler that it could assume that no read of the
array would return a null.  The compiler (perhaps naively ;-) believing that,
would then allow the get(int) operation to declare that it never returned a
null.  Hence get() could be implemented without a run-time null-check (if
that's desired).  So far so good.  But, as you say, there are threading issues
too.  I don't think that it's /necessary/ for the type system to be able to
handle such cases; it would be nice if it could, but if it can't then that
doesn't mean that the feature is useless.

Similarly, the fields could be declared to be non-null, and that declaration
might be false if the programmer abuses constructors.  Not nice, but at least
/most/ accesses are subject to static confirmation.  And -- if we want the
extra safety -- we can use the stronger form of the assertion at the
point-of-use of the field.  (Compare the current situation with final
variables, which can -- despite appearances -- be seen in their uninitialised
state in some circumstances).

I'm not claiming that the change to the language would actually pay for itself,
but I don't think we can dismiss it as valueless even though the issues you
raise do dilute that value.

   -- chris
Dimitri Maziuk - 01 Feb 2006 00:51 GMT
David  Wahler sez:
>> P.Hill sez:
>> ... if the method is public, anyone can call it, including
[quoted text clipped - 11 lines]
> I'm not sure I'm following you. Only the variables that are declared as
> non-nullable would need to be checked.

Are you sure about that? -- you're compiling the *caller* and checking
that it does not pass a null to
public foo( @NotNull x )
declared elsewhere.

...
> If the database table may contain nulls, the result would obviously
> need to be stored in a nullable variable. But there are many situations
> in which a null reference should never happen, and in those cases it
> makes sense to enforce this constraint statically

Really? I happen to know that column i in my table is declared NOT NULL,
so null reference from ResultSet.getX( i ) "should never happen". Would
that be one of "those cases" where I declare
public foo( @NotNull x )
for use with
foo( ResultSet.getX( i ) )
so as to "enforce this constraint statically"? Or is this the case
where x "obviously needs to be a nullable variable"?

Dima
Signature

... with the exception of January and February 1900, all Microsoft application
libraries counted dates the same way.  
                           -- An Interview with Joel Spolsky of JoelonSoftware

P.Hill - 01 Feb 2006 03:31 GMT
> And it still won't work unless you make sure *no* variable
> can ever be set to null: via function return, declaration
> without initialization, RMI, RPC, socket read, etc. Oh, and
> database fetch: did I mention all database types will have
> to be NOT NULL?

It won't work unless every way in and out, many of which you
have mentioned (but many of them reduce down to whether a
return value can be null), has been declared to either possibly
be null or never be null, so that the much simpler analysis
might be done.  The proposal was to make those declarations
and box the problem in.

Each of your above examples would have to declare their return values
as nullable in their respective library implementations, if your
statement is shown to be correct, but for example, all InputStream.read
methods return something.

I believe that any such method of marking arguments and return values
would then lead to the requirement to provide a way for someone to say
"you can't tell from the code, but this API is guaranteed to never
return null."  A possibly dubious feature.

I maintain that getting all APIs to declare which possibility
exists for their return values is an impossible maintenance
hurdle, regardless whether the analysis could be done when
presented with sufficient information.

It *might* be a feature for a new language, but it is an
insurmountable impossibility for an existing language even
if it is shown to be possible and useful.

-Paul
Lasse Reichstein Nielsen - 30 Jan 2006 18:54 GMT
>> means the method should not return null, s should not be null and o can
>> be null. The compiler could check on this.

> Like this?

> TouringMachine tm = new TouringMachine(program);
> String s = null;

> if (tm.halts()){
>   s = "Halts";
> }
> myMethod(s, null);

> The best you will be able to get is capturing the obvious case of
> calling myMethod with a direct null, but a null resulting in another
> operation will not always be detected by the compiler, take my word for
> it.

While the compiler cannot check that the dynamic behavior of the
program, it can check whether your annotations are consistent with
your use.

In the above example, if "s" had been declared @Nullable, then the
static check would fail, as "s" would not be a valid first argument of
myMethod (it's declared to might be null). If it had been declared
@NotNull, then the initial assignment would fail. A missing annotation
should be interpreted as @Nullable.

I too wouldn't mind a type system that allowed nullable variables
of any type as well as non-nullable ones. You could use "?" to
represent it:

int? foo;
foo = 42;
foo = ?int;

Object? bar;
bar = new Object();
bar = ?Object;  

Object?? baz;
baz = bar;

switch(baz) {
  case Object o: // use o
  case ?Object: // this branch taken by baz above
  case ??Object: // ...
}

Alas, I guess it's too late for revolutionizing the Java type system
like this. Gotta make my own language (hmm, is "Lava" taken :)

/L
Signature

Lasse Reichstein Nielsen  -  lrn@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
 'Faith without judgement merely degrades the spirit divine.'

Chris Uppal - 30 Jan 2006 19:24 GMT
> I too wouldn't mind a type system that allowed nullable variables
> of any type as well as non-nullable ones. You could use "?" to
> represent it:
>[...]
> Alas, I guess it's too late for revolutionizing the Java type system
> like this. Gotta make my own language (hmm, is "Lava" taken :)

Too late ;-)

You may find Nice interesting:

   http://nice.sourceforge.net/safety.html

   -- chris
Roedy Green - 30 Jan 2006 10:02 GMT
>What about attaching a "&" character next to the variable to
>indicate that it cannot be null. (Just kidding :-)

I ran into so many problems with programmers not documenting whether
null and empty were possibilities for various variables, I came up
with this scheme.

see http://mindprod.com/jgloss/void.html
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Ed - 30 Jan 2006 10:10 GMT
Jacob skrev:

> A well designed API normaly doesn't accept null as parameter
> values, so as a programmer you are forced to test most inputs
> against null and throw an IllegalArgumentException in case it
> is null. All these cases must be properly documented in the
> javadoc section with an appropriate @throws tag.

This sounds like overkill.

Why not just use the object and if someone has sent you a null, then
you'll throw NullPointerException? Both would have the same effect:
telling the client that he's made a catastrophic error and you're just
not going to play with him anymore.

Admittedly, IllegalArgumentException gives more information, but I
think the costs (object-testing and documentation) outweigh the
benefits.

.ed

--
www.EdmundKirwan.com - Home of The Fractal Class Composition.
Roedy Green - 30 Jan 2006 12:58 GMT
>Why not just use the object and if someone has sent you a null, then
>you'll throw NullPointerException? Both would have the same effect:
>telling the client that he's made a catastrophic error and you're just
>not going to play with him anymore.

the point is a formal declaration on parameters to AVOID having the
error the first place.  People are so sloppy about documenting whether
a method can accept null or empty, or whether it will produce null or
empty. That gives you a way to quickly document it, AND enforce it,
much like assertions.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Andrew McDonagh - 30 Jan 2006 19:18 GMT
>>Why not just use the object and if someone has sent you a null, then
>>you'll throw NullPointerException? Both would have the same effect:
[quoted text clipped - 6 lines]
> empty. That gives you a way to quickly document it, AND enforce it,
> much like assertions.

trouble is, they would only stop the nulls that the compiler could
detect, not those that can happen at runtime...

So why bother with a halfway house, when there's other routes available:

Throwing Exceptions (nullPointer or otherwise)
Assertions
Wrapping null parameters (an example is JTable in its constructor)
Using NullObject Pattern
etc...


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.