@Nullable/@Notnull please advise

Hello,

Do you think any getter annotated with @NotNull MUST guarantee not null
return? In practice if we follow this idea very few methods can be annotated
as @NotNull because at some point in instance lifecycle most of getters
might return null until properly initialized. Alternatively if we chose to
annotate @NotNull those methods which suppose to return not null when
dealing with fully initialized object we might get more value out of it but
I wonder if it could have some negative consequences as runtime behavior
does not match stated statically defined one

Annotating setter's parameter with @NotNUll seems to be fairly straight
forward - any setter which expect not null parameter could be so annotated.
I wonder if we should match runtime behavior of the setter by checking the
parameter for null

I am also a bit confused with @nullable. Could you give us few examples
where you feel explicit use of @Nullable is beneficial. I assume that it is
not a good idea to annotate every method which might return null as
@nullable or is it?

I would appreciate your comments

Thank you

Alex


6 comments
Comment actions Permalink

One observation

public boolean hasParent(@NotNull OrgUnit aParent) {
if (aParent == null) {
throw new IllegalArgumentException("Parameter aParent is required and
can not be null");
}

if (aParent == null) is highlighted as redundant. Would I really drop this
check? Probably not. What if user of my API does not use IDEA or this
annotations in his code? Can I afford not to check my preconditions and rely
entirely on static analysis?



"Alex Roytman" <nospam@hello.world> wrote in message
news:d9in1n$pbg$1@is.intellij.net...

Hello,

>

Do you think any getter annotated with @NotNull MUST guarantee not null
return? In practice if we follow this idea very few methods can be
annotated as @NotNull because at some point in instance lifecycle most of
getters might return null until properly initialized. Alternatively if we
chose to annotate @NotNull those methods which suppose to return not null
when dealing with fully initialized object we might get more value out of
it but I wonder if it could have some negative consequences as runtime
behavior does not match stated statically defined one

>

Annotating setter's parameter with @NotNUll seems to be fairly straight
forward - any setter which expect not null parameter could be so
annotated. I wonder if we should match runtime behavior of the setter by
checking the parameter for null

>

I am also a bit confused with @nullable. Could you give us few examples
where you feel explicit use of @Nullable is beneficial. I assume that it
is not a good idea to annotate every method which might return null as
@nullable or is it?

>

I would appreciate your comments

>

Thank you

>

Alex



0
Comment actions Permalink


Do you think any getter annotated with @NotNull MUST guarantee not null return?

Yup, that's what it's for (but a caveat below).

+
In practice if we follow this idea very few methods can be annotated as @NotNull because at some point in instance lifecycle most of getters might return null until properly initialized.+

As I understand it, the @NotNull annotation for instance method returns is intended to have an implicit "once the object has been initialized (i.e. it's constructor has returned)" clause. You really shouldn't be calling methods on an object until it is properly constructed, and IDEA has a variety of inspections to help prevent you from inadvertantly doing so. Yes, you can break this rule, but that's really the root cause of any issues you (inevitably) run up against, not the @NotNull semantics.
Check out the "this' reference escaped in object construction", "Overridable method call in constructor", and "Call to 'Thread.start()' during object construction" inspections, to help find your lifecycle issues.

+
Annotating setter's parameter with @NotNull seems to be fairly straight
forward - any setter which expect not null parameter could be so annotated.
I wonder if we should match runtime behavior of the setter by checking the
parameter for null+

Keith Lea has a plugin which will add such runtime checks based on @NotNull annotations. Don't know it's current status. As a meta-note, I fully expect that a lot of tools will become available which use these annotations, once they are standardized. Runtime instrumenters, log statement generators, static analyzers, test-case generators, etc., etc.

+
I am also a bit confused with @nullable. Could you give us few examples
where you feel explicit use of @Nullable is beneficial.
+

I would say that for any method which may return null, @Nullable is valuable. At very least, it's auto-checkable documentation of a very important piece of method semantics. That is a prize beyond rubies in my book. Beyond that, marking methods as @Nullable is valuable at their call points, to let you know when you absolutely must check for null before handling the object. Over 50 latent bugs have been in IG and IPP that way (once IDEA started annotating the OpenAPI), in spite of their already being extensive null checking scattered throughout the code.

+
I assume that it is
not a good idea to annotate every method which might return null as
@nullable or is it?+

In any project where I can use the IDEA annotations, I'm using @NotNull and @Nullable pretty much everywhere. I've not found any great problems with doing so, and saved a lot of hassle. This would be even easier if there were inspections which could infer @NotNull annotations, like there are with @Nullable, but I believe those have been backlogged by JetBrains till after Irida.

--Dave Griffith

0
Comment actions Permalink

Alex Roytman wrote:

One observation

public boolean hasParent(@NotNull OrgUnit aParent) {
if (aParent == null) {
throw new IllegalArgumentException("Parameter aParent is required and
can not be null");
}

if (aParent == null) is highlighted as redundant. Would I really drop this
check? Probably not. What if user of my API does not use IDEA or this
annotations in his code? Can I afford not to check my preconditions and rely
entirely on static analysis?


My to-be-released plugin, Nully, inserts checks exactly like yours, for
@NotNull parameters, by compile-time code generation. It looks like you
would benefit from my plug-in. I think it will be released by the end of
July.

0
Comment actions Permalink

Alex Roytman wrote:

Hello,

Do you think any getter annotated with @NotNull MUST guarantee not null
return? In practice if we follow this idea very few methods can be annotated
as @NotNull because at some point in instance lifecycle most of getters
might return null until properly initialized. Alternatively if we chose to
annotate @NotNull those methods which suppose to return not null when
dealing with fully initialized object we might get more value out of it but
I wonder if it could have some negative consequences as runtime behavior
does not match stated statically defined one


I think you should re-design your classes so fields are final and are
fully initialized by the time the constructor completes. I think many
people would agree that this is a better design, and it also allows for
such static analyses to be smarter.

Annotating setter's parameter with @NotNUll seems to be fairly straight
forward - any setter which expect not null parameter could be so annotated.
I wonder if we should match runtime behavior of the setter by checking the
parameter for null


See my response to your followup post. My plugin handles this.

I am also a bit confused with @nullable. Could you give us few examples
where you feel explicit use of @Nullable is beneficial. I assume that it is
not a good idea to annotate every method which might return null as
@nullable or is it?


I think the short answer is yes, it is a good idea. The long answer is,
it's important to annotate methods whose nullness is important. For
example, you may want to alert developers who call your method, that it
may seem like it will always return a nonnull value, but really it might
be null.

0
Comment actions Permalink

Dave, Keith,

I agree with all points you are making here but unfortunately in business
world Beans rule :) But seriously in many cases logical construction of an
object (especially some domain object) is not exactly the same as java
construction. I wish I could make all my members final and initialize them
in constructor ....
Let me give you an example. A persistent domain object model backed by JDO.
many members of those domain classess are supposed to be NOT NULL but at
commit time not while you stuff it with data. Once it is populated and
persisted all non nulls should and mostly will stay non nulls.
Also there is no way in the world to build a highly dependent, complex graph
of objects with one big constructor or factory method (even using parameter
object patterns etc). not to say that you want to follow bean patterns
because every framework in the world depend on it



"Dave Griffith" <dave.griffith@cnn.com> wrote in message
news:5981330.1119701183671.JavaMail.itn@is.intellij.net...
>

+Do you think any getter annotated with @NotNull MUST guarantee not null
return?+

>

Yup, that's what it's for (but a caveat below).

>

+
In practice if we follow this idea very few methods can be annotated as
@NotNull because at some point in instance lifecycle most of getters might
return null until properly initialized.+

>

As I understand it, the @NotNull annotation for instance method returns is
intended to have an implicit "once the object has been initialized (i.e.
it's constructor has returned)" clause. You really shouldn't be calling
methods on an object until it is properly constructed, and IDEA has a
variety of inspections to help prevent you from inadvertantly doing so.
Yes, you can break this rule, but that's really the root cause of any
issues you (inevitably) run up against, not the @NotNull semantics.
Check out the "this' reference escaped in object construction",
"Overridable method call in constructor", and "Call to 'Thread.start()'
during object construction" inspections, to help find your lifecycle
issues.

>

+
Annotating setter's parameter with @NotNull seems to be fairly straight
forward - any setter which expect not null parameter could be so
annotated.
I wonder if we should match runtime behavior of the setter by checking the
parameter for null+

>

Keith Lea has a plugin which will add such runtime checks based on
@NotNull annotations. Don't know it's current status. As a meta-note, I
fully expect that a lot of tools will become available which use these
annotations, once they are standardized. Runtime instrumenters, log
statement generators, static analyzers, test-case generators, etc., etc.

>

+
I am also a bit confused with @nullable. Could you give us few examples
where you feel explicit use of @Nullable is beneficial.
+

>

I would say that for any method which may return null, @Nullable is
valuable. At very least, it's auto-checkable documentation of a very
important piece of method semantics. That is a prize beyond rubies in my
book. Beyond that, marking methods as @Nullable is valuable at their call
points, to let you know when you absolutely must check for null before
handling the object. Over 50 latent bugs have been in IG and IPP that way
(once IDEA started annotating the OpenAPI), in spite of their already
being extensive null checking scattered throughout the code.

>

+
I assume that it is
not a good idea to annotate every method which might return null as
@nullable or is it?+

>

In any project where I can use the IDEA annotations, I'm using @NotNull
and @Nullable pretty much everywhere. I've not found any great problems
with doing so, and saved a lot of hassle. This would be even easier if
there were inspections which could infer @NotNull annotations, like there
are with @Nullable, but I believe those have been backlogged by JetBrains
till after Irida.

>

--Dave Griffith



0
Comment actions Permalink

In article <d9k09u$9hs$1@is.intellij.net>,
"Alex Roytman" <nospam@hello.world> wrote:

Dave, Keith,

I agree with all points you are making here but unfortunately in business
world Beans rule :) But seriously in many cases logical construction of an
object (especially some domain object) is not exactly the same as java
construction. I wish I could make all my members final and initialize them
in constructor ....


Then these methods can return null, and should not be annotated as
NotNullable.

Let me give you an example. A persistent domain object model backed by JDO.
many members of those domain classess are supposed to be NOT NULL but at
commit time not while you stuff it with data. Once it is populated and
persisted all non nulls should and mostly will stay non nulls.


During an important part of the object's life cycle, these fields can be
null, Thus, claiming otherwise would be false. Beans can have null
fields, no two ways about it, and thus should never, ever make the claim
otherwise. I am being strident, because I have seen exactly this kind
of code bite people hard - a developer believes that the persistent
object pk field can never be null, because that just is not true, then
they get an uncommitted object with no assigned pk value yet. This
often comes up during error recovery, or other times where an NPE is
inconvenient.

You can force a different behavior - have your bean getters throw an
IllegalArgumentException and shut the program down hard if they are
called before commit. Frankly, that seems worse than living with NPEs.

Also there is no way in the world to build a highly dependent, complex graph
of objects with one big constructor or factory method (even using parameter
object patterns etc). not to say that you want to follow bean patterns
because every framework in the world depend on it


If you are following bean patterns, then you should behave accordingly.
Beans start out with no initialization of fields, and thus code that is
getting beans must handle null field values. Thus, I often code my
persistence code in a very different way than object code I control.

Scott

--
Scott Ellsworth
scott@alodar.nospam.com
Java and database consulting for the life sciences

0

Please sign in to leave a comment.