It doesn't always make sense to allow extending -- String is `final` for a reason (and one might even argue that final should be the default, and one should explicitly mark with `open` classes that can be subclassed).
The stereotypical FP example for sum types are a List -- there you only have an Element<T>(T head, List<T> tail) and a Nil(). There is no point extending it, it would, in fact, result in incorrect code in conjunction with all the functions that operate on Lists.
Also, the Visitor pattern, which is analogous to pattern matching is very verbose and depends on a hack with the usual method dispatch semantics of Java. I do think that pattern matching is several times more readable here.
In a world of untrusted code and SecurityManagers, it was critical that strings be immutable so a data race couldn’t bypass a policy decision. The JVM doesn’t have immutable arrays, so string methods carefully protected the embedded array from tampering, and couldn’t be overridden.
Most classes don’t have this problem. The original authors of a class don’t know what I’m trying to do, and they don’t bear consequences if I (a consenting adult) get it wrong.
The stereotypical FP example for sum types are a List -- there you only have an Element<T>(T head, List<T> tail) and a Nil(). There is no point extending it, it would, in fact, result in incorrect code in conjunction with all the functions that operate on Lists.
Also, the Visitor pattern, which is analogous to pattern matching is very verbose and depends on a hack with the usual method dispatch semantics of Java. I do think that pattern matching is several times more readable here.