1. having nullable references by default strikes me as a bigger issue
2. I don't see any reason I'd want to subclass String, actually (though I could see wanting to create an alternate implementation e.g. ropes-based). So String being a final class makes perfect sense as far as I'm concerned (unless it were an interface or some sort of "proxy" class as is often done in Cocoa). On the other hand, I'd give a phalange to easily create an unrelated type (typesystem-wise) with the same implementation. What `newtype` provides in Haskell.
I must agree with the nullable one. Let's say the biggest failure that I haven't heard anyone else talk about.
As per your #2, that's what I was hinting at except that the implementation effort of final vs. non-final is negligible, thus making it harder to excuse as far as I'm concerned.
how would a nominally different string type be better than wrapping the string ?
I mean I understand why having a Name, ZipCode or UUID stringish class helps ensure program correctness, I do not understand (out of ignorance) how it would improve your code vs a wrapper.
> how would a nominally different string type be better than wrapping the string ?
* It is significantly less verbose, therefore simpler and more likely to be used at all. And less error-prone
* It can provide string APIs working on itself (either by default or through the aliasing declaration) precluding the need to manually re-implement things like comparisons or printing
As far as I'm concerned Java's biggest failure, orders of magnitude worse than all others, is to make java.lang.String a final class.