Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Comparison of Java and C++
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
== Language features == === Syntax === {{see also|Java syntax|C++ syntax}} * [[Java syntax]] has a [[context-free grammar]] that can be parsed by a simple [[LALR parser]]. Parsing C++ is more complicated. For example, {{nowrap|<code>Foo<1>(3);</code>}} is a sequence of comparisons if Foo is a variable, but creates an object if Foo is the name of a class template. * C++ allows namespace-level constants, variables, and functions. In Java, such entities must belong to some given type, and therefore must be defined inside a type definition, either a class or an [[interface (Java)|interface]]. * In C++, objects are values, while in Java they are not. C++ uses ''value semantics'' by default, while Java always uses ''reference semantics''. To opt for reference semantics in C++, either a pointer or a reference can be used. {| class="wikitable" ! style="width:600px;"| C++ ! style="width:600px;"| Java |- | <syntaxhighlight lang="cpp"> class Foo { // Declares class Foo int x = 0; // Private Member variable. It will // be initialized to 0, if the // constructor would not set it. // (from C++11) public: Foo(): x{0} // Constructor for Foo; initializes {} // x to 0. If the initializer were // omitted, the variable would // be initialized to the value that // has been given at declaration of x. int bar(int i) { // Member function bar() return 3 * i + x; } };</syntaxhighlight> | <syntaxhighlight lang="java"> class Foo { // Defines class Foo private int x; // Member variable, normally declared // as private to enforce encapsulation // initialized to 0 by default public Foo() { // Constructor for Foo } // no-arg constructor supplied by default public int bar(int i) { // Member method bar() return 3 * i + x; } }</syntaxhighlight> |- | <syntaxhighlight lang="cpp"> Foo a; // declares a to be a Foo object value, // initialized using the default constructor. // Another constructor can be used as Foo a(args); // or (C++11): Foo a{args}; </syntaxhighlight> | <syntaxhighlight lang="java"> Foo a = new Foo(); // declares a to be a reference to a new Foo object // initialized using the default constructor // Another constructor can be used as Foo a = new Foo(args); </syntaxhighlight> |- | <syntaxhighlight lang="cpp"> Foo b = a; // copies the contents of a to a new Foo object b; // alternative syntax is "Foo b(a)"</syntaxhighlight> | <syntaxhighlight lang="java"> // Foo b = a; // would declare b to be reference to the object pointed to by a Foo b = a.clone(); // copies the contents of the object pointed to by a // to a new Foo object; // sets the reference b to point to this new object; // the Foo class must implement the Cloneable interface // for this code to compile </syntaxhighlight> |- | <syntaxhighlight lang="cpp">a.x = 5; // modifies the object a</syntaxhighlight> | <syntaxhighlight lang="java">a.x = 5; // modifies the object referenced by a</syntaxhighlight> |- | <syntaxhighlight lang="cpp"> std::println("{}", b.x); // outputs 0, because b is // some object other than a </syntaxhighlight> | <syntaxhighlight lang="java"> System.out.println(b.x); // outputs 0, because b points to // some object other than a</syntaxhighlight> |- | <syntaxhighlight lang="cpp"> Foo* c; // declares c to be a pointer to a // Foo object (initially // undefined; could point anywhere)</syntaxhighlight> | <syntaxhighlight lang="java"> Foo c; // declares c to be a reference to a Foo // object (initially null if c is a class member; // it is necessary to initialize c before use // if it is a local variable)</syntaxhighlight> |- | <syntaxhighlight lang="cpp"> c = new Foo; // c is set to the value of the address of the Foo object created by operator new</syntaxhighlight> | <syntaxhighlight lang="java"> c = new Foo(); // binds c to reference a new Foo object</syntaxhighlight> |- | <syntaxhighlight lang="cpp"> Foo& d = *c; // binds d to reference the same object to which c points</syntaxhighlight> | <syntaxhighlight lang="java"> Foo d = c; // binds d to reference the same object as c</syntaxhighlight> |- | <syntaxhighlight lang="cpp"> c->x = 5; // modifies the object pointed to by c</syntaxhighlight> | <syntaxhighlight lang="java"> c.x = 5; // modifies the object referenced by c</syntaxhighlight> |- | <syntaxhighlight lang="cpp"> d.bar(5); // invokes Foo::bar() for a c->bar(5); // invokes Foo::bar() for *c </syntaxhighlight> | <syntaxhighlight lang="java"> d.bar(5); // invokes Foo.bar() for a c.bar(5); // invokes Foo.bar() for c </syntaxhighlight> |- | <syntaxhighlight lang="cpp"> std::println("{}", d.x); // outputs 5, because d references the // same object to which c points </syntaxhighlight> | <syntaxhighlight lang="java"> System.out.println(d.x); // outputs 5, because d references the // same object as c</syntaxhighlight> |- | It is possible to declare a pointer or reference to a [[const]] object in order to prevent client code from modifying it. Functions and methods can also guarantee that they will not modify the object pointed to by a pointer by using the "const" keyword. This enforces [[const-correctness]]. <syntaxhighlight lang="cpp"> const Foo* a; // it is not possible to modify the object // pointed to by a through a </syntaxhighlight> | The <code>final</code> keyword is similar to the <code>const</code> keyword in C++, but its usage is more limited.{{sfn|Goetz|Peierls|Bloch|Bowbeer|2006|loc=§3.4.1 Final fields|p=48}} For the most part, const-correctness must rely on the semantics of the class' interface, i.e., it is not strongly enforced, except for public data members that are labeled <code>final</code>. <syntaxhighlight lang="java"> final Foo a; // a declaration of a "final" reference: // it is possible to modify the object, // but the reference will constantly point // to the first object assigned to it</syntaxhighlight> |- | <syntaxhighlight lang="cpp">a = new Foo();</syntaxhighlight> | <syntaxhighlight lang="java">a = new Foo(); // Only in constructor</syntaxhighlight> |- | <syntaxhighlight lang="cpp">a->x = 5; // ILLEGAL</syntaxhighlight> | <syntaxhighlight lang="java">a.x = 5; // LEGAL, the object's members can still be modified // unless explicitly declared final in the declaring class</syntaxhighlight> |- | <syntaxhighlight lang="cpp">Foo *const b = new Foo(); // a declaration of a "const" pointer // it is possible to modify the object, // but the pointer will constantly point // to the object assigned to it here</syntaxhighlight> | <syntaxhighlight lang="java">final Foo b = new Foo(); // a declaration of a "final" reference</syntaxhighlight> |- | <syntaxhighlight lang="cpp">b = new Foo(); // ILLEGAL, it is not allowed to re-bind it</syntaxhighlight> | <syntaxhighlight lang="java">b = new Foo(); // ILLEGAL, it is not allowed to re-bind it</syntaxhighlight> |- | <syntaxhighlight lang="cpp">b->x = 5; // LEGAL, the object can still be modified</syntaxhighlight> | <syntaxhighlight lang="java">b.x = 5; // LEGAL, the object can still be modified</syntaxhighlight> |} * C++ supports <code>[[goto]]</code> statements, which may lead to [[spaghetti code]] programming. With the exception of the goto statement (which is very rarely seen in real code and highly discouraged), both Java and C++ have basically the same [[control flow]] structures, designed to enforce structured control flow, and relies on [[Control flow#Early exit from loops|break and continue]] statements to provide some <code>goto</code>-like functions. Some commenters point out that these labelled flow control statements break the single point-of-exit property of structured programming.<ref name="Martin">{{cite web|url=http://www.objectmentor.com/resources/articles/javacpp.pdf|title=Java vs. C++: A Critical Comparison|date=January 1997|author=Robert C. Martin|access-date=15 December 2007|archive-url=https://web.archive.org/web/20080511205821/http://www.objectmentor.com/resources/articles/javacpp.pdf|archive-date=11 May 2008|url-status=dead}}</ref> * C++ provides low-level features which Java mostly lacks (one notable exception being the <code>sun.misc.Unsafe</code> API for direct memory access and manipulation). In C++, pointers can be used to manipulate specific memory locations, a task necessary for writing low-level [[operating system]] components. Similarly, many C++ compilers support an [[inline assembler]]. Assembly language code can be imported to a C/C++ program and vice versa. This makes C/C++ language even faster. In Java, such code must reside in external libraries, and can only be accessed via the [[Java Native Interface]], with a significant overhead for each call. === Semantics === * C++ allows default values for arguments of a function/method. Java does not. However, [[method overloading]] can be used to obtain similar results in Java but generate redundant stub code. * The minimum of code needed to compile for C++ is a function, for Java is a class. However, since Java 21 with the introduction of the unnamed class, it is possible to write a Java program consisting only of a main function. * C++ allows a range of implicit conversions between native types (including some narrowing conversions), and also allows defining implicit conversions involving user-defined types. In Java, only widening conversions between native types are implicit; other conversions require explicit cast syntax. ** A result of this is that although loop conditions (<code>if</code>, <code>while</code> and the exit condition in <code>for</code>) in Java and C++ both expect a boolean expression, code such as <code>if(a = 5)</code> will cause a compile error in Java because there is no implicit narrowing conversion from int to boolean, but will compile in C++. This is handy if the code was a typo and <code>if(a == 5)</code> was intended. However, current C++ compilers will usually generate a warning when such an assignment is performed within a conditional expression. Similarly, standalone comparison statements, e.g. <code>a==5;</code>, without a side effect usually lead to a warning. * For passing parameters to functions, C++ supports both [[pass-by-reference]] and [[pass-by-value]]. In Java, primitive parameters are always passed by value. Class types, interface types, and array types are collectively called reference types in Java and are also always passed by value.<ref>{{cite web|title=Reference Types and Values|url=http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.3|work=The Java Language Specification, Third Edition|access-date=9 December 2010}}</ref><ref>{{cite book |title= Core Java |volume= I |edition= Eighth |last1= Horstmann |first1= Cay |last2= Cornell |first2= Gary |publisher= Sun Microsystems |date= 2008 |isbn= 978-0-13-235476-9 |pages= 140–141 |quote=Some programmers (and unfortunately even some book authors) claim that the Java programming language uses call by reference for objects. However, that is false. Because this is such a common misunderstanding, it is worth examining a counterexample in some detail... This discussion demonstrates that the Java programming language does not use call by reference for objects. Instead ''object references are passed by value''.}}</ref><ref>{{cite book |title= Java for Programmers |last1= Deitel |first1= Paul |last2= Deitel |first2= Harvey |publisher= Prentice Hall |date= 2009 |isbn= 978-0-13-700129-3 |page= 223 |quote= Unlike some other languages, Java does not allow programmers to choose pass-by-value or pass-by-reference—all arguments are passed by value. A method call can pass two types of values to a method—copies of primitive values (e.g., values of type int and double) and copies of references to objects (including references to arrays). Objects themselves cannot be passed to methods.}}</ref> * Java built-in types are of a specified size and range defined by the language specification. In C++, a minimal range of values is defined for built-in types, but the exact representation (number of bits) can be mapped to whatever native types are preferred on a given platform. ** For instance, Java characters are 16-bit [[Unicode]] characters, and strings are composed of a sequence of such characters. C++ offers both narrow and wide characters, but the actual size of each is platform dependent, as is the character set used. Strings can be formed from either type. ** This also implies that C++ compilers can automatically select the most efficient representation for the target platform (i.e., 64-bit integers for a 64-bit platform), while the representation is fixed in Java, meaning the values can either be stored in the less-efficient size, or must pad the remaining bits and add code to emulate the reduced-width behavior. * The rounding and precision of floating point values and operations in C++ is implementation-defined (although only very exotic or old platforms depart from the [[IEEE 754]] standard). Java provides an optional ''strict floating-point model'' ([[strictfp]]) that guarantees more consistent results across platforms, though at the cost of possibly slower run-time performance. However, Java does not comply strictly with the IEEE 754 standard. Most C++ compilers will, by default, comply partly with IEEE 754 (usually excluding strict rounding rules and raise exceptions on NaN results), but provide compliance options of varied strictness, to allow for some optimizing.<ref>{{cite web |url= https://gcc.gnu.org/wiki/FloatingPointMath |title= Semantics of Floating Point Math in GCC |publisher= GNU Foundation |access-date= 20 April 2013}}</ref><ref>{{cite web |url= http://msdn.microsoft.com/en-us/library/e7s85ffb.aspx |title= Microsoft c++ compiler, /fp (Specify Floating-Point Behavior) |publisher= Microsoft Corporation |access-date=19 March 2013}}</ref> If we label those options from least compliant to most compliant as ''fast'', ''consistent'' (Java's ''strictfp''), ''near-IEEE'', and ''strict-IEEE'', we can say that most C++ implementations default to ''near-IEEE'', with options to switch to ''fast'' or ''strict-IEEE'', while Java defaults to ''fast'' with an option to switch to ''consistent''. * In C++, [[pointer (computer programming)|pointers]] can be manipulated directly as memory address values. Java references are pointers to objects.<ref>{{cite web |url= http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.3.1 |title= Java Language Specification 4.3.1: Objects |publisher= Sun Microsystems |access-date=9 December 2010}}</ref> Java references do not allow direct access to memory addresses or allow memory addresses to be manipulated with pointer arithmetic. In C++ one can construct pointers to pointers, pointers to ints and doubles, and pointers to arbitrary memory locations. Java references only access objects, never primitives, other references, or arbitrary memory locations. In Java, memory can be read and written by arbitrary values using the <code>sun.misc.Unsafe</code> API, however it is deprecated and not recommended. * In C++, pointers can point to functions or member functions ([[function pointer]]s). The equivalent mechanism in Java uses object or interface references. * Via stack-allocated objects, C++ supports [[Resource Acquisition Is Initialization|scoped resource management]], a technique used to automatically manage memory and other system resources that supports deterministic object destruction. While scoped resource management in C++ cannot be guaranteed (even objects with proper destructors can be allocated using <code>new</code> and left undeleted) it provides an effective means of resource management. Shared resources can be managed using <code>shared_ptr</code>, along with <code>weak_ptr</code> to break cyclic references. Java supports automatic memory management using [[Garbage collection (computer science)|garbage collection]]{{sfn|Bloch|2018|loc=Chapter §2 Item 8: Avoid finalizers and cleaners|pp=29-33}} which can free unreachable objects even in the presence of cyclic references, but other system resources (files,{{sfn|Bloch|2018|loc=Chapter §2 Item 7: Eliminate obsolete references|pp=123-125}} streams, windows, communication ports, threads, etc.) must be explicitly released because garbage collection is not guaranteed to occur immediately after the last object reference is abandoned. * C++ features user-defined [[operator overloading]]. Operator overloading allows for user-defined types to support operators (arithmetic, comparisons, etc.) like primitive types via user-defined implementations for these operators. It is generally recommended to preserve the semantics of the operators. Java supports no form of operator overloading (although its library uses the addition operator for string concatenation). * Java features standard [[application programming interface]] (API) support for [[reflective programming]] (reflection) and [[dynamic loading]] of arbitrary new code. * C++ supports static and dynamic linking of binaries. * Java has [[Generic programming#Generics in Java|generics]], which main purpose is to provide type-safe containers. C++ has compile-time [[Generic programming#Templates in C++|templates]], which provide more extensive support for generic programming and metaprogramming. Java has [[Java annotation|annotations]], which allow adding arbitrary custom metadata to classes and metaprogramming via an [[Annotation processing tool#Java|annotation processing tool]]. * Both Java and C++ distinguish between native types (also termed ''fundamental'' or ''built-in'' types) and user-defined types (also termed ''compound'' types). In Java, native types have value semantics only, and compound types have reference semantics only. In C++ all types have value semantics, but a reference can be created to any type, which will allow the object to be manipulated via reference semantics. * C++ supports [[multiple inheritance]] of arbitrary classes. In Java a class can derive from only one class,{{sfn|Bloch|2018|loc=Foreword|pp=xi-xii}} but a class can implement multiple [[Interface (Java)|interfaces]]{{sfn|Bloch|2018|loc=Chapter §8 Item 8: Favor composition over inheritance|pp=87-92}} (in other words, it supports multiple inheritance of types, but only single inheritance of implementation). * Java explicitly distinguishes between interfaces and classes. In C++, multiple inheritance and pure virtual functions make it possible to define classes that function almost like Java interfaces do, with a few small differences. * Java has both language and standard library support for [[Thread (computer science)|multi-threading]]. The <code>synchronized</code> [[Java keywords|keyword in Java]] provides [[mutual exclusion|mutex locks]] to support multi-threaded applications.{{sfn|Goetz|Peierls|Bloch|Bowbeer|2006|loc=§2.3.1 Intrinsic locks|pp=25-26}}{{sfn|Bloch|2018|loc=Chapter §11 Item 78: Synchronize access to shared mutable data|pp=126-129}} Java also provides libraries for more advanced multi-threading synchronizing. [[C++11]] has a defined memory model for multi-threading in C++, and library support for creating threads and for many synchronizing primitives. There are also many third-party libraries for this. * C++ member functions can be declared as [[virtual function]]s, which means the method to be called is determined by the run-time type of the object (a.k.a. dynamic dispatching). By default, methods in C++ are not virtual (i.e., ''opt-in virtual''). In Java, methods are virtual by default, but can be made non-virtual by using the <code>[[final (Java)|final]]</code> keyword (i.e., ''opt-out virtual''). * C++ enumerations are primitive types and support implicit conversion to integer types (but not from integer types). Java enumerations can be {{code|public static enum{enumName1,enumName2}|java}} and are used like classes. Another way is to make another class that extends <code>java.lang.Enum<E></code>) and may therefore define constructors, fields, and methods as any other class. As of [[C++11]], C++ supports [[C++11#Strongly typed enumerations|strongly-typed enumerations]] which provide more type-safety and explicit specification of the storage type. * Unary operators {{code|++}} and {{code|--}}: in C++ "The operand shall be a modifiable [[Value (computer science)|lvalue]]. [skipped] The result is the updated operand; it is an lvalue...",<ref>Standard for Programming Language C++ '11, 5.3.2 Increment and decrement [expr.pre.incr].</ref> but in Java "the binary numeric promotion mentioned above may include unboxing conversion and value set conversion. If necessary, value set conversion {and/or [...] boxing conversion} is applied to the sum prior to its being stored in the variable.",<ref>The Java™ Language Specification, Java SE 7 Edition, Chapters 15.14.2, 15.14.3, 15.15.1, 15.15.2, http://docs.oracle.com/javase/specs/</ref> i.e. in Java, after the initialization {{code|1=Integer i=2; ++i;|2=java}} changes the reference {{code|i}} by assigning new object, while in C++ the object is still the same. === Resource management === * Java offers automatic [[Garbage collection (computer science)|garbage collection]], which may be bypassed in specific circumstances via the [[Real time Java]] specification. Memory management in C++ is usually done via constructors, destructors, and [[smart pointer]]s. The C++ standard permits garbage collection, but does not require it. Garbage collection is rarely used in practice. * C++ can allocate arbitrary blocks of memory. Java only allocates memory via object instantiation. Arbitrary memory blocks may be allocated in Java as an array of bytes. * Java and C++ use different idioms for resource management. Java relies mainly on garbage collection, which can reclaim memory,{{sfn|Bloch|2018|loc=Chapter §2 Item 8: Avoid finalizers and cleaners|pp=29-33}} while C++ relies mainly on the [[Resource Acquisition Is Initialization]] (RAII) idiom. This is reflected in several differences between the two languages: ** In C++ it is common to allocate objects of compound types as local stack-bound variables which are destroyed when they go out of scope. In Java compound types are always allocated on the heap and collected by the garbage collector (except in virtual machines that use [[escape analysis]] to convert heap allocations to stack allocations). ** C++ has destructors,{{sfn|Bloch|2018|loc=Chapter §2 Item 8: Avoid finalizers and cleaners|pp=29-33}} while Java has [[finalizer]]s.{{sfn|Bloch|2018|loc=Chapter §2 Item 8: Avoid finalizers and cleaners|pp=29-33}} Both are invoked before an object's deallocation, but they differ significantly. A C++ object's destructor must be invoked implicitly (in the case of stack-bound variables) or explicitly to deallocate an object. The destructor executes [[Synchronization|synchronously]] just before the point in a program at which an object is deallocated. Synchronous, coordinated uninitializing and deallocating in C++ thus satisfy the RAII idiom. Destructors in C++ is the normal way of getting back the resources associated with an object, and is a needed counterpart to constructors.{{sfn|Bloch|2018|loc=Chapter §2 Item 8: Avoid finalizers and cleaners|pp=29-33}} In Java, object deallocation is implicitly handled by the garbage collector. A Java object's finalizer is invoked [[Asynchrony (computer programming)|asynchronously]] some time after it has been accessed for the last time and before it is deallocated. Very few objects need finalizers. A finalizer is needed by only objects that must guarantee some cleanup of the object state before deallocating, typically releasing resources external to the JVM.{{sfn|Bloch|2018|loc=Chapter §2 Item 8: Avoid finalizers and cleaners|pp=29-33}} Direct usages of finalizers are usually not advised, as they are unpredictable, usually dangerous, and most of the time unneeded.{{sfn|Bloch|2018|loc=Chapter §2 Item 8: Avoid finalizers and cleaners|pp=29-33}} One has to be cautious not to think of finalizers as C++ destructors.{{sfn|Bloch|2018|loc=Chapter §2 Item 8: Avoid finalizers and cleaners|pp=29-33}} Rather, the try-with-resources or try-finally block achieves a more similar purpose as the destructor.{{sfn|Bloch|2018|loc=Chapter §2 Item 8: Avoid finalizers and cleaners|pp=29-33}} One problem with finalizers or cleaners is that it is not guaranteed that they will run immediately.{{sfn|Bloch|2018|loc=Chapter §2 Item 8: Avoid finalizers and cleaners|pp=29-33}} Hence, a finalizer should never be used for tasks that are time-critical.{{sfn|Bloch|2018|loc=Chapter §2 Item 8: Avoid finalizers and cleaners|pp=29-33}} Additionally, finalizers come with severe performance penalties and significantly increase the time it takes for objects to be deallocated, so their use is discouraged and deprecated in Java 9. ** With RAII in C++, one type of resource is typically wrapped inside a small class that allocates the resource upon construction and releases the resource upon destruction, and provide access to the resource in between those points. Any class that contain only such RAII objects do not need to define a destructor since the destructors of the RAII objects are called automatically as an object of this class is destroyed. In Java, safe synchronous deallocation of resources can be performed deterministically using the try/catch/finally construct. Alternatively, the try-with-resources construct, which was introduced in Java 7, should be used in preference to try-finally construct. {{sfn|Bloch|2018|loc=Chapter §2 Item 9: Prefer try-with-resources to try-finally|pp=34-36}} The try-with-resources construct is more concise and readable.{{sfn|Bloch|2018|loc=Chapter §2 Item 9: Prefer try-with-resources to try-finally|pp=34-36}} It also provide more helpful diagnostic information, since suppressed exception are not discarded, and will be printed in the stack trace with information saying that they were suppressed.{{sfn|Bloch|2018|loc=Chapter §2 Item 9: Prefer try-with-resources to try-finally|pp=34-36}} ** In C++, it is possible to have a [[dangling pointer]], a stale [[Reference (computer science)|reference]] to an object that has already been deallocated. Attempting to use a dangling pointer typically results in program failure. In Java, the garbage collector will not destroy a referenced object. ** In C++, it is possible to have uninitialized primitive objects. Java enforces default initialization. ** In C++, it is possible to have an allocated object to which there is no valid reference. Such an [[unreachable object]] cannot be destroyed (deallocated), and results in a [[memory leak]]. In contrast, in Java an object will not be deallocated by the garbage collector ''until'' it becomes unreachable (by the user program). (''[[Weak reference]]s'' are supported, which work with the Java garbage collector to allow for different ''strengths'' of reachability.) Garbage collection in Java prevents many memory leaks, but leaks are still possible under some circumstances.<ref>{{cite web|url=http://www-128.ibm.com/developerworks/rational/library/05/0816_GuptaPalanki/ |title=Java memory leaks – Catch me if you can |author1=Satish Chandra Gupta |author2=Rajeev Palanki |publisher=IBM DeveloperWorks |date=16 August 2005 |access-date=2015-04-02|archive-url=https://web.archive.org/web/20120722095536/http://www.ibm.com/developerworks/rational/library/05/0816_GuptaPalanki/ |archive-date=2012-07-22}}</ref><ref>[https://web.archive.org/web/20140205030750/http://www.openlogic.com/wazi/bid/188158 How to Fix Memory Leaks in Java] by Veljko Krunic (10 Mar 2009)</ref><ref>[https://stackoverflow.com/questions/6470651/creating-a-memory-leak-with-java Creating a memory leak with Java] on [[stackoverflow]].com</ref> The automatic garbage collector may give the false impression that in Java one does not need to think about memory management.{{sfn|Bloch|2018|loc=Chapter §2 Item 7: Eliminate obsolete references|pp=123-125}} However this is not quite true.{{sfn|Bloch|2018|loc=Chapter §2 Item 7: Eliminate obsolete references|pp=123-125}} Loosely speaking, this is because a program can have "memory leaks", more formally known as "unintentional object retentions".{{sfn|Bloch|2018|loc=Chapter §2 Item 7: Eliminate obsolete references|pp=123-125}} An example of a memory leak that may occur is for a program that has been written without any logical errors, except that it did not eliminate obsolete references.{{sfn|Bloch|2018|loc=Chapter §2 Item 7: Eliminate obsolete references|pp=123-125}} This results in higher use of garbage collector activity, higher [[memory footprint]].{{sfn|Bloch|2018|loc=Chapter §2 Item 7: Eliminate obsolete references|pp=123-125}} In extreme circumstances, this problem can lead to an <code>OutOfMemoryError</code>, but this rarely happens. {{sfn|Bloch|2018|loc=Chapter §2 Item 7: Eliminate obsolete references|pp=123-125}} The solution to this is to null out object references. {{sfn|Bloch|2018|loc=Chapter §2 Item 7: Eliminate obsolete references|pp=123-125}} A second common reason for memory leak is the use of cache that has become no longer relevant. The solution to memory leaks due to using old cache is to represent the cache using a <code>WeakHashMap</code>. === Libraries === * C++ provides [[cross-platform]] access to many features typically available in platform-specific libraries. Direct access from Java to native operating system and hardware functions requires the use of the [[Java Native Interface]], or since Java 21, the Foreign Function and Memory API, which allow for allocating and managing memory outside of the Java Virtual Machine, as well as calling native (i.e. C/C++) functions. * The [[C++ standard library]] is designed to be minimalistic, providing only a standardised set of general use features, while the [[Java Class Library]] and [[Java Platform Module System]] (the Java standard library) is much more extensive, providing a much larger comprehensive standardised set of features, such as graphics, UI creation, and more. === Runtime === {| class="wikitable" ! style="width:50%;"| C++ ! style="width:50%;"| Java |- | C++ is compiled directly to [[machine code]] which is then executed directly by the [[central processing unit]]. | Java is compiled to [[byte-code]] which the [[Java virtual machine]] (JVM) then [[interpreter (computing)|interprets]] at runtime. Actual Java implementations do [[just-in-time compilation]] to native machine code. |- |} * Due to its unconstrained expressiveness, low level C++ language features (e.g. unchecked array access, raw pointers, [[type punning]]) cannot be reliably checked at compile-time or without overhead at run-time. Related programming errors can lead to low-level [[buffer overflow]]s and [[segmentation fault]]s. The [[Standard Template Library]] provides higher-level RAII abstractions (like vector, list and map) to help avoid such errors. In Java, low level errors either cannot occur or are detected by the [[Java virtual machine]] (JVM) and reported to the application in the form of an [[exception handling|exception]]. * The Java language requires specific behavior in the case of an out-of-bounds array access, which generally requires [[bounds checking]] of array accesses. This eliminates a possible source of instability but usually at the cost of slowing execution. In some cases, especially since Java 7, [[compiler analysis]] can prove a bounds check unneeded and eliminate it. C++ has no required behavior for out-of-bounds access of native arrays, thus requiring no bounds checking for native arrays. C++ standard library collections like std::vector, however, offer optional bounds checking. In summary, Java arrays are "usually safe; slightly constrained; often have overhead" while C++ native arrays "have optional overhead; are slightly unconstrained; are possibly unsafe." === Templates vs. generics === Both C++ and Java provide facilities for [[generic programming]], [[Template (programming)|templates]] and [[Generics in Java|generics]], respectively. Although they were created to solve similar kinds of problems, and have similar syntax, they are quite different. :{| class="wikitable" ! C++ Templates ! Java Generics |- | Classes, functions, aliases<ref>{{cite web|website=cppreference.com| url=http://en.cppreference.com/w/cpp/language/type_alias| title=Type alias, alias template| accessdate=4 October 2022}}</ref> and variables<ref>{{cite web|url=http://en.cppreference.com/w/cpp/language/variable_template |website=cppreference.com |title=Variable template |accessdate=4 October 2022}}</ref> can be templated. | Classes and methods can be genericized. |- | Parameters can be variadic, of any type, integral value, character literal, or a class template. | Parameters can be any reference type, including boxed primitive types (i.e. Integer, Boolean...). |- | Separate instantiations of the class or function will be generated for each parameter-set when compiled. For class templates, only the member functions that are used will be instantiated. | One version of the class or function is compiled, works for all type parameters (via type-erasure). |- | Objects of a class template instantiated with different parameters will have different types at run time (i.e., distinct template instantiations are distinct classes). | Type parameters are erased when compiled; objects of a class with different type parameters are the same type at run time. It causes a different constructor. Because of this type erasure, it is not possible to overload methods using different instantiations of the generic class. |- | Implementation of the class or function template must be visible within a translation unit in order to use it. This usually implies having the definitions in the header files or included in the header file. As of [[C++11]], it is possible to use [[C++11#Extern template|extern templates]] to separate compiling of some instantiations. | Signature of the class or function from a compiled class file is sufficient to use it. |- | Templates can be [[Template (programming)#Explicit template specialization|specialized]]—a separate implementation could be provided for a particular template parameter. | Generics cannot be specialized. |- | Template parameters can have [[default argument]]s. Pre-[[C++11]], this was allowed only for template classes, not functions. | Generic type parameters cannot have default arguments. |- | Wildcards unsupported. Instead, return types are often available as nested [[typedef]]s. (Also, [[C++11]] added keyword <code>auto</code>, which acts as a wildcard for any type that can be determined at compile time.) | Wildcards supported as type parameter. |- | Bounding of type parameters and enforcement of relationships between type parameters effectively possible through metaprogramming,<ref>[http://www.boost.org/libs/type_traits/doc/html/boost_typetraits/reference.html Boost type traits library]</ref> or since C++20, directly via <code>std::derived_from</code> and other [[Concepts (C++)|concepts]] | Supports bounding of type parameters with "extends" and "super" for upper and lower bounds, respectively; allows enforcement of relationships between type parameters. |- | Allows instantiation of an object with the type of the parameter type. | Precludes instantiation of an object with the type of the parameter type (except via reflection). |- | Type parameter of class template can be used for static methods and variables. | Type parameter of generic class cannot be used for static methods and variables. |- | [[Static variable]]s unshared between classes and functions of different type parameters. | Static variables shared between instances of classes of different type parameters. |- | Class and function templates do not necessarily enforce type relations for type parameters in their declaration. Use of an incorrect type parameter results in compiling failure, often generating an error message within the template code rather than in the user's code that invokes it. Proper use of templated classes and functions is dependent on proper documentation. Metaprogramming provides these features at the cost of added effort. Since C++20, [[Concepts (C++)|concepts]] can be used to provide these features. | Generic classes and functions can enforce type relationships for type parameters in their declaration. Use of an incorrect type parameter results in a type error within the code that uses it. Operations on parametrized types in generic code are only allowed in ways that can be guaranteed to be safe by the declaration. This results in greater type safety at the cost of flexibility. |- | Templates are [[Turing-complete]] (see [[template metaprogramming]]). | Generics are also Turing-complete<ref>[https://arxiv.org/abs/1605.05274 Java Generics Are Turing Complete]</ref> |} === Miscellaneous === * Java and C++ use different means to divide code into multiple source files. ** Java uses a [[Java package|package system]] that dictates the file name and path for all program definitions. Its compiler imports the executable [[class (file format)|class files]]. ** Prior to [[C++20]], C++ used a [[header file]] [[source code]] inclusion system to share declarations between source files. Since C++20, however, [[precompiled header#Modules|modules]] were introduced offering similar functionality to Java packages, however C++ modules do not have the same granularity of Java packages which allowing for importing individual classes - rather, in C++, all symbols marked <code>export</code> are accessible after importing a module, making it akin to a wildcard import in Java. ** Since [[C++23]], the C++ standard library can now be imported as a module, but must be imported in its entirety rather than importing specific packages of the library like in Java, with <syntaxhighlight lang="C++" inline>import std;</syntaxhighlight>. This may change in the future, with proposals to separate the standard library into more modules such as <code>std.core</code>, <code>std.math</code>, and <code>std.io</code>.<ref name="P0581R1">C++ Standards Committee. (2018). ''P0581R1 - Modules for C++''. Retrieved from [https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0581r1.pdf https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0581r1.pdf]</ref><ref name="P2412R0">C++ Standards Committee. (2021). ''P2412R0 - Further refinements to the C++ Modules Design''. Retrieved from [https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2412r0.pdf https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2412r0.pdf]</ref> * The term "[[modular programming|module]]" refers to different things. In Java, a [[Java package#Modules|module]] is used to group several packages together, meanwhile in C++ a [[precompiled header#Modules|module]] represents a single [[translation unit]]. ** <code>import</code> in C++ imports a module by linking it at compilation, however in C++, modules do not dictate the namespace which a symbol belongs to. Meanwhile, <code>import</code> in Java does not actually "import" any code into a file, and is used to alias classes to avoid fully qualifying them. This is because all classes are handled as needed during runtime by the [[Java class loader]] on demand, and can be invoked even without "importing", simply by fully qualifying the class. * A Java source file must match the namespace which of the public class it declares (it may be named anything if there are no public classes), and the package it belongs to must match the path it is located in. A package may only declare at most one public class (but may have multiple non-public classes). * A C++ source file (whether a header or module) may have any arbitrary name, and may contain as many classes as the programmer desires. Modules have no requirement to match the path of its location. * Compiled Java code files are generally smaller than code files in C++ as [[Java bytecode]] is usually more compact than native [[machine code]] and Java programs are never statically linked. * C++ compiling features an added textual [[preprocessor|preprocessing]] phase, while Java does not. Thus some users add a preprocessing phase to their build process for better support of conditional compiling. * Java's division and modulus operators are well defined to truncate to zero. C++ (pre-[[C++11]]) does not specify whether or not these operators truncate to zero or "truncate to -infinity". -3/2 will always be -1 in Java and C++11, but a [[C++03]] compiler may return either -1 or -2, depending on the platform. [[C99]] defines division in the same fashion as Java and C++11. Both languages guarantee (where a and b are integer types) that <code>(a/b)*b + (a%b) == a</code> for all a and b (b != 0). The [[C++03]] version will sometimes be faster, as it is allowed to pick whichever truncation mode is native to the processor. * The sizes of integer types are defined in Java (int is 32-bit, long is 64-bit), while in C++ the size of integers and pointers is compiler and [[application binary interface]] (ABI) dependent within given constraints. Thus a Java program will have consistent behavior across platforms, whereas a C++ program may require adapting for some platforms, but may run faster with more natural integer sizes for the local platform. An example comparing [[Wikibooks:C++ Programming/Code/IO#.E2.80.8ERounding number example|C++]] and [[Wikibooks:Java Programming/Mathematical functions#Rounding number example|Java]] exists in [[Wikibooks]].
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)