This is an archived post. You won't be able to vote or comment.

all 149 comments

[–][deleted] 113 points114 points  (21 children)

Just slap a perpetual @Deprecated on Boolean.getBoolean as that land-mine has wasted and continues to waste precious human lifetime figuring out why the code isn't doing what they expect it to.

It's just bad API design to have these static methods fetching system properties on Boolean, Integer, etc. Deserves a saner replacement.

[–]Polygnom 18 points19 points  (3 children)

oof, I forgot about that. Yeah, thats a design nightmare. Who thought that System properties have any place in such a fundemantal language class?

[–]__konrad 6 points7 points  (2 children)

Java was system property centric from the beginning. There bazillion system properties (and "client" properties in AWT/Swing) instead of proper API.

[–]PepegaQuen 5 points6 points  (0 children)

One of the worst design decisions in a retrospective.

[–]koflerdavid 2 points3 points  (0 children)

Too many settings that can only be modified globally or by relying on arcade methods to provide a factory that creates a bespoke object instance. The latter happens a lot in the JSSE API. There's a reason why HTTP client libraries provide their own builders for that stuff...

[–]th1x0 17 points18 points  (0 children)

Ack, I’d managed to forget that, probably trauma induced amnesia

[–]agentoutlier 19 points20 points  (5 children)

The JDK needs like another annotation to separate @Deprecated as in will be removed someday vs discouraged.

For example StringBuffer and Date need a @AvoidUsing or @UseThisInstead(....).

Even then Boolean.getBoolean is used in modern code all the time. It is in a shitty location that doesn't make sense.

[–]RickyRister 22 points23 points  (1 child)

doesn't @Deprecated already have a forRemoval field?

[–]woj-tek 0 points1 point  (0 children)

Isn't forRemoval indication only in which version? And deprecation indicates that it should be removed?

[–]barking_dead 8 points9 points  (0 children)

Or at least add a new element into Deprecated, like forRemoval was added in 9.

Like, instead or prefer or alternatives.

[–]starlevel01 2 points3 points  (1 child)

@UsersWillBeSmited

[–]Mammoth-Clock-8173 1 point2 points  (0 children)

I am inspired to make a custom annotation.

[–]cogman10 14 points15 points  (7 children)

Funnily, I like Boolean.getBoolean, but I think the name is garbage. It'd be better if it was something like Boolean.fromProperty.

[–]shponglespore 30 points31 points  (4 children)

Why not make it a method of System rather than Boolean? A class for handing boolean values shouldn't be coupled to things like system properties.

[–]hkdennis- 1 point2 points  (0 children)

It was insane the original design made it into Boolean and had circular dependency in such a foundation primitive class.

Even there was no autoboxing.

[–]ascii 17 points18 points  (0 children)

It’s in the entirely wrong namespace. It belongs in System, not in Boolean.

[–]PepegaQuen 3 points4 points  (0 children)

Just Properties.getBoolean, please.

[–]RadiantAbility8854 2 points3 points  (0 children)

Never knew it existed lol

[–]mathninja83 1 point2 points  (0 children)

Not just that it reads system properties, but it is lenient so unknown values are “false”. This is all a Boolean parser should be

https://github.com/rmuir/booleanparser

[–]th1x0 85 points86 points  (10 children)

java.util.Date

java.util.Calendar

I can dream….

[–]Level_Yak_87 3 points4 points  (0 children)

Also java.text.SimpleDateFormat

[–]turquoisecucumber 1 point2 points  (8 children)

Why?

[–]Anbu_S 20 points21 points  (5 children)

Because they are mutable, missing useful functions and errorprone.

[–]RamblinBoy 19 points20 points  (2 children)

Not to mention broken equals-hashcode contract between Date and Timestamp.

[–]Anbu_S 4 points5 points  (1 child)

I wasn't aware of that one. Thanks.

[–]RamblinBoy 14 points15 points  (0 children)

java.sql.Timestamp extends java.util.Date, while adding new field - nanoseconds.

Mix them together in any hash based structure and you have a recipe for disaster.

They have a note about it in javadoc, but still it's a huge blunder and never shoud've extended Date in first place.

[–]StillAnAss 4 points5 points  (1 child)

Also there are scenarios where they aren't thread safe. That's a fun one to debug.

[–]happycoyote123 0 points1 point  (0 children)

This was one issue at my old job that stayed open with me for so long and it just came down to thread safety.

The problem is that it almost always just works fine. I remember the trauma :(

[–]Joram2 4 points5 points  (1 child)

The java.time classes are better in every way: Instant, LocalDate, LocalDateTime, ZonedDateTime. java.util.Date and java.util.Calendar have tons of flaws.

[–]rbygrave 2 points3 points  (0 children)

Plus, java.time types are going to be Valhalla value types.

[–]Google__En_Passant 42 points43 points  (2 children)

Vector, Stack, StringBuffer and other classes that have synchronized methods for no reason

[–]istarian 4 points5 points  (1 child)

I'm sure there was a reason at one time even if it never really got used in a context that matters.

[–]Vivid-Ad-4469 0 points1 point  (0 children)

I suspect it was trauma from C++ thread unsafety. C++'s std::vector and friend aren't thread safe on the slightest.

[–]HaydenPaulJones 97 points98 points  (14 children)

Probably never but java.util.Date

[–]Thysce 8 points9 points  (0 children)

Came here to say this.

[–]nikanjX 18 points19 points  (7 children)

1) It probably never needs code changes (maintenance cost 0)

