Transitioning from C++ to Java

Introduction

For a developer who wants to switch from one main programming language to another this might seem quite challenging (and depending on the concrete cases, it certainly can be) at first. Fortunately, many programming languages have a lot of commonalities since you won’t redevelop the wheel but rather reuse existing proven concepts from an older language.

This is especially the case, if you compare two programming languages where one serves as a basis of inspiration to the other. Java is such a language, where you find a lot of concepts/structures from C/C++; in several cases even the same.

However, when looking at things in detail, there are also cases where concepts seem to be the same at first glance, but have noticeable differences in detail.

This blog post showcases some of these differences and commonalities between Java and C/C++. The listing is far from being complete and just a subjective selection of items picked by the author which popped up while working through the ‘programming bible’ for Java developers: Java ist auch eine Insel [1].

Java and C++ – Commonalities and Differences

The following table depicts the language features of C/C++ and Java and is meant as a rough overview of noticeable differences and commonalities (in the opinion of the author). It is not meant as a summary for every developer (since what’s important in one’s opinion is obviously different from person to person).
Also it’s beyond the scope of this blog post to explain what each concept means. Therefore, we expect that the reader has a decent knowledge about C++ and we don’t mention anything if there are no important difference other than the name for the listing (f.e. auto in C++ vs. var in Java).
Beyond the author’s own experience/knowledge, the main source for looking details up were the already mentioned Java book as well as posts on Stackoverflow [2] and the cppreference.com-page [3].

ConceptC++Java
autokeyword: auto (new in C++11)keyword: var (new in Java 10)
constkeyword: constkeyword: final
final is certainly not a full equivalent to C++’s const keyword. Since there’s no real ‘constness’ in Java, specifying a local variable (or method argument) as final still allows you to modify the object. Only the variable/argument itself cannot be changed (C++ equivalent: const int i = 0;).

Note that in Java you can do a ‘delayed initialization’ of a final variable. As long as the variable is only initialized once, that’s still fine if you specify it as final. Example:
final int a;
[…]
a = 15
namespacekeyword: namespacekeyword: package
usingkeyword: usingkeyword: import
Java also allows to import static class methods/members, which is not possible in C++. Example:
class Foo {
public static void bar() {}
}

Then you can use the bar()-method in a different class simply like:
import static [PACKAGE_NAME].Foo.bar;
[…]
class Foo2 {
public static void bar2() { bar(); }
}
enumskeyword: enum class/struct (new in C++11)

static_cast must be used to convert to int.

Normal (pre-C++11) enums are just ‘integers’ without ‘strict’ type safety.
keyword: enum

Use Foo.ordinal() to convert to int.
++/–/%/+=/-=/etc.-operators These operators are only valid for integer types.In contrast to C++ the prefix/suffix and modulo operators can also be used on float and double.

The same goes for the +=/-=/etc. operators which can mix integer and floating point operands.
Example:
int i = 0;
i += 20.4; // will result in i = 20
>>>-operator n/ARight-shift operator keeping the sign unchanged.
size of char typeUsually 1 byte. However, the standard permits a different size, as long as sizeof(char) <= sizeof(short).2 bytes
constant literal typesThe type of an integer constant is the smallest type which can keep the integer value (beginning with type ‘int’).Always int (use suffix-notation to enforce a different type like long) for integer types.

Floating point constants are double by default (unless suffix is specified) -> same as with C++.
byte (Java)/char/short type in operationsTypes remain unchanged in operations. Types are implicitly cast into int-types so that a + b results in an integer, even if a and b are of type short.

Note:
This even applies to the unary +/- operators!
shadowing variablesEvery variable (local, global, function arguments, or class/object member) can be shadowed.

