Java was initially created to support network computing on integrated systems. Java was designed to be extremely portable, secure, multithreaded, and distributed, none of which were design goals for C++. Java has a familiar syntax for C programmers, but no direct support for C. Java was also specifically designed to be simpler than C++, but continues to evolve beyond that simplification.
During the decade between 1999 and 2009, especially in the part of the business solutions programming industry, "coffee-based" languages, which are based on "virtual machines" that are familiar in Smalltalk, took on importance. It was an exchange between performance and productivity, something that made perfect sense at a time when computing power and the need for simplified and optimized language allowed not only easy adoption, but a lower learning curve. There is enough similarity between languages so that C++-competent programmers can easily adapt to Java, which is still less complex today and even more consistent in adopted paradigms than C++.
However, this change in interest has declined, mainly due to the evolution of languages. The evolution of C++ and Java has merged much of the gap over the problems and limitations of both languages, today's software requirements have also changed and fragmented further. We now have specific requirements for mobile, data center, and desktop computing, which makes programming language selection an even more central topic.
Syntactic C++ analysis is somewhat more complicated than with Java; for example, Foo <1> (3); is a sequence of comparisons if Foo is a variable, but creates an object if Foo is the name of a class template.
C++ enables namespace-level constants, variables, and functions. All of these Java declarations must be within a class or interface.
const in C++ indicates that the data is 'read-only' and applies to types. Java indicates that the variable should not be reassigned. For basic types such as const int vs final int, these are identical, but for complex classes, they are different.
C++ did not support constructor delegation up to the C++ 11 standard, and only very recent compilers support this.
C++ generates machine code that runs on the hardware, Java generates bytecode that runs on a virtual machine, so with C++ it has greater power at the cost of portability.
C++, int main() is a function in itself, without a class.
The C++ access specification (public, private) is done with tags and in groups.
Java requires automatic garbage collection. Memory management in C++ is usually done by hand or by smart pointers. The C++ standard allows garbage collection, but does not require it; Garbage collection is rarely used in practice. When allowed to relocate objects, modern garbage collectors can improve overall space efficiency and application time over the use of explicit allocation.
C++ can allocate arbitrary memory blocks. Java only allocates memory through object instantiation. (Note that in Java, the developer can simulate the allocation of arbitrary memory blocks by creating a byte array. Still, Java arrays are objects).
Java and C++ use different idioms for resource management. Java is primarily based on garbage collection, while C++ is primarily based on the Resource Acquisition Is Initialization (RAII) language. This is reflected in several differences between the two languages:
In C++, it is common to assign objects of composite types as stack-linked local variables that are destroyed when they are out of range. In Java, composite types are always allocated on the heap and are collected by the garbage collector (except for virtual machines that use escape analysis to convert heap allocations to stack allocations).
The C++ Standard Library provides a limited set of basic and relatively general purpose components. Java has a considerably larger standard library. This additional functionality is available for C++ through third-party libraries (often free), but third-party libraries do not provide the same cross-platform ubiquitous functionality as standard libraries.
C++ is primarily backward compatible with C, and C libraries (such as APIs on most operating systems) are directly accessible from C++. In Java, the richest functionality of your standard library provides cross-platform access to many functions that are typically only available in platform-specific libraries. Direct access from Java to the native operating system and hardware functions requires the use of the native Java interface.
Imports do not duplicate any lexical analysis efforts, which usually results in faster compilation for larger projects.
Imports do not require splitting the code into separate files for declaration/implementation.
Imports make it easier to distribute object code, rather than source code.
Imports can allow circular dependencies between source files.
Imports implicitly carry a mechanism for resolving symbol collisions when more than one symbol table defines the same symbol.
When you modify an importable module, because there is no definition and deployment separation, all dependent modules must be recompiled, which can involve significant build times in large projects.
Imports require a standard mechanism for defining a symbol table in the object code. If this limitation is really a weakness it is debatable, since a standard symbol table is useful for several other reasons.
Imports require a method to discover symbol tables at compile time (such as the class path in Java). However, when there is a standard method for doing this, this is not necessarily more complicated than specifying the locations of the include files.
When circular dependencies are allowed, you may need to interleave semantic analysis of multiple interdependent source files.
Unless the language includes support for partial types, languages with imports instead of inclusions require that all source code in a class be in a single source file.