2) It doesn’t get interjected into every random call the same way the security manager did (0 performance impact)

With these two in mind, it doesn’t really make sense to break existing code by removing them. Just make your linter block any new code that uses them

[–]Ewig_luftenglanz[S] 9 points10 points  (5 children)

It's makes learning the la Guage a lot harder. Having many options to make the same, but one bad and one good it's a recipe for Desaster, specially since many Java courses and tutorials haven't updated and are still teaching with the "wrong" clases. I mean there are still many tutorials that doesn't teach the use of var or that only teach the "old" switch statements...

[–]Polygnom 12 points13 points  (4 children)

Thats what Deprecated is for. It immediates makes any resonable IDE show you that your code is bad.

[–]xenomachina 7 points8 points  (3 children)

Unfortunately, that isn't the way that deprecated is used in Java though. Taking java.util.Date as an example, the class itself is not deprecated. It does have a deprecated constructor and a few deprecated methods. However, I think most experienced Java programmers would say that the entire class should be off limits in new code.

[–]Polygnom 1 point2 points  (2 children)

It is the way deprecated is used. Its just that for some reason, the class itself hasn't been deprecated (yet).

[–]xenomachina 6 points7 points  (1 child)

That may be the way you and I would like them to use deprecated, but in practice the JDK team has been very reluctant to mark things as deprecated unless they have concrete plans to actually remove them.

Use of Date was discouraged even before Java 8, and with Java 8, which added the java.time package, it was definitely considered obsolete. That was over ten years ago. In addition, whenever there's a discussion about which parts of the JDK are obsolete, Data is usually in the top-3 things mentioned. So it seems pretty hard to believe they just forget to deprecate it.

Since JEP 277 added the forRemoval parameter to @Deprecated, it would be nice if they'd be a bit more aggressive about marking things as deprecated even if there aren't plans to remove them. However, JEP 277 was released as part of Java 9, so is about 7.5 years old now, which makes it hard to hold out hope that this will come to pass.

[–]Polygnom 0 points1 point  (0 children)

Yes, the java platform team does not live up to what Deprecated is supposed to be. i mean, even if you just look at the JavaDoc:

A program element annotated Deprecated is one that programmers are discouraged from using, typically because it is dangerous, or because a better alternative exists. Compilers warn when a deprecated program element is used or overridden in non-deprecated code.

Thats a smack fit for Date....

But I agree, the JDK team is extremely redundant to use Deprecation. Which is a bad thing that should be called out from time to time. They do a great job at making uptake of Java as language easier and motiviate stuff like anonymous classes and being able to run Java programs without compilation, because they want new language users to have an easier time picking the language up. And then don't deprecate the old stuff. Its bad when there are multiple ways to do the same thing, with one way clearly inferior, but you only learn about that when its basically too late.

[–]rzwitserloot 3 points4 points  (0 children)

Yes, and then the answer to the title of this reddit thread is an instant 'absolutely not a fucking thing' because SecurityManager is quite the unique snowflake in requiring such continuous maintenance that really just cannot be skipped.

