I attempted to write a function that won't compile if null
is passed:
$scala
Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_101).
Type in expressions for evaluation. Or try :help.
scala> :t null
Null
scala> def f[A >: Null](x: A):A = x
f: [A >: Null](x: A)A
However, it did not work as I expected:
scala> f( null )
res1: Null = null
Null means having no value; in other words null is zero, like if you put so little sugar in your coffee that it's practically null. Null also means invalid, or having no binding force. From the Latin nullus, meaning "not any," poor, powerless null is not actually there at all. Or if it was, it's gone now.
A null value indicates a lack of a value, which is not the same thing as a value of zero. For example, consider the question "How many books does Adam own?" The answer may be "zero" (we know that he owns none) or "null" (we do not know how many he owns).
Null nie is the expression used when the information that has traveled through your ear is to hard to process and leaves you at a loss for words.
If a reference points to null , it simply means that there is no value associated with it. Technically speaking, the memory location assigned to the reference contains the value 0 (all bits at zero), or any other value that denotes null in the given environment.
As has been pointed out, A >: Null
allows for A
to be Null
itself, but that doesn't even matter here. Even if A
were required to be a strict supertype of Null
, it would still be possible to pass null
to f
as null
is a valid value of those types (which follows directly from the fact that Null
is a subtype of them).
If you don't want to accept nullable types, A
needs to be a subtype of AnyVal
. Note that this will prevent any values of reference types to be passed - not just null
itself.
There is no way to accept reference types without also accepting null.
Scala specification section 3.5.2 (conformance) states (emphasis mine):
The
<:
relation forms pre-order between types, i.e. it is transitive and reflexive. least upper bounds and greatest lower bounds of a set of types are understood to be relative to that order.
So if we look at the type constructor declaration from a mathematical point of view, we see the :<
relation as:
Null <: T <: Any
Since by definition the relation is reflexive, Null <: Null
is in the relation, which makes null a valid value to be passed into the method.
As @sepp2k rightly said in the comments and in his answer, the fact that A
isn't constrained by an upper bound means that Any
is a valid candidate, which means a null value could be passed anyway.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With