Java most wanted: Non-null variables

Discussion in 'Java' started by Jacob, Jan 30, 2006.

  1. Jacob

    Jacob Guest

    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?
    Jacob, Jan 30, 2006
    #1
    1. Advertising

  2. Jacob

    Bart Cremers Guest

    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
    Bart Cremers, Jan 30, 2006
    #2
    1. Advertising

  3. Jacob

    Roedy Green Guest

    On Mon, 30 Jan 2006 09:25:44 +0100, Jacob <> wrote,
    quoted or indirectly quoted someone who said :

    >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
    --
    Canadian Mind Products, Roedy Green.
    http://mindprod.com Java custom programming, consulting and coaching.
    Roedy Green, Jan 30, 2006
    #3
  4. Jacob

    Roedy Green Guest

    On 30 Jan 2006 01:01:59 -0800, "Bart Cremers" <>
    wrote, quoted or indirectly quoted someone who said :

    >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.
    --
    Canadian Mind Products, Roedy Green.
    http://mindprod.com Java custom programming, consulting and coaching.
    Roedy Green, Jan 30, 2006
    #4
  5. Jacob

    Ed Guest

    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.
    Ed, Jan 30, 2006
    #5
  6. Roedy Green wrote:
    > On 30 Jan 2006 01:01:59 -0800, "Bart Cremers" <>
    > wrote, quoted or indirectly quoted someone who said :
    >
    > >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


    IIRC: There is an Eclipse plugin that does much the same thing.
    Stefan Schulz, Jan 30, 2006
    #6
  7. Bart Cremers wrote:
    > 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


    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).
    Stefan Schulz, Jan 30, 2006
    #7
  8. Jacob

    Bart Cremers Guest

    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
    Bart Cremers, Jan 30, 2006
    #8
  9. Jacob

    Roedy Green Guest

    On 30 Jan 2006 02:10:16 -0800, "Ed" <> wrote,
    quoted or indirectly quoted someone who said :

    >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.
    --
    Canadian Mind Products, Roedy Green.
    http://mindprod.com Java custom programming, consulting and coaching.
    Roedy Green, Jan 30, 2006
    #9
  10. Jacob

    David Wahler Guest

    Stefan Schulz wrote:
    > Bart Cremers wrote:
    > > @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

    >
    > Like this?
    >
    > TouringMachine tm = new TouringMachine(program);
    > String s = null;
    >
    > if (tm.halts()){
    > s = "Halts";
    > }
    >
    > 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
    David Wahler, Jan 30, 2006
    #10
  11. Roedy Green sez:
    > On 30 Jan 2006 01:01:59 -0800, "Bart Cremers" <>
    > wrote, quoted or indirectly quoted someone who said :
    >
    >>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.


    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
    --
    Backwards compatibility is either a pun or an oxymoron. -- PGN
    Dimitri Maziuk, Jan 30, 2006
    #11
  12. David Wahler sez:
    > Stefan Schulz wrote:

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

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


    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
    --
    Backwards compatibility is either a pun or an oxymoron. -- PGN
    Dimitri Maziuk, Jan 30, 2006
    #12
  13. "Stefan Schulz" <> writes:

    > Bart Cremers wrote:


    >> 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
    --
    Lasse Reichstein Nielsen -
    DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
    'Faith without judgement merely degrades the spirit divine.'
    Lasse Reichstein Nielsen, Jan 30, 2006
    #13
  14. Roedy Green wrote:
    > On 30 Jan 2006 02:10:16 -0800, "Ed" <> wrote,
    > quoted or indirectly quoted someone who said :
    >
    >
    >>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.


    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...
    Andrew McDonagh, Jan 30, 2006
    #14
  15. Jacob

    Chris Uppal Guest

    Lasse Reichstein Nielsen wrote:
    > 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
    Chris Uppal, Jan 30, 2006
    #15
  16. Jacob

    David Wahler Guest

    Dimitri Maziuk wrote:
    > David Wahler sez:
    > > Stefan Schulz wrote:

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

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


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

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


    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
    David Wahler, Jan 30, 2006
    #16
  17. Jacob

    P.Hill Guest

    Dimitri Maziuk wrote:
    > 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
    P.Hill, Jan 31, 2006
    #17
  18. P.Hill sez:
    > Dimitri Maziuk wrote:

    .... 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
    --
    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
    Dimitri Maziuk, Jan 31, 2006
    #18
  19. Jacob

    David Wahler Guest

    Dimitri Maziuk wrote:
    > P.Hill sez:
    > > Dimitri Maziuk wrote:

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


    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
    David Wahler, Jan 31, 2006
    #19
  20. 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
    --
    Unemployed English Java programmer
    http://jroller.com/page/tackline/
    Thomas Hawtin, Jan 31, 2006
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Harvey
    Replies:
    0
    Views:
    654
    Harvey
    Jul 16, 2004
  2. Harvey
    Replies:
    1
    Views:
    810
    Daniel
    Jul 16, 2004
  3. H.MuthuKumaraRajan
    Replies:
    3
    Views:
    415
    H.MuthuKumaraRajan
    Feb 4, 2004
  4. Replies:
    5
    Views:
    26,426
    Mike Schilling
    Mar 29, 2006
  5. xkenneth
    Replies:
    8
    Views:
    327
    Bruno Desthuilliers
    Feb 6, 2008
Loading...

Share This Page