3 ms·
Not sure what you mean by null being "outside the type system"--it's just the bottom type, assignable to all references. I loved Java circa 2002-2005 and was d
by titzer 4y ago
Not sure what you mean by null being "outside the type system"--it's just the bottom type, assignable to all references.
I loved Java circa 2002-2005 and was deeply interested in JVMs. However I wanted to develop the JVM itself, and it turns out that Java is bad systems language. So I really want a systems language because VMs are the itch I have.
What's weird to me are the choices that Java has made in its evolution. In Java 5, the VM and library powers-that-be basically killed reified generics, forcing type erasure. That was a huge language design mistake precipitated by not wanting to upset the apple cart of libraries and the .class format. But in versions 6 and 7 they updated the class format anyway, to add stackmaps and invokedynamic! I never understood why such a key language feature didn't get the requisite VM support it needs to be done right, but completely marginal features did get VM support. Poor choices IMHO.
Java is just a big ball of semi-typed mud at this point. There are no layers and hardly any separation between what features are in the VM and what features are in the class libraries that are wormholes into the VM.
- BlackFly 4y agoI would say it explicitly isn't the bottom type since it doesn't satisfy the Liskov substitution principle for any actual type due to null pointer exceptions unless you unreasonably axiomatize null checks into every single property any type may have. Basically, you need to think of Java references as the tagged union of Void + the true type. But since nobody wants to discriminate and pattern match on every reference, most java code tries to either follow a convention of non-nullability + Optional, additional type annotations with static checks beside the compiler, or "trust me, I've done this a million times". Lack of reified generics used to bother me. Than I started passing parameterized interfaces next to instances of that type parameter to access polymorphic "static" methods of the type. This allows for up stack dependency injection into the body of the method where you would want the reified generic type without being forced to extend the parameters of the method for every use case: that is, you get a much more flexible design this way.
- titzer 4y ago> it doesn't satisfy the Liskov substitution principle I haven't seen that principle applied so stringently before. Under a strict interpretation it wouldn't be allowed to override methods with any implementation that didn't have observably equivalent behavior. > I started passing parameterized interfaces next to instances of that type parameter This is just manual reification, and it's only skin deep. You still can't do List<Foo>[] because Java's builtin array types can't be polymorphic or extended with fields to store classes representing the reification.
- ragnese 4y agoIt's outside of the type system for two-ish reasons. First, because of the point the sibling comment made: while you can assign the singleton value `null` to any reference type's binding (but not primitives, so it's not even the bottom value for all types), it's not actually a value of that type, bottom or not. E.g, I can assign `null` to a `String` binding, or pass it as a `String` parameter, but I can't actually get it to behave as a `String`, so any call to a `String` method results in a runtime error. That leads to the second reason I say it's "outside the type system": you can't explicitly write down the `null` type in the language. The reason you get a runtime error when we pretend like the `null` value is a `String` is because it's not a `String`- rather, the binding actually has the type `String | null`, but the compiler allows (forces us) to pretend that the binding is a `String`. Since we can't describe nullability in the written Java language (express it in the type system's language), but it does exist at runtime, I say it's outside the type system.