A risk which, happily, does not exist concerning your advice that every
method null-check its parameters.
Correct, because I am advising good engineering practices.
And I didn't say that "every method [should] null-check its
parameters". I said that every method should (responsibly) handle
every possible input to it. Please do not use straw-man tactics.
This all hinges on what you mean by 'can'. Consider this program:
public class LewIsWrong {
Cute.
public static void printLength(String str) {
System.out.println(str.length()) ;
}
public static void main(String[] args) {
printLength("Hello, world!") ;
}
}
Would you say that an exception can occur in the body of printLine [sic]? Would
you say that printLine can receive a null as input?
That depends. If the class is exposed to other uses, then some future
client code very well could pass a null to printLength(). Just
because your main() didn't doesn't mean some other caller couldn't,
true?
To prevent that, you could have made printLength() private. Otherwise
you have *no* idea whether printLength() will ever receive a null
input. Therefore you must plan for the worst case - that it will.
If so, then this program does not meet your requirements, since it does
nothing about handling a null in printLength. And yet, it does not crash.
It does not crash if *and only if* called from the main() you show.
You do not show how someone else might call that method - their
program might crash.
In this scenario, printLength() must guard against null inputs,
perhaps by throwing an exception. To help future users of the class,
you should consider testing for and logging the error, or at least
creating a meaningful error message. At the very least, you should
document in the Javadocs that that method can throw an NPE. That
would be minimal handling of the null case.
If not, then actually, we're in agreement.
I do not know if we are in agreement until I see the Javadocs for the
printLength() method. If you document that it might throw an NPE,
then I agree that it's handled it.
This is a trivial example, and a matter of semantics, but it is not a
frivolous point. There can be as many places as you like in your program
where an exception, crash, etc could occur in certain circumstances, but
as long that those circumstances never arise, the program will not crash.
But you have not guaranteed that the circumstances cannot occur;
you've done nothing to prevent an NPE in the printLength() method.
In this case, assuming you document that the method can throw NPE, the
responsibility then falls on the client code to catch the exception
and log it.
One way of preventing crashes is to remove the places where crashes can
occur; another is to stop them being triggered. The former sounds better
in theory, because it should be more 'robust', but it doesn't work in
practice - every method, no matter how trivial, would need to check its
arguments, and there would be as much argument-checking code as functional
code. Certainly, there are times when armouring a method is a good idea -
This is correct, but you say it like it's a Bad Thing. Guarding
against incorrect input is one of the most powerful and fundamental
bug-stopping techniques there is. Quite frankly, I'm astounded that
you or anyone else would argue against it. No wonder so much
production code is so buggy.
when it's an entry point to a package, or when it does something
potentially dangerous. It's simply not good engineering to do it in every
single public method, though.
It's simply not good engineering to ignore bad inputs in any public
method.
I'm also curious about what you would suggest doing in printLength that
would prevent a crash when a null is passed in. Presumably, i [sic] test for
I don't suggest that. Why do you think I do?
What I do suggest is that the caller of the method make sure that it
not pass in a null.
null, or catch the NullPointerException - but what do i do then? Skip the
printing? Print 0? Print an error message? I'd say that the program is
then behaving incorrectly, which is worse than crashing. Should it throw
an unchecked exception? Then it merely crashes in a different way. Should
it throw a checked exception? What could the calling code do with that
that isn't ultimately also crashing?
You are arguing against points that I have not made and with which I
do not agree. Why would I defend points with which I do not agree?
I'm with you here. I do not endorse programs crashing. I wish to make this
clear.
If you don't want the program to crash, then you must intercept and
deal with any event that would otherwise cause a crash. Apparently we
are in agreement in the end.
"No" what? Is that supposed to be a point?
and tells you so in its Javadocs. Otherwise how would it be clear?
By telling you so in the javadocs.
It would be nice if java [sic] could express a requirement for non-nullity
in the type system. Some type systems forbid nulls from normal variables,
It can - by including a checked exception in the method signature.
No.
Again, what is that supposed to argue? That declaring a checked
exception does not provide a way to express such a requirement? But
it most surely does. If you have some other point, then you should
make it clear. Maybe add a subject, verb and object to your sentence?