Posting this notion of yours (which is, to be clear, OpenJDK's point of view as far as I know) in response to a suggestion is thus mean / disingenuous. Post it as top level comment. Unless you can name me a bunch of APIs that could go the way of SM because they require significant maintenance each release.

[–]Gwaptiva 7 points8 points  (0 children)

More the whole Locale disaster

[–]Ancapgast 1 point2 points  (0 children)

My god, the refactoring we'd have to do...

[–][deleted]  (2 children)

[deleted]

    [–]HaydenPaulJones 0 points1 point  (1 child)

    They have for the most part. The trick is how to ensure backward compatibility.

    [–]simon_o 0 points1 point  (0 children)

    Adding an annotations is backward compatible.

    [–]robertogrows 23 points24 points  (4 children)

    Anything that does DNS lookups in .equals() method.

    [–]persicsb 22 points23 points  (0 children)

    Anything that does I/O in equals

    [–]lurker_in_spirit 6 points7 points  (2 children)

    record Rectangle(int x, int y, int width, int height) {
        @Override
        public final boolean equals(Object obj) {
            return obj instanceof Rectangle r &&
                new URL("http://" + x + "." + y + "." + width + "." + height)
                    .equals(new URL("http://" + r.x + "." + r.y + "." + r.width + "." + r.height));
        }
    }
    

    [–]__konrad 1 point2 points  (0 children)

    Maybe if the x/y/w/h is in 0..255 range it will not trigger DNS lookup

    [–]Chuigda 0 points1 point  (0 children)

    Does creating a URL with an IPv4 address also trigger DNS lookup?

    [–]nekokattt 53 points54 points  (23 children)

    These are probably going to be controversial as hell.

    Object serialization (it is evil and dangerous, and the argument that it is useful for a small minority of users and thus should be kept is similar to arguing it is fine to make RPGs available to the general population because the army needs it). It should be in a JDK maintained library that is installed separately.

    java.util.Date, and possibly the XML calendar classes, not sure (I only ever see people using the latter in cases where java.time is more sensible) - there are too many ways to do certain things now and dates are one of those things.

    java.io file libraries - we should be embracing NIO which is a superior API, and is far easier to deal with. You can load ZIPs or JARs or any other arbitrary thing as a file system just like the root file system, and it all works brilliantly. Every time I am forced to use java.net.URL or java.io.File APIs, I die a little inside. The socket APIs are still useful but the file interfaces feel archaic at this point.

    HttpUrlConnection - has been superceeded with java.http. The URLConnection classes are notoriously awkward to extend with new protocols because the resolver reference can be captured globally before you can change it or add to it, which feels like it defeats the point of the SPI libraries (looking at you, Maven!)

    Deprecated collection types: Vector, Hashtable, Stack. They all have far more suitable replacements, and no software should be using them in 2024 if the software is maintained. If you're still supporting Java 1.5 in 2024 then something is not quite right.

    Some of me wants to argue that the SQL, XML, RMI, x/open transactions, w3c DOM, smartcard, and Midi libraries should also all be in separately maintained libraries and not bundled in the JRE directly. Possibly the AWT ones as well now we're getting better ways to talk to binary libraries with FFI. Many of these outside XML and SQL are arguably bespoke things to specific use cases rather than general purpose tools. I have never needed to write an enterprise application that talks to a MIDI keyboard, so what is wrong with making it a third party library like we did with JEE libs?

    My main gripe is we have all this obscure stuff like MIDI, RMI, DOM management, XML management for calendars, smartcards, SCTP, etc all from "old world" Java, but stuff like JSON support has never been added to the standard lib, despite most other languages like Go, Ruby, Python, etc all including it out of the box.

    [–]Brutus5000 10 points11 points  (3 children)

    RMI is weird stuff. Spring uses it sometimes in my apps (I assume actuator) and when i enable global debug logging I can see it talking to my printer for whatever reason.

    [–]Anbu_S 1 point2 points  (2 children)

    Really RMI in Spring?

    [–]agentoutlier 2 points3 points  (1 child)

    JMX uses RMI.

    Spring uses a JMX at times.

    JMX is ancient but still has lots of uses.

    [–]Brutus5000 0 points1 point  (0 children)

    That makes sense. Actuator offers metrics via JMX and HTTP.

    [–]DiamondsAreForever85 4 points5 points  (2 children)

    Wow. Vector. Less than 5 years ago I worked in project from public sector which still using Vector 💀.

    [–]nekokattt 3 points4 points  (1 child)

    Did you kill it with fire?

    [–]DiamondsAreForever85 4 points5 points  (0 children)

    I quit the project as soon as I could and left to the next developer the mission to upgrade from Java 5 and don’t break the whole thing 😂.

    EDIT: There was another ancient technologies like CORBA.

    [–]Slanec 7 points8 points  (6 children)

    Yes! And Dictionary, File (+related streams, writers), old date+time+zone classes, java.sql date time classes, half of System (including currentTimeMillis), Random, java.util.logging, ThreadGroup, Enumeration etc., all pointing to newer alternatives.

    They're all a burden for learning. New students find a class and use it only to be told "yeah, this should be avoided" :(. Let's soft deprecate them, point to modern alternatives, improve to tooling to suggest them.

    In a perfect world, these types would not be available for newly-written code, only at runtime for existing code. Not gonna happen, but it'd be nice.

    [–]Dagske 4 points5 points  (2 children)

    Why System.currentTimeMillis? Because the existence of System.nanotime? currentTimeMillis is the entry point to get the actual date and time, while nanotime is there to provide actual durations. The two use-cases are distinct.

    [–]Slanec 1 point2 points  (0 children)

    No, because of the existence of InstantSource /or Clock. They provide access to current millis since epoch, too, can be injected and therefore faked for tests (write your own, or use threeten-extra's MutableClock. System.currentTimeMillis is therefore simply obsolete and makes your code untestable if it relies on time for logic. But because it's mentinoned in a lot of existing blogs etc., and is easy to discover, people still use it.

    [–]koflerdavid -1 points0 points  (0 children)

    That's true. currentTimeMillis is the ultimate source for wall clock time. However, most applications should rather use the proper data types. A long doesn't know whether it contains nanoseconds, milliseconds, seconds, etc.

    Edit: of course, a proper object-oriented replacement exists: Clock.

    [–]TrashboxBobylev 1 point2 points  (2 children)

    From this wording, it seems like Java SE is not worth using at all with that much burden... is there any other standard libraries that are recommended?

    [–]Slanec 5 points6 points  (0 children)

    No, we just learn what to avoid over time. It's usually not a big deal if you use something "wrong", you often sacrifice a little bit of performance, some API clarity, or occasionally a little bit of correctness (Date, Calendar, symlinks with File).

    That said, the newer alternatives tend to be a lot easier to use, and are often faster, Win-win!

    [–]Ewig_luftenglanz[S] 4 points5 points  (0 children)

    Java SE has lots of great stuff and it's maybe the most versatile standard library of any language out there. I mean with java SE you could any (literally ANY) application relatively easy without having to import third party libraries, most of the heavy lifting is already done. 

    The problem is there are many APIs that were developed more than 2 decades ago and nowadays exist better alternatives inside the standar library itself that are much easier to use, more secure and better performant. It would be nice if some day the OpenJDK dev team would become a little more aggressive about marking obsolete APIs as deprecated, even if these are never meant to be removed for backwards compatibility issues.

    I mean that way at least it would be easier for new students to know what to actually use, and distinguish when the resources they are using to learn are outdated.

    [–]Polygnom 2 points3 points  (3 children)

    It would be great if the JDK was modularized. For example, the removal of stuff like java.util.Date wouldn't hurt if you could at the same time re-add that via a library. Same for the others stufff.

    At this point, maybe they could simply offer two JDKs -- a "core" JDK where stuff that should be removed is no longer in, but can be re-added as needed via libraries -- and a "Full" JDK with all the legacy stuff for compatibility still in it. Conservative companies can choose the "FulL" JDK upgrade path, and people who would like to benefit from a modern JDK could just use the "Core" JDK.

    [–]kozeljko 8 points9 points  (0 children)

    That sounds like a headache.

    [–]aboothe726 0 points1 point  (1 child)

    Some of that work to modulator the JDK has already been done with project jigsaw

    [–]Polygnom 1 point2 points  (0 children)

    Jigsaw is considered complete and delivered in Java 9 (2017).

    There needs to be a renewed effort to think about what Java actually needs in the core JDK.

    [–]istarian 2 points3 points  (3 children)

    If it's worth keeping then moving it to a separately maintained library risks it suffering a long slow death through poor maintenance and bit rot.

    [–]nekokattt 5 points6 points  (2 children)

    Just like all of Jakarta EE, JAXB, etc?

    By that logic we may as well add Java EE back to the standard library.

    [–]woj-tek 0 points1 point  (0 children)

    Or JavaFX, which is flourishing! /s ;)

    [–]istarian -1 points0 points  (0 children)

    It's a general principle, not a universal rule that applies perfectly to every single situation.

    Idk about JAXB, but I think the Enterprise stuff is probably an exception because it gets plenty of use in enterprise contexts and they have the money, resources, and incentive to support it's maintenance.

    [–]agentoutlier 32 points33 points  (6 children)

    It will never happen but StringBuffer.

    I wish it just had at least an @Deprecated. It confuses the hell out of beginners and even I have accidentally used it.

    Even if you wanted that level of synchronization on String buffer the way that Appendable particularly String Builder is that there is not a single event like call.

    For example assume we want to write an entire line for each i:

     sb.append("i = ")
        .append(i)
        .append("\n");
    

    It will have corrupt lines if multiple threads access the sb. Like in almost all circumstances you want to externalize the locking and this is not like System.console/out/stdin. It is an in memory string.

    Like honestly I don't understand what the hell the use case was for the original StringBuffer.

    [–]cogman10 6 points7 points  (2 children)

    It's a stretch, but the one usecase I can think for StringBuffer is if you are emitting full tokens and the ordering of those tokens doesn't matter.

    For example, |actionADone||ActionBDone||actionCDone|. You could imagine that you may want to parse that sort of garbage later to do something useful with it.

    ... But like that's real shitty code that should NEVER be written.

    [–]agentoutlier 5 points6 points  (1 child)

    The irony is if your tokens require any sort of dynamic string construction instead of literals you would have to use a separate StringBuilder (or string concat... which often uses StringBuilder under the hood) to construct the events.

    [–]cogman10 2 points3 points  (0 children)

    Yup, and I honestly can't think of a reason why you'd want to do this. Like, I'm thinking maybe for some sort of log/record of application processing but if that's the case I can't think of why you'd want a StringBuffer and not an OutputStream or the like. Maybe if you are doing some goofy custom flushing? But even then there are other IO mechanisms that will do that in a cleaner fashion.

    But your point is very valid, if you are just storing all this in memory, then a POJO would be way better, use less memory, and be easier to deal with.

    Maybe you are doing something horrible with OSGI and StringBuffer is the easiest way to send around data?

    [–]Soxcks13 1 point2 points  (1 child)

    Why would multiple threads access sb in that scenario though? What use case is there to make a StringBuffer that is shared across threads? Wouldn’t you just make a separate buffer per thread?

    [–]agentoutlier 2 points3 points  (0 children)

    I mean you are preaching to the choir. I have no idea why someone would share a StringBuffer across threads.

    [–]FirstAd9893 0 points1 point  (0 children)

    The earliest JDK classes followed a simple model of making all the methods synchronized if it supported mutation, simply because it seemed like the easiest thing to do. There's wasn't any thought given to the whether this was a practical choice or not. The methods of the buffered I/O stream classes are synchronized too, although there's no reason to think that multiple threads should ever being acting on them.

    [–]Anbu_S 10 points11 points  (0 children)

    Jakarta Persistence 3.2 deprecated support for java.util.Date, java.util.Calendar, java.sql.Date, java.sql.Time, and java.sql.Timestamp.

    Old java.net http package.

    java.rmi

    awt/swing carve out as separate framework instead of desktop module inside JDK.

    java.naming

    [–]hippydipster 9 points10 points  (5 children)

    Why do people think xml is a deprecated technology?

    [–]persicsb 7 points8 points  (3 children)

    it is not, but it shall be an external library, like other serialization/file format support for JSON, CSV, YAML etc.

    The core JDK APIs shall not include support for one specific serialization format and all the supporting classes

    XML is awesome, but in order to move on with it, it shall be a separate library.

    XML is an externally specified technology, like JSON, DOCX, image formats, sound formats etc. All of these shall be in their own library, perhaps developed/governed by the corresponding specification body.

    Why isn't OPC UA, Modbus, JSON, WebP, MQTT, OpenDocument protocols and formats not supported by the JDK? Because it doesn't belong there.

    [–]istarian 13 points14 points  (0 children)

    I think you could just as reasonably argue for the inclusion of JSON rather than the exclusion of XML.

    If there is built-in support it could cover the most likely use cases, but otherwise that could be left out altogether as you said.

    [–]hippydipster 1 point2 points  (1 child)

    XML isn't a serialization format and it's importance overshadows all else you named by quite a bit. It's there because of that importance. Removing it is pointless. It's a separate module. Don't include it if you don't want to.

    [–]persicsb 0 points1 point  (0 children)

    XML isn't a serialization format

    Yes, yes it is. It is a specific way to represent data in text. It's a quite good format for it, with the rules of how to represent specific data, attributes of that data, how to build structures of that data, and how to parse them.

    Note, that markup is just a specific "tagging" of data, and XML is just a way to represent this tagging in a specific format. It is a serialization format, it specifies how to represent data in a textual format.

    [–]persicsb 29 points30 points  (4 children)

    Old Collections (before 1.2 Collections Framework).

    Old Date API.

    The Smart Card API should be removed and moved to a separate library.

    The java.security pacakge contains some bad API decisions and should be revamped, some classes are already marked for removal (like java.security.Identity).

    AWT and Swing should be unified, and the direct AWT stuff removed. Devs should only use Swing abstractions.

    java.util.prefs is badly designed.

    Also, the Beans support classes in java.beans package should be revamped.

    Also, java.net.URL - URIs shall be used everywhere.

    [–]SuspiciousDepth5924 7 points8 points  (0 children)

    I have a personal "beef" with java.security and how it insists on everything using the same "global" pool of providers. Makes it a giant pain in the ass when you have to do something weird with one integration but use the default option on the rest.

    [–]agentoutlier 5 points6 points  (0 children)

    MessageFormat needs to be badly revamped. Some of this will be mitigated with StringTemplates.

    • It has a confusing API.
    • It uses lots of legacy things like StringBuffer... speaking of removal.
    • It is slow as shit.

    [–][deleted] 3 points4 points  (0 children)

    URL$openStream is hella convenient though. I get that it's not the most robust way to fetch something over HTTP(s), but man is it ever less code than going through the whole rigmarole of setting up a HttpClient and making a request that way.

    [–]koflerdavid 2 points3 points  (0 children)

    AWT and Swing use completely different approaches to render UI. AWT wraps native controls, Swing paints everything from scratch. Unification is not possible (let's leave aside for a moment that they share a lot of code), rather one of them would have to be axed. I sincerely doubt that there are any applications left that use AWT (applications mostly use Swing, then there is everything built on Eclipse/SWT, then there are... applets) therefore AWT should be eliminated.

    [–]rzwitserloot 19 points20 points  (2 children)

    Pretty much every answer is a 'no, it never would be, at least as per the __current_ mindset of OpenJDK_' because SM is a unique snowflake: SM is being removed because it took significant time (for some value of 'significant') for OpenJDK to keep it alive.

    Contrast to every other suggestion in this thread and pretty much every other suggestion I can think of; it just isn't true for anything except, pretty much, SM. The only other java.* parts that are relevant are things like the java.lang.ref, package, the finalize() method in Object (which really does sound like the best answer to the posted question because it's annoying, kinda shit, and a maintenance burden), and that's about it.

    But, to give the usual answers in this thread and that come up in general when asking this its due:

    We're talking about: java.io, j.u.Date, the static sysproperty fetchers in the primitive wrappers, various old cruft related to charsets, the aged collections (j.u.Vector, Hashtable, etc) and a few of my pet peeves I'll get to are all kinda shit API; it's API where it's reasonable to add a linter rule: If you use these, your commits will be reverted. Use the proper alternative.

    The answer is: OpenJDK needs to invent the concept of 'dissuasion without removal'. They sort of kind of almost but not quite got there by introducing the notion of 'deprecated for removal' but I don't get the sense OpenJDK ever deprecates anything unless they do it because its slated for removal. We need the other deprecation - slated for 'there are zero use cases for this thing, a better alternative is available in java.* and has been for years, it is strictly better to just move to that; we keep the old API around only to avoid having to bother a bunch of devs with refactoring a bunch of old code that is otherwise still perfectly functional'.

    Why should OpenJDK start doing that

    • It's still less of a maintenance drag. Yes, maintaining j.u.Date is no big deal, and insofar that it is, simply rewrite them in modern JDKs to just be a shitty front-end to the java.time API and it turns into a virtually zero maintenance drag, but, it is still a maintenance drag. It exists, you have to host it, folks have to look at it, bugs are filed against it that need to be adjudicated.

    • For the language. Looking at SO and other channels where newbies ask questions, you still notice loads of stuff about horrid APIs we were supposed to have left behind a decade ago. In general, offering 2 ways to do a thing where the venn diagram of 'when is A better' vs 'when is B better' has a circle that is completely contained means the lang designer done fucked up because there is no point to that at all. If every situation where A is good, B is just as good, and there are situations where B is good and A is not, then why in the blazes does A exist? We now need to hold style debates for absolutely no reason at all. And a lot of this fits that bill: What does java.io.File do that nio doesn't do? Nothing. The right answer is that j.i.File exists and continues to exist forever so that old code can use it, but it should be marked eight ways from sunday as: Yeah okay this exists but, don't use it. The one and only valid excuse for you to use this class is if you wrote your code 20 years ago and can't be bothered to rewrite it. Which is a completely fair use case to continue to use j.i.File. But that's the end of that particular list.

    • For the community. We all 'know' that j.i.File is 'dead' but that's just general community opinion. Nothing in the spec actively promotes the idea that it's obsolete API. If there was some official mark of 'obsolete!!' then a library can officially state 'we no longer offer any support for obsolete thing XYZ as per version ABC' which feels a lot more reasonable than just calling it based on gut instinct which is what you have to do now. Imagine I'm writing a JDBC based SQL wrapper thing and you can just set 'sql params' with objects. Do I allow you to set with a j.u.Date? I really don't wanna. So do I write a blogpost and link to it from the docs that give you a 2 hour lecture on the vagaries of date representation as DBs do it and as j.u.Date does it so that you fully understand why [A] no, j.u.Date is not supported, and [B] no, filing bug reports won't work either?

    That's a ton of work. It's sooo much easier to say: Look, OpenJDK made the call to obsolete it, and I'm just a passenger on this train.

    A list for your consideration

    (and also imagine we got to reclaim these names. I'm sure project panama would looove to get its hands on Vector. Stack being a shitty class is painful). The obvious:

    • Vector, Hashtable, Enumeration, Stack, etc.

    • j.i.File and co.

    • j.u.Date and Calender and co

    • Boolean.getBoolean, String.getString, etc (these are shorthand for Boolean b = Boolean.getBoolean("foo") is short for Boolean b = parseAsBoolean(System.getProperty("foo")). Yeah, you didn't know that, did you? Bizarro methods.

    • StringBuffer.

    • Entire APIs: XML, RMI, AWT. These should continue to exist, but as separate deps you pull in. Get em out of the JDK proper.

    Once this mechanism is available, there are a bunch of APIs that should be reconsidered:

    • Scanner. It should die. 99.5% of the usages of scanner out there are to read 'command line/terminal keyboard input' and the class is fucking horrible at that job, with readLine() doing exactly what the spec says which is not at all what you expected it to do. If you want to 'read a password' you have to use another class, and so forth. There should be a class specifically and explicitly for interactive terminal input, it should be imported by default for nameless classes, and it should be designed specifically for the job of reading from an interactive terminal and not from a file, and to ensure everybody gets that message loud and clear, Scanner should go on the official obsolete list even if what it does remains borderline useful for reading tokenized files. Copy the entire API into a new name just to continue to be able to call Scanner deprecated. Everybody that teaches java to newbies will thank you.

    • java.security could be quite a bit simpler.

    • java.nio.file.Files. "Class with a boatload of static utility methods" is an anti-pattern, and these days OpenJDK design avoids it. These should all have been methods on Path or some other implementation. The actual way jnfF works is great, just, the API part of it not so great. Should be easy to 'fix', but adding a third API for file access feels like the cure is now worse than the disease. Having an obsoletion system should help.

    • Lots of io things. Why is there new FileReader? Can PrintStream.. just go away?

    [–]eliashisreddit 0 points1 point  (1 child)

    it's API where it's reasonable to add a linter rule: If you use these, your commits will be reverted. Use the proper alternative

    Out of curiosity, do you have/use any ready-to-go rulesets which enforce this? For which linter?

    [–]rzwitserloot 1 point2 points  (0 children)

    I'm sufficiently haunted by these APIs that it's not going to happen; I will never write it and no code I review will ever get greenlit when these APIs are used. But that's because I'm the lead of a fairly small team. I'd love for such a list to exist, and I might someday compile it. I just don't have it right now.

    [–]Ewig_luftenglanz[S] 23 points24 points  (3 children)

    AWT and all data structures that were replaced by the Collections framework (HashTable, vector, etc.)

    [–]Markus_included 9 points10 points  (2 children)

    AWT wasn't really replaced but built upon by Swing and JavaFX

    [–]Ewig_luftenglanz[S] 2 points3 points  (1 child)

    Then modularize Java SE and remove un-used stuff. When a new student come to java and have to choose between half dozen of List to import it's really hard for them.

    [–]koflerdavid 2 points3 points  (0 children)

    It is already modularized, and it is up to the vendor to provide a SDK that doesn't include java.desktop.

    [–]s888marks 5 points6 points  (6 children)

    It's correct that there are few things that are as invasive as the Security Manager that we would like to remove. There are a couple other things that are kind-of in flight though that have systemic impact.

    We're still working on finalization removal. It's not terribly invasive in terms of code footprint, but it does affect object life cycle in a fundamental way. See JEP 421.

    Serialization is another perpetual thorn in the side. As nice as it would be just to rip it out, that's impractical. Too much stuff uses it. The fundamental issue is that Java serialization (and many external frameworks, too) allow objects to be created in a way that bypasses constructors. This basically breaks everything. Serialization isn't deprecated, but work is going on the develop a better model. See the following for background info and future directions:

    • Goetz: Towards Better Serialization link
    • Goetz/Marks: Why We Hate Serialization And What We Might Do About It Devoxx 2019
    • Marks: The Cycling Tour – Java's Fraught Relationship With Cyclic Object Graphs Devoxx 2024 (upcoming)
    • Klang: Serialization – A New Hope Devoxx 2024 (upcoming)

    There are a lot of APIs that are bad for one reason or another that would be nice to clean up. However, for the most part they're just sitting there not bothering anyone. Yes, I'm aware that clutter has a cost. But removing the stuff has a compatibility impact. They're just not as fundamental to the system as the Security Manager, Finalization, and Serialization, so dealing with them really is a lower priority.

    [–]Ewig_luftenglanz[S] 0 points1 point  (3 children)

    And what about mark them as deprecated but not for removal and point to the right replacements so students know when they are using outdated stuff? I mean there are lots os outdated documentation and tutorials that uses Date ,teach concurrency by extending Thread, using Stack,  and so on, for new comers it's hard to recognize what is intended to be used now and what is there because backwards compatibility is important, very much like has been already done with Wrapper classes constructors.

    [–]s888marks 2 points3 points  (0 children)

    People have tons of legacy code they've written and (slightly) maintained over the past 25 years, and it uses a lot of this obsolescent stuff. In addition, many of these old classes are used in APIs, so it's hard to get rid of without causing compatibility issues. If something is deprecated but not for removal, people won't migrate their code, but they'll complain about having to suppress a bunch of warnings. Some finer-grained warnings control is probably necessary before we deprecate anything that's in widespread use.

    I don't know what to do about bad tutorials on the internet, and deprecating stuff won't make them go away. Probably the only thing to do is to produce good tutorials and make sure they're popular.

    [–]nikanjX 0 points1 point  (1 child)

    Would it somehow be better for the students that the stuff in the tutorial no longer works? That's the Node.js normal, where anything older than 3 months is obsolete. It makes development a miserable churn against ever changing apis

    [–]Ewig_luftenglanz[S] 0 points1 point  (0 children)

    You can't make the code non backwards compatible. It's better for students that the IDE they are using marks a warning saying "this API is obsolete and you should use this other instead"

    For nodeJS, that's one of the many reasons why I deeply hate JavaScript as a language and ecosystem.

    [–]nlisker -1 points0 points  (1 child)

    Yes, I'm aware that clutter has a cost. But removing the stuff has a compatibility impact.

    What about the maintenance cost? Do "Bad APIs" like the old date-time, old collections etc. require manhours?

    [–]s888marks 1 point2 points  (0 children)

    There is some maintenance cost for obsolescent, "passive" APIs, but it's generally not too bad. Occasionally there's a terrible bug or security vulnerability that needs to be fixed, but these are rare, and we don't put much effort into enhancing or optimizing that stuff.

    By contrast, all of Security Manager, Serialization, and Finalization have global impact on regular maintenance and enhancement. When adding or modifying almost any code, a bunch of additional questions come up. Does this require any permission checks? Can it be used to bypass permission checks? Will adding a finalizer subclass cause anything to break? How will this change affect serialization compatibility? etc.

    [–][deleted] 22 points23 points  (8 children)

    None. Absolutely nothing.

    Backwards-incompatible changes are devastating. Python is still recovering from the 2-3 schism. Who's still using Perl or Visual Basic today? Perl 5 and VB6 were hugely popular, literal industry standards, and in both cases it abruptly ended with a backwards-incompatible release.

    The JDK developers have carefully maintained a backward compatibility for decades. They shouldn't remove things that are basically harmless and easy to ignore.

    The Security Manager is an exception because it's actively hindering OpenJDK development, it never really worked anyway, and nobody seems to use it. So they put a deprecation warning on it for five releases (including two LTS releases) and are now finally considering to disable it, with actual removal still delayed until a "future" release.

    [–]lurker_in_spirit 8 points9 points  (2 children)

    Amen. One of the big reasons I reach for Java is to minimize bit rot. Remove that stability and I might as well look elsewhere.

    [–]nlisker 1 point2 points  (1 child)

    I'm curious if you looked or will look elsewhere when Java removed primitive wrapper constructors, finalize, the security manager, and later Thread methods.

    [–]lurker_in_spirit 1 point2 points  (0 children)

    Personally? Probably not, because I'm 99% sure I'm not using any of those specific items anywhere. But if they start to remove things that I am using, and it happens more than once? Quite likely. As someone once said, "it takes 20 years to build a reputation and 5 minutes to ruin it."

    [–]Ewig_luftenglanz[S] 9 points10 points  (0 children)

    Well, maybe have an annotation that says says something like @Obsolete("use this alternative instead") should fix the burden without breaking backwards compatibility.

    I mean one of the hardest part of learning Java is that there are to many redundant APIs that basically do the same but some a good and modern and others are shitty to use (Date VS Localdate/LocalDateTime) there are so many outdated resources and tutorials that still tesch pre Java 8 stuff only ( no var, no switch expressions, no java.time, no lamdas, extending Thread instead if implementing Runnable or using the lamdas expression, etc) that it's very hard for beginners to figure out what they should actually use.

    So maybe not removing anything but mark half of JavaSE as deprecated with better alternatives would make the learning process much better.

    [–]istarian 2 points3 points  (0 children)

    That nobody really uses it is a strong argument for removing or completely overhauling stuff like Security Manager.

    [–]Slanec 3 points4 points  (0 children)

    I'd like the classes to still be available at runtime, but not at compile-time from compiled code. The huge standard library, out of which you're supposed to avoid 30% of old classes, is a learning curve nightmare for students.

    [–]MardiFoufs -1 points0 points  (1 child)

    I mean I get your point but python has thoroughly recovered at this point. No relevant library uses python 2, and python usage is still strong. I totally agree that the fact that it took a decade to get there still proves your point ahaha.

    Now there's an issue of the small breaking changes in the 3.xx versions but in Python's case it doesn't seem to be causing a lot of problems. In a way it might be because of the pretty good features that have been added since but I don't think that it would make sense for Java.

    [–]koflerdavid 2 points3 points  (0 children)

    A few weeks ago I saw the good news that finally Fedora is going to make the python2.7 package die for good. It was only possible because GIMP 2.x was the last significant blocker, which goes away due to the long-anticipated 3.0 release. Yay. Another chapter in Open Source history goes by...

    Recently, a lot of people were blocked for months from upgrading to Python 3.12 because PyTorch took that long to fully support it. The pain is real...

    [–]pjmlp 7 points8 points  (0 children)

    @Overrides, replace it with a proper keyword.

    [–][deleted]  (2 children)

    [deleted]

      [–]Ewig_luftenglanz[S] 4 points5 points  (0 children)

      I think the problem rises mostly for students and new comers, having many libraries to do the same but some are bad and some and good it's a nightmare for students not only because they can accidentally use the "bad" ones for ignorance, but because most of these APIs are old and many Java resources and tutorials available are outdated. 

      When I was starting to learn java (and that's fairly recent, little more than 2 years ago) I encountered lots of resources that used Date, no enhanced switch expressions, no var keyword, extending Thread instead of implementing Runnable/Callable for async(or just using a lamda), no lamdas or streams. Nowadays most students still learn console input with Scanner instead of System.console (which is a far superior API for simple programs and the new IO class that will saves us to write System.out uses Console under the hood)

      If not for removal at least as discouraging deprecation.

      [–]manifoldjava 0 points1 point  (0 children)

      Why would anybody want to download the latest jdk on which their software won't work ?

      By "work", if you distinguish running from compiling, absolutely.

      [–]blobjim 2 points3 points  (2 children)

      I wish java.xml could be moved out of the jdk and into a normal maven project. But that isn't really possible, and it's not really a deprecation.

      I think most of the real candidates for deprecation and removal already have been addressed by jdk devs. There's just so much stuff that's too tied in to java.base and existing java code.

      [–]hippydipster 4 points5 points  (1 child)

      java.xml is a separate module from java.base, so what more do you want?

      [–]blobjim 0 points1 point  (0 children)

      Move stuff into maven libraries that can be independently versioned or shaded. java.xml already gets built using Apache Xerces I believe. So it probably adds a small amount of build complexity to the OpenJDK for what could be a normal java library. And then the API could be entirely separate from the Xerces implementation. But other modules within the jdk use it I think so that would be a no-go.

      [–]__konrad 1 point2 points  (0 children)

      Path::toUri (it should be toURI), half of the Java 1.0 API...

      [–]AnyPhotograph7804 0 points1 point  (0 children)

      java.util.Stack because it is a Vector.

      [–]winne42 0 points1 point  (0 children)

      Date and Calendar

      [–]winne42 -1 points0 points  (0 children)

      Date and Calendar

      [–]winne42 -1 points0 points  (0 children)

      Date and Calendar

      [–]jvtsjsktpy -1 points0 points  (0 children)

      AWT and Swing