This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Null is a subclass of AnyRef... isn't it?

5 replies
Andrew Forrest
Joined: 2008-12-20,
User offline. Last seen 42 years 45 weeks ago.

Hi all,

I'm seeing strange (to me) behaviour with type bounds and null.

def doStuff[T <: AnyRef]() {
var t: T = null // compile error here
println(t)
}

...doesn't compile (2.7.4)— “type mismatch; found : Null(null)
required: T”. Whereas, as I understand it, I'm saying that the array
must be an array of reference type, and any reference type value may
be null... The following DOES compile:

def doStuff[T >: Null]() {
val t: T = null
println(t)
}

Now that's actually 'better' code in that the type bound is more
explicit about what I require of the type, but I thought that the
first one should work.

What say you?

Is it a consequence of the fact that trait NotNull extends AnyRef too…?

--Andrew

DRMacIver
Joined: 2008-09-02,
User offline. Last seen 42 years 45 weeks ago.
Re: Null is a subclass of AnyRef... isn't it?

2009/6/15 Andrew Forrest :
> Hi all,
>
> I'm seeing strange (to me) behaviour with type bounds and null.
>
> def doStuff[T <: AnyRef]() {
>        var t: T = null // compile error here
>        println(t)
> }
>
> ...doesn't compile (2.7.4)— “type mismatch; found   : Null(null) required:
> T”. Whereas, as I understand it, I'm saying that the array must be an array
> of reference type, and any reference type value may be null... The following
> DOES compile:
>
> def doStuff[T >: Null]() {
>        val t: T = null
>        println(t)
> }
>
> Now that's actually 'better' code in that the type bound is more explicit
> about what I require of the type, but I thought that the first one should
> work.
>
> What say you?
>
> Is it a consequence of the fact that trait NotNull extends AnyRef too…?

Null is a subtype of AnyRef, but it doesn't follow that it's a subtype
of everything which is a subtype of AnyRef (example: String is a
subtype of AnyRef, but it doesn't follow from that that String is a
Subtype of Map).

NotNull is one reason for this, but a more fundamental one is that
Nothing <: AnyRef but Null is not a subtype of Nothing (Nothing is the
type which has no values - the only way a method can have return type
Nothing is to never return normally. If Null <: Nothing then null
would be a value of type Nothing, which is not permitted)

odersky
Joined: 2008-07-29,
User offline. Last seen 45 weeks 6 days ago.
Re: Null is a subclass of AnyRef... isn't it?

On Mon, Jun 15, 2009 at 12:59 PM, Andrew Forrest wrote:
> Hi all,
>
> I'm seeing strange (to me) behaviour with type bounds and null.
>
> def doStuff[T <: AnyRef]() {
>        var t: T = null // compile error here
>        println(t)
> }
>
> ...doesn't compile (2.7.4)— “type mismatch; found   : Null(null) required:
> T”. Whereas, as I understand it, I'm saying that the array must be an array
> of reference type, and any reference type value may be null... The following
> DOES compile:
>
> def doStuff[T >: Null]() {
>        val t: T = null
>        println(t)
> }
>
> Now that's actually 'better' code in that the type bound is more explicit
> about what I require of the type, but I thought that the first one should
> work.
>
> What say you?
>
Null is a subtype of any class or trait that inherits of AnyRef. But
it's not automatically a subtype of a type parameter that's bounded by
an AnyRef. So the behavior you are seeing is as expected.

Cheers

James Iry
Joined: 2008-08-19,
User offline. Last seen 1 year 23 weeks ago.
Re: Null is a subclass of AnyRef... isn't it?


On Mon, Jun 15, 2009 at 3:59 AM, Andrew Forrest <andrew [at] dysphoria [dot] net> wrote:
Hi all,

I'm seeing strange (to me) behaviour with type bounds and null.

def doStuff[T <: AnyRef]() {
       var t: T = null // compile error here
       println(t)
}


Null is not a subtype of Nothing.

Has anybody else noticed that Scala makes you speak in double negatives?

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: Null is a subclass of AnyRef... isn't it?
All other answers are correct, and you couldn't find more knowledgeable persons to do it. But since I found the answers a bit too indirect, I'll give you mine, which is imprecise (or, strictly speaking, incorrect :), but might be easier to understand on a practical level.   Nothing is a subtype of everything, and null is not a valid value o Nothing. So if you get AnyRef, you could assign null to it, but if you get Nothing, you can't.   By the way, you can pass "null" as value o "Any".     On Mon, Jun 15, 2009 at 7:59 AM, Andrew Forrest <andrew [at] dysphoria [dot] net> wrote:
Hi all,

I'm seeing strange (to me) behaviour with type bounds and null.

def doStuff[T <: AnyRef]() {
       var t: T = null // compile error here
       println(t)
}

...doesn't compile (2.7.4)— “type mismatch; found   : Null(null) required: T”. Whereas, as I understand it, I'm saying that the array must be an array of reference type, and any reference type value may be null... The following DOES compile:

def doStuff[T >: Null]() {
       val t: T = null
       println(t)
}

Now that's actually 'better' code in that the type bound is more explicit about what I require of the type, but I thought that the first one should work.

What say you?

Is it a consequence of the fact that trait NotNull extends AnyRef too…?


--Andrew



--
Daniel C. Sobral

Something I learned in academia: there are three kinds of academic reviews: review by name, review by reference and review by value.
Andrew Forrest
Joined: 2008-12-20,
User offline. Last seen 42 years 45 weeks ago.
Re: Null is a subclass of AnyRef... isn't it?
Cool, thanks everybody.

On 15 Jun 2009, at 15:58, Daniel Sobral wrote:
All other answers are correct, and you couldn't find more knowledgeable persons to do it. But since I found the answers a bit too indirect, I'll give you mine, which is imprecise (or, strictly speaking, incorrect :), but might be easier to understand on a practical level.   Nothing is a subtype of everything, and null is not a valid value o Nothing. So if you get AnyRef, you could assign null to it, but if you get Nothing, you can't.   By the way, you can pass "null" as value o "Any".     On Mon, Jun 15, 2009 at 7:59 AM, Andrew Forrest <andrew [at] dysphoria [dot] net> wrote:
Hi all,

I'm seeing strange (to me) behaviour with type bounds and null.

def doStuff[T <: AnyRef]() {
       var t: T = null // compile error here
       println(t)
}

...doesn't compile (2.7.4)— “type mismatch; found   : Null(null) required: T”. Whereas, as I understand it, I'm saying that the array must be an array of reference type, and any reference type value may be null... The following DOES compile:

def doStuff[T >: Null]() {
       val t: T = null
       println(t)
}

Now that's actually 'better' code in that the type bound is more explicit about what I require of the type, but I thought that the first one should work.

What say you?

Is it a consequence of the fact that trait NotNull extends AnyRef too…?


--Andrew



--
Daniel C. Sobral

Something I learned in academia: there are three kinds of academic reviews: review by name, review by reference and review by value.

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland