Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Can you convince me to use Java? I’ve never used it (only C++, Python, CL) but it feels bloated and dirty.


None of the memory problems of C++, the speed of C++ most of the time. Thousands of high quality libraries, a JVM that is a marvel of engineering after 20 years, tooling for development, monitoring and introspection of exceptional quality. Many of the internal tools at the largest Cloud developed in Java. Most enterprise level software. NASA extensive use of Java. A team behind the development who has stunning common sense in resisting the latest fads. Support for IEEE 754 that took years. AOT compilation...The infra behind most internet banking sites out there. Use in high speed trading.

What else do you want from the ecosystem?


What would be a modern IDE for Java?

I remember programming Java in Eclipse. And it was powerful for the time, but everytime I read bloated, I automatically think Eclipse since then..



and also FOSS (Apache 2): https://github.com/JetBrains/intellij-community (as well as PyCharm found in the "python" subdirectory)


IntelliJ is very good.


Eclipse has seen vast development in the last few years and is fast and easy to use these days.


Another rather new option is VSCode + the Java plugin


>” None of the memory problems of C++”

I’m sorry, I’m calling BS here. You can still leak memory in Java.


You can leak memory in any language. That’s an impossible bar. The problems op is referring to is obviously about memory safety.

Java obviously isn’t thread safe like Rust is, but it’s typically safer than C++ on that front too.


Rust isn’t thread safe either. It’s borrow checker will attempt to correct you but you can still run Rust unsafely.


As I understand it Rust's unsafe is designed so you can encapsulate unsafety behind a safe interface.

It's up to the programmer to verify the safety of code using unsafe. But it they do so correctly then you can rely on the borrow checker to verify that everything else is safe.

This means that when you run into a thread safety bug in Rust code you should only have to look at the unsafe blocks to find the culprit.


With that said, I think it is important to mention that if you go off the safe path in rust and you do hit such a bug, your current execution is no longer trustable, it could have corrupted the heap, introduce UB, and die with a segfault, etc.

In java, race conditions can enter illegal application state, but their scope is much more limited. NPEs are 100% safely handled, etc. you can only get off the safe road with using Unsafe unsafe, and manipulating the JVM’s inner state which is not even allowed by default. Depending on application, this difference may matter a lot!


There are two kinds of leaks IMO. The one where your algorithm allocates gigabytes needlessly (and cannot be avoided by language design) and more insidious stuff like having to unsubscribe from an event handler for your object to be dereferenced.


Shitty code is shit in any language. What's your point?


Isn't that true in any language that lets you allocate memory?


var list = [];

while (true) { list.add(1); }

Here you are, which language won't leak memory here?

Also, which language will let you connect to a prod instance without a performance hit to get some stats on the heap and its allocated objects? Hell, you can even list every instance of a type as I've recently learned.


>var list = [];

> while (true) { list.add(1); }

idk, I don't think endlessly growing memory usage is really what a leak is, a leak is really when you have no way of accessing the allocated memory to free it (ex. dropping the last remaining pointer to a `alloc`'d block in C) or the opposite in garbage collected languages: accidentally holding onto a strong reference to objects that should be freed.


> the opposite in garbage collected languages: accidentally holding onto a strong reference to objects that should be freed

So basically what I gave an easy example of. Sure, it won’t look like this in practice, you probably accidentally keep adding to a list, or a cache, but basically this is what happens. The former kind of leak can’t happen with tracing GCs.


You can. But you have to try rather hard.


> None of the memory problems of C++

Every time I see something like this I roll my eyes... C++ doesn't have any "memory problems".

There are sometimes human problems, such as thinking one is capable of coding without understanding the (basic programming) concept of a pointer. But that's because the human's dumb, not a language problem. (This argument also sometimes comes from those who do understand basic programming, but are only familiar with C++98.)

> Thousands of high quality libraries a JVM that is a marvel of engineering after 20 years

I reluctantly have to agree. :)


> Every time I see something like this I roll my eyes... C++ doesn't have any "memory problems".

You can choose which report you would prefer: Microsoft's, Google's 65%, ... I'm sure they just hired bad developers that don't understand pointers.

Sure, human problem, but if no human can use the tool correctly, then surely there is some problem with it. And no, that doesn't mean that memory unsafe languages don't have a place, but we really should have a very good reason for going down that road.


