| There's nothing really wrong with it, but it's core design is pretty outdated in ways that are difficult to fix without putting together a totally new language. Couple of examples - Support for nullable values. Swift and Kotlin have first class support for these, which are meant to minimize or reduce the number of null pointers in your code. You can mostly fix this with annotations, but those your team using them very consistently, and are not supported by most java libraries. - It's approach to concurrency. Java built in synchronization primitive is based upon an older model of concurrency whose name I cant remember but it involves every object basically being able to maintain internal consistency with it's own state. No one still uses it like this, with most method creating an `Object lock` as a synchronization primitive. - Serialization. Java has built in binary serialization support that ended up being a massive security hole. Most people are now forced to use some json serialization, but the old serialization format is still lurking in the background to ensnare less knowledgeable programmers. - Generics. Smarter people than me can probably give you more detail on this, but generics were grafted on to the language long after it was introduced, and it shows. At runtime, there are no generic types kept, meaning it is technically possible to break the generic typing of an object. None of these it should be noted are deal breakers or reasons why you shouldn't use the language. Almost every single one has some form of workaround for it. But if you're not aware of them (or stuck with an older legacy codebase like a lot of people are) they can be major headaches that can just be avoided by using a more modern language. |