Recent compilers issue a warning though if this happens.
Only allows shadowing object/class members but not method arguments or local variables.
switch-case-statementAll integer values plus bool and enums are allowed.Allows int-values (not long though!), enums and strings.
Provides extended switch-syntax (4 variants in total. (new in Java 12 / finalized in Java 14)
break/continueValid inside loops – always applies to the inner most loop. Supports syntax with labels to break out of or continue an outer loop.
Break also supported to break out of any block.
range-based-for loopavailable (new in C++11)Available with same syntax as in C++.
class/object members and array initializationNot initialized by default.Initialized by default with 0/null/false.

But:
Local variables are NOT initialized by default (same as with C++).
function parameter evaluation orderright-to-leftleft-to-right!
printf-format stringCurrent compilers usually validate the format string and passed in arguments at compile time and issue warnings.

Note:
There is however no runtime check to ensure that passed in arguments match the specified type!

Arguments and format specifiers are always mapped one-to-one. There is no way to specify one argument and use it for two format specifiers.
Format specifiers are always checked with their passed in argument at runtime.
Note:
The compiler won’t issue a warning!

Favor %n as new line in format string over \n, since the later won’t be converted to a platform specific line ending.
Note:
This is different from C++!
Further note that %n has an entirely different meaning in C++!

Using ‘$x’ (f.e. in ‘%$1f’) allows explicitly specifying a different argument to be used. Using ‘$<‘ specifies that the same argument as used for the previous format specifier is to be used again.
varargsvarargs of different types are supported.

Using special va_list-handling to access and the arguments.
varargs must be of a single type. For example:
void foo(double… bar)

Simple access to varargs like array access.

Can also be passed in an array instead of multiple arguments.
arraysArrays are not objects (in C++11: alternative array class added).

Multi-dimensional arrays always have the same size for each dimension.

No hard limit for number of elements.
Arrays are objects.

Rectangular multi-dimensional arrays supported. For example:
int[][] = new int[][]{{1}, {1, 2, 3, 4}, {1, 2}}
Results in a multi-dimensional array where the first dimension has 3 elements and the second has varying elements: 1, 4, 2.

Hard limit of 2^31 elements within a single dimension.
main()-functionFirst argument is the command line used to call the program.

Exit code directly through return value.
First argument is the first argument passed in in the command line.

No return value. Instead use System.exit(), if exit code must be returned.
stringsString class is mutable.

No hard size limit for strings.
String class is immutable. -> Results in overhead when ‘adjusting’ the string (since new String objects get constructed).
Use StringBuffer (thread-safe)/StringBuilder if string needs to be mutable.

Hard limit at 2^31 characters.
class visibilityNo class visibility of outer classes. You can define a class within a cpp-file to make it kind of ‘private’ (to the single compilation unit).

protected methods/members: only visible in same or derived classes
Classes have their own visibility: public/package
Inner classes can also have private/protected visibility.

protected methods/members: visible to same class, derived classes or other classes in the same package.
Note: There is no visibility to restrict members to (the own and) derived class only!
default visibilitymembers/methods/constructors/destructor: private for classes, public for structs
members/methods/classes: package visibility (class/method/member visible in the same package)

constructors: same visibility as the class visibility

Note: There’s no corresponding C++ construct for package visibility.
default constructordefault constructor dropped, once first custom constructor definedsame as in C++
constructor chainingn/AInside a constructor call:
this(xxx, xxx, …)
to call a different constructor.

Call must be the first line in a constructor.
class initializersconcept: initialize class members in single cpp-file directlyuse static{}-block
nullptr type deductionRequires explicit type-cast of nullptr, if casting is ambiguous. F.e.

class Foo {};
class Foo2 : Foo {
void test(Foo*) {}
void test(Foo2*) {}
}
void main() {
test(nullptr); // compile error – could be Foo* or Foo2*
}
Type deduced for a null pointer based on the context. If either passed in as an argument of a ctor or as an argument for a reference, null type is deducted to the lowest sub class. F.e.

class Foo {};
class Foo2 extends Foo {
void test(Foo f) {}
void test(Foo2 f) {}
};
class Foo3 {
void main() {
Foo2 f = new Foo2();
f.test(null); // will deduce null to Foo2 -> calls test(Foo2 f)
}
}
function range notation conventionusually functions taking a start and end range notation are defined as:
[start, end] – aka: start and end element is included in the range
usually functions taking a start and end range notation are defined:
[begin, end) – aka: start element included but end element not included
For example:
java.util.Array.sort(a, 0, 2) -> sorts array a from 0 to 1 (since 2 is exclusive)

References

[1] – book: “Java ist auch eine Insel, 15. aktualisierte und überarbeitete Auflage” – 2020 (1. Nachdruck 2020) – Author: Christian Ullenboom – Distributor: Rheinwerk Computing (Germany) – ISBN: 978-3-8362-7737-2
[2] – https://stackoverflow.com/
[3] – https://en.cppreference.com/

Updates

2021-09-15: Added enums and strings as switch-case-aruments to Java (and for consistency also added enums to C++, even though these are practically integer values).

2021-09-20: Added following new entries:

  • class initializers
  • class visibility
  • constructor chaining
  • default constructor
  • default visibility
  • enum
  • nullptr type deduction
  • shadowing variables

Author: luke1410

Starting the experience with programming in 1989 (back then with GW-Basic and QBasic), Stefan studied Computer Science at the HTW Aalen (Germany). Following his studies he has been working for the games industry in different areas of game engines (especially focusing on the languages C++ and Lua) for 14 years before switching industries where he is primarily focusing on Java development.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.