I understand pointers, yet I can’t be trusted never to make a mistake with them. “Each mistake will go uncaught and become an unpredictable catastrophe” is a language problem when your target audience is made of meat.


"But that's because the human's dumb, not a language problem."

If everything is the programmer's fault for being dumb, then Brainfuck is an excellent system language.


> C++ doesn't have any "memory problems"

Well, every time I see someone claim this, I roll my eyes.


It must be hard being perfect. The rest of us will keep looking for solutions for mortals.


I’m a fan, long time fan, but I can honestly say that I feel Java is one of the most pragmatic development systems on the planet.

It can do most anything. It can do it most anywhere. And you can code in it using several different paradigms.

It’s easy to install, it’s easy to be instal several versions, the footprint, by today’s standards, is not enormous.

It’s easy to deploy, especially server side. While you can certainly do all of that modern stuff with containers and what not, it’s not really necessary for Java. Drag and drop a JDK install, anywhere. Plonk your Java server code, anywhere, and point it at your JDK, and. . .that’s it! Fire it up. The JDK is remarkably light on dependencies.

And since most Java apps are “pure Java”, the apps rarely have a dependency outside of the JDK. And since Java apps routinely bundle their Java dependencies, the apps don’t stomp on each other either. Even SQLite bundles it’s binaries in the Java Jar file. So wherever that jar goes (again, and typically bundled with your app), SQLite goes. No floating dependencies.

Desktop bundling requires a bit of search engine research, but it’s doable. And the runtimes can dwarf something like Electron installs.

As a language is Java ELEGANT? Not particularly. It has its own elegance in some areas but that can break down or get overrun in others.

But, boy howdy, it sure is practical. The ecosystem is so huge. It compiles really fast. I marvel at the stories folks tell about their dev cycles in other languages. How do they get anything done, besides sword fighting?

I love Java, but I’m very comfortable in it. But the Maven based dependency system works, it’s huge, it makes use and reuse simple. The IDEs are powerful and mature.

And, finally, Java’s not dead. Hardly. Oracle has been a surprisingly good steward (with warts, as always). The language has been on a rocket of development and shows no sign of slowing down. Server side is still very hot with all the frameworks and all the different approaches. Things like GraalVM taking the JVM in a whole new direction.

And, yea, that. I’ve only been talking Java the language, not the JVM itself per se. That’s a whole other thread.


Throughput in Java can be quite high, and latency can be quite low. You still occasionally get latency spikes from the GC, but these days that's not so bad. (If you are extremely latency sensitive, stick to C++).

Dependency injection frameworks are your bread-and-butter in server-side Java, and some can take a while to grok, but Java can be very productive after the chosen framework "clicks" for you. Typically, this means you'll be writing constructors or factory classes that construct your dependencies per request. The way you wire your factories into the system differs by framework, but it often involves using Java's annotation syntax.

Not having to worry about memory management is a huge win for productivity over C++. Likewise, constructors in Java are much more sane than in C++.

Classical object-oriented programming is intuitive, and Java tends towards the "one obvious way to do something" paradigm. I find it pretty easy to hop into legacy code bases, if I already know the framework being used. The collections API in the standard library is one of the best classical OO APIs out there.

The JVM provides great visibility into the performance of your system. A lot of instrumentation comes "for free".

I'm not sure where you get the "dirty" and "bloated" feeling from. By any definition I can think of for those words, Python would be in the same bucket.


> Java can be very productive after the chosen framework "clicks" for you.

you can chose to not use DI frameworks at all..


DI buys you maintainability.

Without DI, there's too much flexibility in how objects get constructed. If you want to add new functionality to a legacy code base, it can be difficult to track down the different integration points and slow to plumb through your dependencies. These projects can turn into spaghetti very quickly.

DI solves this with a simple recipe: define your functionality, define your dependencies, wire it up to the injector.

The pattern is useful in all OO languages, Python and C++ included.


the problem is that those DI frameworks are all adding substantial amount of complexity and brain load.

I started using just static factories in my code, and abandoned all those DI and it works well enough.


  > I started using just static factories in my code, and abandoned all those DI and it works well enough.
