- Readability is one of the biggest thing that comes to mind; here's a decent blog post on the issue.
- Cross-platform operation is big, although I don't know how it fits in the scheme of things.
- Someone well can probably elaborate on this better than I, but one big thing is that Java tends to be easy for mediocre programmers to use. (I specifically did not say "use well".)
- Static typing (which you mentioned).
- Java's garbage collection system was pretty big when it came out, even though it wasn't the first to implement one by a long shot.
- Sun put a lot of marketing dollars into Java, which surely helped give it momentum.
- Java's standard API documentation is pretty good, as is the mechanism for documenting code.
- There is a ton of existing infrastructure for Java, which helps maintain momentum.
- The runtime permits development of other languages, like Scala and JRuby.
- Java has many mature libraries.
- Java's exceptions are pretty sweet, giving you a call stack, and line number if in a debug build.
- Java has several excellent IDEs.
- Java is now open source.
- Java scales fairly well. (Several other items in the list contribute to this.)
- Concurrent programming is made easy.
- Reflection allows for metaprogramming.
- Built-in serialization/deserialization functionality.
- Extensive toolset for remote debugging, profiling, managing, etc.
- Almost perfect Unicode support.
- Easy embedding of resources.
- Performance is quite good these days.*
- Applications can be developed more rapidly than with C/C++.
- Memory cannot be corrupted, at least when using purely managed code.
- There is an incredible amount of information about Java on the web; almost anything is "googleable".
* I am sure this will be debated heavily, or at least has in the past. Java has significant performance advantages over most if not all scripting languages and some compiled languages. Garbage collection can be more efficient than standard C/C++ memory allocation systems. Yes, optimized C code can be made faster in many cases, but this is often not economically prudent;
Java is often Fast Enough (tm).
why not Java
- Checked exceptions aren't all that great, at least as implemented.
- Generics are implemented via type erasure.
- One cannot pass by reference.
- No list comprehensions, like C# 3.0's LINQ (I think these can be called list comprehensions).
- No type inference.
- Code can get quite crufty.
- No true closures (they're coming, at some point).
- Poor support for functional programming.
- Java's static nature (yes, this can be a plus and a minus — see metaprogramming).
- Developing in Java can be slower than in other languages (like Ruby, Python, PHP), especially for prototypes.*
- No operator overloading.
- No support for fancy object literals, like JSON, anonymous types, etc.
- No unsigned types.
- No value types.
- No iterators (like C#'s
- No delegates.
* Java tends to shine on larger projects.