28 ms·
The Java type system is broken
- bunnymancer 8y agoOh good, another opinion about how this one thing in this one language is the worst thing ever, and also works just fine. Find something that bothers you, complain publicly, do absolutely nothing after that, repeat.
- Froyoh 8y agoNot broken. Working as intended.
- lmm 8y agoNonsense. There are four bug reports at the bottom of the article; all seem to have been accepted as bugs and one has already been fixed.
- viach 8y agoFrom the examples: "String s = gridWrapper.get(0).get(0).get(0);" - Java type system is broken! Java is not perfect, but this looks to me like a broken code indeed ".get(0).get(0).get(0)". Could we rephrase the message of the article as "If you write really broken code in Java, you might be not guarded by the type system". And this is, well, uhm, well... acceptable?
- rimunroe 8y agoIs a type system really worth that much if it can't help you in a situation where your code is ugly and hard to follow?
- freddie_mercury 8y ago"Is X really worth it if it isn't perfect and doesn't cover every edge case?" I kinda feel like humanity has repeatedly decided the answer to this question is "yes". "Being valuable" isn't binary. There are relative amounts of value, I think.
- carlmr 8y agoBeing valuable isn't binary, but you shouldn't stop in the middle if it's possible to do better easily.
- kjeetgill 8y agoI think that's always the conflict in these discussions. We can usually agree on how things work but your "broken and unsounds" is simply a "limitation" to others. Saying things like "do better easily" makes sense in the context of fixing something that's broken. But for anyone who just sees it just as a limitation this comes off as presumptuous. What do you want to change? How do you want to overcome the limitation? At what cost?
- sorokod 8y agoType system helps those who help themselves.
- stickfigure 8y agoUnequivocally, yes. Several new languages (eg Typescript, Dart) have optional type systems that still bring significant value to the table. Sure - all other things being equal, I'd much rather have a type system that is completely sound. Ceylon's type system is beautiful and I'm happy to see its union + intersection types being adopted by Typescript. But honestly, I'm not going to lose much sleep over these particular issues in Java. Bad code gets refactored. A bigger complaint should be made that generic type erasure makes libraries hard (eg, the number of places you have to pass around Class<?> or TypeReference objects to let the runtime know what to do). But that was a clearly a compromise decision and everyone knows about it.
- igouy 8y ago> … Dart… have optional type systems… fyi "Dart’s type system is now sound" and "…types are mandatory". https://www.dartlang.org/guides/language/sound-dart https://www.dartlang.org/guides/language/sound-dart
- stickfigure 8y agoWow great news! That makes Flutter even more exciting.
- lmm 8y ago> Several new languages (eg Typescript, Dart) have optional type systems that still bring significant value to the table. I think it's too early to say that this approach has proven to be successful - indeed another reply says that Dart has switched to a stronger type system with required types, which I'd take as significant evidence that optional typing is not a good tradeoff. Certainly my experience of the checkers framework in Java was that optional types are the worst of both worlds. > But honestly, I'm not going to lose much sleep over these particular issues in Java. Bad code gets refactored. I'm worried (or rather, I would be worried if I hadn't seen the bug reports, which seem to be being taken seriously and fixed in the compiler). If they can happen in bad code, who's to say they can't happen in good code. > A bigger complaint should be made that generic type erasure makes libraries hard (eg, the number of places you have to pass around Class<?> or TypeReference objects to let the runtime know what to do). But that was a clearly a compromise decision and everyone knows about it. I'd argue that the only cases where you need that are when you're doing something you shouldn't (reflection). But I guess in a language without typeclasses there are problems that have no good solution.
- agumonkey 8y agoIt's stupid code, but a type system has to be code agnostic. Otherwise you're back to dynamic languages with local type annotations.
- Anderkent 8y ago> And this is, well, uhm, well... acceptable? It is not. The only purpose of a type system is to prevent broken code from compiling. When it fails to do so, it is broken.
- dtech 8y agoTypescript with its explicitly unsound type system show that a "broken" type system is immensely valuable, especially when you get something in return for that [1] [1]: https://www.typescriptlang.org/docs/handbook/type-compatibility.html https://www.typescriptlang.org/docs/handbook/type-compatibil...
- Anderkent 8y agoWell, sure, it's better than having an even worse type system! No one's saying java's type system is worse than not having anything.
- bdhess 8y agoThe author is trying to write a concise example. You could achieve the same effect by writing three for loops, but that would take additional code and declarations that make his point less clear.
- opnitro 8y agoIs it? The whole point of a type system is that it gives you guarantees over your code. Certain bugs should be inexpressible within the language.
- emodendroket 8y agoWell, think of it this way. A seat belt cannot help you at all if an object flies through your windshield. Nevertheless, driving while wearing a seat belt is, overall, safer than driving without one.
- opnitro 8y agoSure, and there's a point to all kinds of semi-strong typing. I'm glad Python does time checking at runtime, even it can't protect me from everything. When the type system becomes part of the grammar, it should be stronger than that though.
- picsao 8y agoRedefining the outlier. The outlier is a person catapulted out of its car during a accident. This is rarely a good thing, but sometimes a very lucky event. As only the lucky ones get to tell the tale in a bar, the world is full od outliers.
- ilikehurdles 8y agoThis is HN, we don't need seat belt analogies. Very strict type systems forbid this class of errors during compilation, others do a best effort and fail at runtime.
- emodendroket 8y agoWhoever you are, analogies can help clarify your thinking. A type system that prevents some errors is not without value just because it cannot catch others. If the uncaught types of errors are rare and the type system that would solve them somehow burdensome it may even be a reasonable compromise to accept these faults.
- macspoofing 8y agoIf you don't like this example, you can always find cases where the limitations of the type system (or more specifically Generics) become apparent. This isn't quite so obvious during 'normal' application development, but if you start creating libraries or frameworks and you want generic type support, you will run into a wall very quickly.
- byte1918 8y agoIf he were to show real world example, few would bother to follow it through because it would be tens of lines of code spanning through multiple classes and namespaces.
- Doxterpepper 8y agoWhat's the point of strong typing if it only saves you most of the time?
- dtech 8y agoSo a type-system that does the right thing in 99.999999% of the cases is completely useless according to you?
- Retra 8y agoDon't throw out a number like that. We're talking about a Turing complete language, which means we're talking about protections that have to range over all possible programs and abstractions. It may be that your problem domain is extremely biased toward some small region of that space, in which case a type system that doesn't work there is actually useless. Either way, it is hard to reason about factors like that numerically when we've not qualified which kinds of programs we're expecting the type system to actually work for.
- tom_ 8y agoI think the question is rhetorical.
- HelloNurse 8y agoNot really, a language in which some type errors are impossible (rather than merely very unlikely) makes it drastically easier to prove something useful about programs (e.g. to optimize away runtime checks that would otherwise be needed as a safety net and impossible cases).
- coldtea 8y ago>Could we rephrase the message of the article as "If you write really broken code in Java, you might be not guarded by the type system" The very idea of the type system is that it makes "broken code" of a certain type a compile error.
- cmiles74 8y agoFor certain and specific definitions of "broken code".
- coldtea 8y agoYeah, for the type of broken code that has the wrong types.
- cmiles74 8y agoIn some situations. The examples in this article, I think, make it clear that for a lot of "broken code" these errors are caught. It's too bad that there are edge cases, but that is Java all over, in my opinion.
- PDoyle 8y agoRight. I think this is the promise of Java generics: we promise we'll warn you if you're relying on dynamic type checking because we can't prove all dynamic type checks will pass. This article gives a series of examples that break that promise.
- Someone 8y agoIn Java f.get(0).get(0).get(0) typically is the way to write want in languages that allow operator overloading is written as: f[0][0][0] You will rarely see that with three constants, but f[x][y][z] isn’t uncommon.
- lmm 8y agoThe type system should give guarantees. I believe these cases violate the specification, and I think the specification is right to require the typechecker to check all code rather than just most code: a type system that works 100% of the time is much more useful than a type system that works 99.99% of the time, because it means you can blindly rely on it rather than having to double-check it every time you do anything critical and then maintain all those double-checks. If we take the view that these are bugs in the Java compiler, then of course a bug that's rarely triggered is less bad than a bug that's triggered all the time. But both are bugs all the same.
- TazeTSchnitzel 8y agoMy favourite feature of Java's type system is that, because any object type also accepts null, the type system is unsound and you can convert anything to anything else: https://raw.githubusercontent.com/namin/unsound/master/doc/unsound-oopsla16.pdf https://raw.githubusercontent.com/namin/unsound/master/doc/u...
- stingraycharles 8y agoWouldn't that be a problem in most languages? Even Haskell allows for it through Data.Dynamic If I can serialize to String, and then deserialize a String to any type of class, I can effectively "cast" anything to anything.
- TazeTSchnitzel 8y agoBy “convert” here I mean convince the compiler that any thing of type A is any type B, when it definitely isn't, without using an explicit cast.
- lmm 8y agoThe point is not that you can do explicit casts, it's that because you can form a (fake) instance for impossible types you can do invalid type conversions without doing anything that looks unsafe. In Haskell you can certainly achieve the same thing with various common extensions ( http://okmij.org/ftp/Haskell/impredicativity-bites.html http://okmij.org/ftp/Haskell/impredicativity-bites.html ). Possibly not in vanilla Haskell '98, at the price of being not a very nice language to work in. (A total language like Idris should permit GADT-like functionality without allowing this kind of issue).
- J-Kuhn 8y agoRead about Bottom (⊥). null can be considered bottom (if it were not for primitives)
- tathougies 8y agoData.Dynamic is type safe. It performs a run-time type check. Haskell can be made to be unsound using 'unsafeCoerce', but as you'll note, there is a giant unsafe in front of it.
- wintorez 8y ago* The Java is broken
- npstr 8y agoJava generics are broken? What else is new?
- buremba 8y agoWelcome to the world of enterprise-ready complex applications. I agree that these cases should be covered by the compiler but man, there are mainstream languages that don't implement generics just because they're complex and pretend that they're not helpful. It would be nice of you to compare Java generics with equivalents instead of just criticizing it. It doesn't help anyone writing "this is broken" not offering any alternatives or suggesting ways to fix the problem.
- hyperpape 8y agoI think it would've been better to write "unsound" rather than broken, but it's pretty common to present little proofs/results like this without saying how the system should fix it. Doing so is helpful, because many times you'll know there's a problem without there being an obvious fix.
- pdpi 8y agoClearly you didn't reach the conclusion. First, because the conclusion is not "Java sucks", but rather "Most of these things, while not kosher, are unlikely to happen in practice." Second, because the author didn't just leave it at criticising the language — he opened a bunch of bugs in the OpenJDK tracker.
- bad_user 8y agoPeople criticizing constructive criticism are often not constructive.
- nurettin 8y agoC# is a similar language in it's goals and architecture. LINQ to Objects type system will throw an error if you try to return conditionally different types from a lambda expression, so it is doable.
- humanrebar 8y ago> It doesn't help anyone writing "this is broken" not offering any alternatives or suggesting ways to fix the problem. Clearly stating and detailing problems is absolutely helpful. We can't solve problems if we don't understand them.
- nik736 8y agoJava is broken ¯\_(ツ)_/¯
- hyperpape 8y agoHere's another fun trick, though it's probably not a flaw in the type system: https://twitter.com/joshbloch/status/1018987317489426432 https://twitter.com/joshbloch/status/1018987317489426432.
- BonesJustice 8y agoYeah, compound types like that are a bit of a hack. During type erasure, the type variable gets reduced to its leftmost type (in this case, `String`), so the `main` signature ends up being a valid entry point. Best the compiler can do to enforce the right-hand type constraints is to insert cast instructions where values are used as insances of those types. As the tweet shows, you still get (some) type safety from the runtime checks.
- dlubarov 8y agoAnother flaw we can abuse is Java's covariant array types: Object[] objects = new Integer[] {1, 2, 3}; objects[0] = "hello"; Also compiles but fails at runtime.
- bad_user 8y agoIt’s pretty tragic how people respond to such criticism emotionally, instead of acknowledging the issues and working towards fixing them or educating others in the traps and compromises involved. HN is less prone to toxicity, but this is reminiscent of Reddit and it drives away the people that want to help. As a piece of advice, some type theory never harmed anyone ;-)
- kjeetgill 8y agoI think it's just a knee jerk reaction to some academic/PL theory types that chime in with a "Huzza! Long live (Haskell/Scala/Ocaml/etc.)!" As if a lack of soundness is dawning on anyone and was anyone's issue to begin with. It's pretty dramatic so it gets met with preemptive defensiveness. From the end of article: Everything is broken. Everything is fine.
- jerf 8y agoIn theory, as soon as a type system is unsound, it is unsound. In practice, there are ranges of brokenness. If you have to go hunting for the problem, and it takes a combination of 5 obscure features which nobody would ever use together, it's not that big a deal. If it's the sort of thing that you encounter in any non-trivial program, well.... ... your language dies. Part of the reason so many people in this thread can be cavalier about type soundness issues is precisely that all the languages they use, being the languages that did not die because they have a crappy type system, are pretty sound, within the model the language is operating under, so, yeah, of course it doesn't look like a problem to a normal programmer, because it was solved a long time ago. Doesn't mean it's a bad idea, or that people should just sneer contemptuously at the issues and snidely dismiss them as academic frippery, because then these people go on to write new languages that have these sorts of issues. (Like the recent wave of "event based" programming environments that just threw away the benefits of structured programming, because they were so thoroughly immersed in a structured programming world they didn't even realize how thoroughly they'd internalized it, had no idea what the preconditions were for it, and not only had no idea they were throwing it away but snidely berated people who pointed it out. And then spent 5+ years rediscovering it all over again....)
- 8y ago
- MrBuddyCasino 8y ago> Everything is broken. Everything is fine. This is the correct conclusion. The people getting outraged over this are the same that will hold long and boring monologues about how everybody does REST wrong.
- bunnymancer 8y agoHad a client just last month that were doing SOAP wrong somehow... Required a SOAP message, that contained no XML after the message tag, but instead the entire message body was to be a JSON, and responded with a JSON if something was wrong, and a fully formed SOAP message if things were Ok. That and the guys that handle your money use the Http status code as their personal error messages. Except when the error is on their end, in which case they return 200 and a JSON with an error message. There are plenty of ways to do REST wrong, so let's not lump that into the people that make blog posts complaining about X because X is broken, and working just fine...
- MaxBarraclough 8y agoThe only thing stopping Tim Berners-Lee spinning in his grave, is that he's still alive.
- meddlepal 8y agoWell I hope the money was good at least. Yikes.
- deleted 8y ago[deleted]
- cs02rm0 8y agoHad a client just last month that were doing SOAP wrong somehow... To be fair, I'm not sure there's any other way.
- mey 8y agoThere are degrees, sort of like levels of hell. I think the universe implodes if you combine XML Encryption and SOAP SMTP binding. Actually that may explain things pretty well...
- yash1195 8y agoThere are problems with every language but if we don't talk about these problems, fanboyism increases.
- mcculley 8y agoThe mess that is the current Java type system makes me skeptical when proponents of languages like Go say not to worry, that generics can be added later. If Java had generics in the beginning, it would look a lot different and the type system would be more powerful and safe.
- cmiles74 8y agoI agree that generics should probably be a strong consideration right from the beginning. I disagree that this would mean that it would necessarily be done correctly or that it's impossible to add it later. That was the case with .Net and C#, it wasn't until the 2.0 release that generics were added. [0] [0]: http://mattwarren.org/2018/03/02/How-generics-were-added-to-.NET/ http://mattwarren.org/2018/03/02/How-generics-were-added-to-...
- monocasa 8y agoUnlike Java, Go doesn't have to worry about bytecode backwards compatibility. That was the main issue that had them reaching for type erasure. Take a look at C# which added it without many issues (because they were willing to break back compat of their bytecode). Go fits this model a whole lot better.
- enitihas 8y agoDid C# really break backwards compatibility of their bytecode? What I understand is that C# generic and non generic APIs are completely different, and are not inter operable.
- kjeetgill 8y agoYea from the wording I think they mean you can either break backwards compatibility or "fork the world". In Java's case, old bytecode using Map would correctly work with change to Map <K, V>. C# introduced a new set of collections I believe.
- mohaine 8y agoNot sure on the first part but the second part is true. When there is a C# class that both has and doesn't have type information, they are actually completely different classes that just happen to share a base name. This really made it painful when they first added generics. If you used generic containers but wanted to call into a library that predated it you hand to transform your data in/out of all the calls to the library. In Java land you didn't have to do anything other then a blind cast on the out side which doesn't even have a runtime penalty. Long term the C# way was probably better but then they didn't have nearly as robust of a library ecosystem when they added generics.
- picsao 8y agoThe boo boxed? The boobox.
- raj7749 8y agoI was trying to justify the type safety of list in java to one of my senior, i am glad that i was right, it is indeed broken
- whatyoucantsay 8y agoThis fact may be hacker but it is not news.
- kazinator 8y agoDisagree with bullshit term: heap pollution. Pollution is the proliferation of superfluous objects creating some sort of undesirable mixture. For instance "namespace pollution". An inconsistency between the run-time type of an object in the heap, and the type of the expression in the program which refers to that object, isn't a good fit for the word "pollution". Quit trying to pollute the computing lexicon with nonsense.
- kazinator 8y agoLooks like this is a thing in Java culture; good grief.
- exabrial 8y agoWebsite is struggling, here's a cache: http://archive.is/k2YbA http://archive.is/k2YbA
- olliej 8y agoIt missed my favorite: contravariant arrays (or is it covariant, I last did work on this more than a decade ago. Specifically you can do (forgive syntax it’s also been a long time since I wrote java) X = new String[10] Ovject[] o = X o[0] = 1; // this will auto box, and then fail at runtime Note that this isn’t a “bug” as it predates any version of generics so collection types especially are much saber if you support this. That said it does result in a logical error in which you can’t assign something that looks like it should be fine. .Net unfortunately picked up this design decision in order to support java on their vm.
- deleted 8y ago[deleted]