i have done this as well (though not in java), it makes knowing what gets initialized how and where much easier and faster to debug


Yes, I agree that Python can feel “dirty”, although not necessarily “bloated.”


urllib... getopts...

There's as much useless junk in Python's standard library as there is in Java's.


What's dirty is trying to get a python project reliably running on all dev computers. Pyenv, venv, wheels, suddenly you need a complete rust or c toolchain etc. With java I haven't had those kind of issues the last decade, it just works. With python it's still a big hassle and everything breaks every update.


To be fair, getting all those scientific library binaries compiled and installed was a huge pain even before python came around. Python's toolchain made it better, but only marginally in some cases.


Sadly this isn't just the case for scientific Python. E.g. some widely-used web library (I forget which) recently switched to using a Rust implementation of TLS, and suddenly you needed a working Rust tool chain available to install it. This caused a lot of grief.

I love Python, and I've been experimenting with Rust and enjoying it so far, but this situation could have been better handled, I think.

I agree 100% about scientific Python though. It's a whole new level of horrible when it comes to dependency management.


Java itself is a nice language that can be lean and mean but has long been culturally bloated by early tooling and conventions. Since Java 8 (~10 years) the tide has reversed and it now mostly accepted to write terse code that is to the point.

The language gets updated regularly and is managed very competently. Although it may seem to trail on some aspects vs other langs, it benefits from second mover advantage - new features are done right, for the right reasons.

Any Java code ever written is essentially eternal, both in text and compiled bytecode form. Compiler and VM compatibility guarantees are unmatched. You can stumble upon 20 year old code and just use it.

The platform is mature and robust. The JVM itself is a marvel of engineering.

The ecosystem is extremely rich. There isn't a problem that wasn't addressed by a library or a stack overflow question.

The tooling is unequalled. IDEs can reliably perform large code transformations because there is no preprocessor or macros and the type system is relatively sane.

If you know Java you'll never be out of a job.


Bloat is a meaningless word. One person's bloat is another's essential.


How could you possibly like C++ but feel that Java is bloated?

Like I academically understand disliking Java but this just makes no sense.


I think people are understanding 'bloated' differently.

I agree C++ is bloated in a 'just make it a setting' / 'add this feature' / 'kitchen sink' sort of way.

I agree Java is bloated in a boilerplate, empty directories, maybe except for another directory, 'oh god the boilerplate' sort of way.


> I agree C++ is bloated in a 'just make it a setting' / 'add this feature' / 'kitchen sink' sort of way.

Interesting. Can you expand on this, explain more? I honestly don't know what you mean or are referring to -- and I'm a heavy modern c++ advocate -- but suspect if I did it might expand my mindset/viewpoint a bit. :)


Honestly I haven't actually used it since C++14 was new, but it's a common complaint IME that each 'edition' (as Rust would call it, I don't know remember the term, standard?) adds too much, there's too many ways of doing things, variations of pointers, boost, and so on.

I think a lot of people wish it had stayed at say C++7, a mature C superset, but that's enough now. I probably should have said 'I understand' rather than 'I agree' - I don't feel strongly, I don't use either of them.


Ohhh, I get what you mean now, thank you! I understand (and mildly disagree). :)

Yeah, C++ is a living language, I can respectfully see that bothering some people. I viewed c++98->c++11 as essentially a new language with c++14 and c++17 being "bug fixes" for the "new language" that is c++11. But certainly, it can require more learning about every decade now.


I think of Java as more bloated than C++ at runtime - with C++ I can make smaller executables that start up faster, use less memory, etc.

But if you are talking about the source code itself, then things are quite different.


???

I'll answer your question with a question: Have you seen https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpris... ? :)

I'm guess that to those of us who remember when Java came out, "FizzBuzz: EE" is what we think of when we think of Java. :P

In Java I have to type a bazillion characters to get anything done! And make all these useless directories and files and InterfaceClassFactoryProtocolStreamingSerializer BS. And worry about how that executes.

C++? No bloat*, just speed

*Yes, there's some _optional_ bloat. But compared to Java? no contest.


> In Java I have to

You have to do literally none of these things to write working Java.


When java came out? So mid 90s c++ vs mid 90s java?


I mean...Java is run through a VM while C++ is compiled to native code.

I can see that being used as a reasonable argument for bloat.


> run through a VM

This is just incorrect use/understanding of Java’s execution model. It does have a runtime, but it is definitely not a VirtualBox VM.


What are you talking about? No one brought machine/platform virtualization into this conversation other than you.

The bytecode interpreter for Java (and other similar languages) is literally called a Virtual Machine, due to the way it functions:

https://en.m.wikipedia.org/wiki/Java_virtual_machine

It would seem your understanding of the Java execution model is flawed.


C++ allows for much more terse code than java when you do small projects. It is popular in competitive programming for that reason, not just because it runs fast but also because it is really fast to write algorithms in it.


You don’t have to use Java. All the languages you’ve mentioned are fine. If you think that using Java to solve a particular problem is a good idea, then you should definitely use Java.


What feels bloated and dirty?

Because there is plenty of bloated and dirty stuff in C++ and Python too.


What convinced me to consider Java just recently is GraalVM. I don't know about the "dirty" part, but at least GraalVM might solve the "bloated" part. Compiling to native standalone executables makes a big difference to what Java is traditionally known for (portable bytecode but requiring the JVM). Been using C++ and C# for a long time now, and my pet peeves with these languages were also only just addressed relatively recently (C++ getting modules and native AOT for C#). Java being able to get natively compiled makes it worth considering among these. Now, for me, it's a matter of what other frameworks/libraries available for the respective languages would get the job done while I only have to rewrite little to switch among them if I try my best to stay within their syntax overlap.


I work on a Python codebase now after years of JVM and here's what I miss, static typing taken as read.

* Threads that can use more than one core.

* The best approach to package management I've ever seen, no-one worries about typosquatting or "someone already registered all the cool crate names" because every package has at least two coördinates - a group id based on a DNS entry you must be able to prove you have access to, then the package name. So I can publish my malicious package gauva, but as I can't register it with the group id "com.google.guava" or even "com.google.gauva", no-one is going to mistakenly use my package.

* No fucking dance of the C libs. Or Rust these days. I want to use a Python package that wraps a C lib, but there's no binary wheel built for my version of Python and/or platform arch, so build from source it is. Which I'll figure out when pip install -r breaks, and then I get to a) apt-get/brew/etc. install the lib and/or headers b) install any compiler toolchain needed buy not yet present c) export compiler flags and header locations d) all of the above, and then run my pip install again. Until the next library breaks.

* Intersection types for generic bounds. I don't need it that often but when I do, I really miss being to say that for `def foo(ex: T) -> Z`, T must implement interfaces A and B.

* Logging. Occasional horrible security holes aside, Java's logging story is one of the best I've ever worked with, compared to it, Go's sucks, Python sucks more, like how you can't set your preferred timestamp format AND include millis without writing a custom formatter (seriously, go look at the source code of logging.Formatter.formatTime...)

* JMX and MBeans. Having detailed VM performance metrics and the ability to change exposed values or execute an exposed method at runtime built into the VM is amazing. Want to have a quick look at what's happening with the GC? JConsole in. Want to set one logger in particular to DEBUG to see what's going on in prod without having to restart anything? JConsole or jmxterm and away you go. Want to experiment with your batching parameters under prod load to find the sweet spot for throughput? Expose them via an MBean.

* No need for pyenv, virtualenv, etc. Although being fair, if you're working with different incompatible JDK versions, you'll usually end up using SDKMan like Python uses pyenv, and Maven needs a little bit of additional configuration to locate your toolchains, but Gradle is smarter about finding your available JDKs.

* Libraries with type signatures, makes for far easier code reading, and if you pass **kwargs 5 levels down, I hate you. Yes you, sentry-sdk...

* Libraries with correct type signatures, looking at you confluent-kafka, either publish type stubs to typeshed, or update your goddamn doc-string type hints so my IDE doesn't think that confluent_kafka.Message.value() is missing a parameter.

* The ecosystem. I really really really miss the ecosystem of JVM FOSS packages.

* The speed, in general.

I'm sure there's more, but these are the pain points I've been having of late.


Id rather say use kotlin. It comes with a better type system with explicit nullable types, proper closures, and syntactic sugar to easily enavle beneficial programming patterns.

Nd it is very compatible with Java itself, interop is dead simple




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: