Tangible Software Solutions

Java and C++ Comparison and Equivalents


Equivalents were produced with the Free Edition of C++ to Java Converter and the Free Edition of Java to C++ Converter.


Java C++
public abstract class AbstractClass
{
    protected abstract void AbstractMethod();
}
class AbstractClass
{
protected:
    virtual void AbstractMethod() = 0;
};

The closest equivalent to Java anonymous inner classes in C++ is to use a private class which implements the corresponding interface (but if the interface is a functional interface, then the closest equivalent is to replace the functional interface with a function pointer and the anonymous inner class with a lambda).

Java C++
public class TestClass
{
    private void TestMethod()
    {
        MyInterface localVar = new MyInterface()
        {
            public void method1()
            {
                someCode();
            }
            public void method2(int i, boolean b)
            {
                someCode();
            }
        };
    }
}

Smart pointers:

#include <memory>

class TestClass
{
private:
    void TestMethod()
    {
        std::shared_ptr<MyInterface> localVar = std::make_shared<MyInterfaceAnonymousInnerClass>(shared_from_this());
    }

private:
    class MyInterfaceAnonymousInnerClass : public MyInterface
    {
    private:
        std::shared_ptr<TestClass> outerInstance;

    public:
        MyInterfaceAnonymousInnerClass(std::shared_ptr<TestClass> outerInstance) : outerInstance(outerInstance)
        {
        }

        void method1()
        {
            someCode();
        }
        void method2(int i, bool b)
        {
            someCode();
        }
    };
};

Raw pointers:

class TestClass
{
private:
    void TestMethod()
    {
        MyInterface *localVar = new MyInterfaceAnonymousInnerClass(this);
    }

private:
    class MyInterfaceAnonymousInnerClass : public MyInterface
    {
    private:
        TestClass *outerInstance;

    public:
        MyInterfaceAnonymousInnerClass(TestClass *outerInstance)
        {
            this->outerInstance = outerInstance;
        }

        void method1()
        {
            someCode();
        }
        void method2(int i, bool b)
        {
            someCode();
        }
    };
};

Sized Array

C++ Java
int myArray[2];

or:

int *myArray = new int[2];
int[] myArray = new int[2];

Access Array Element

C++ Java
x = myArray[0]; x = myArray[0];

Jagged Array

C++ Java
int **myArray = new int*[2]; int[][] myArray = new int[2][];

Rectangular Array

C++ Java
int myArray[2][3];

int[][] myArray = new int[2][3];
Java C++
x = (FooType)myObject;
Smart pointers:

x = std::static_pointer_cast<FooType>(myObject);

Raw pointers:

x = static_cast<FooType*>(myObject);
C++ Java
// vector:
std::vector<int> myList = {1, 2, 3};

// unordered_map:
std::unordered_map<std::wstring, int> myD = {
    {string1, 80},
    {string2, 85}
};
import java.util.*;

// ArrayList: (Java 9 List.of would also work here)
ArrayList<Integer> myList = new ArrayList<Integer>(Arrays.asList(1, 2, 3));

// HashMap: (Map.ofEntries requires Java 9)
HashMap<String, Integer> myD = new HashMap<String, Integer>(Map.ofEntries(Map.entry(string1, 80), Map.entry(string2, 85)));

Vectors (C++) and ArrayLists (Java)

C++ Java
#include <vector>

void Vector()
{
    std::vector<int> myList;
    myList.push_back(1);
    int i = 1;
    myList[0] = i;
    i = myList[0];
}
import java.util.*;

private void Vector()
{
    ArrayList<Integer> myList = new ArrayList<Integer>();
    myList.add(1);
    int i = 1;
    myList.set(0, i);
    i = myList.get(0);
}

Maps (C++) and HashMaps (Java)

(std::map and java.util.TreeMap are also very close equivalents).

C++ Java
#include <string>
#include <unordered_map>

void UnorderedMap()
{
    std::unordered_map<std::wstring, int> map;
    std::wstring s = L"test";
    map.emplace(s, 1);
    int i = map[s];
    i = map.size();
    bool b = map.empty();
    map.erase(s);
}
import java.util.*;

private void UnorderedMap()
{
    HashMap<String, Integer> map = new HashMap<String, Integer>();
    String s = "test";
    map.put(s, 1);
    int i = map.get(s);
    i = map.size();
    boolean b = map.isEmpty();
    map.remove(s);
}

Local Constant

C++ Java
constexpr int myConst = 2; final int myConst = 2;

Class Constant

C++ Java
public:
static constexpr int myConst = 2;
public static final int myConst = 2;

Local Variable

C++ Java
int myVar = 2; int myVar = 2;

Inferred Types

There is no inferred typing in Java, so the type is inferred by the converter:

C++ Java
auto myVar = 2; int myVar = 2;

Static Field

C++ Java
public:
static inline int S = 0;
public static int S = 0;

Read-Only Field

C++ Java
public:
const int R = 2;
public final int R = 2;

The implementation of the 'close' method in the Closeable interface can be converted to a C++ destructor, but this is not exactly equivalent.

Java C++
class Foo implements java.io.Closeable
{
    public Foo()
    {
        this(0);   // call to other constructor
    }
    public Foo(int i)
    {
    }

    public final void close()
    {
    }
}
class Foo
{
public:
    Foo() : Foo(0)   // call to other constructor
    {
    }
    Foo(int i)
    {
    }

    ~Foo()   // destructor
    {
    }
};
C++ Java
int/signed int
long/long int/signed long/signed long int

long long/long long int
signed long long/signed long long int

short/short int
signed short/signed short int

unsigned/unsigned int
unsigned long/unsigned long int

unsigned short/unsigned short int
unsigned long long/unsigned long long int

bool
char/wchar_t
signed char
unsigned char
float
double/long double
std::wstring (no C++ language built-in type)
std::any (C++17) or void * (no C++ language built-in type)
int
int (may convert to 'long' on some systems)

long
long

short
short

no unsigned types in Java
no unsigned types in Java

no unsigned types in Java
no unsigned types in Java

boolean
char
byte (signed byte)
no unsigned types in Java
float
double
java.lang.String (no Java language built-in type)
java.lang.Object (no Java language built-in type)

Java does not allow optional parameters. Overloaded methods are the only alternative in Java to optional parameters (these are inserted into the converted code by C++ to Java Converter). A C++ method with n optional parameters is converted to n + 1 overloaded methods. The overloaded methods call the overloaded method with the maximum number of parameters (which contains your original method code), passing the default values originally specified for the original optional parameters.

Here's an example of the simplest possible case:

C++ Java
void TestOptional(int x = 0)
{
    ...
}
public void TestOptional()
{
    TestOptional(0);
}
public void TestOptional(int x)
{
    ...
}

Simple enums in Java have simple equivalents in C++:

Java C++
public enum Simple
{
    FOO,
    BAR
}
enum class Simple
{
    FOO,
    BAR
};

More complex enums in Java unfortunately have exceedingly complex equivalents in C++:

Java C++
public enum Complex
{
    FOO("Foo"),
    BAR("Bar");

    private final String value;

    Complex(String enumValue)
    {
        this.value = enumValue;
    }

    public void InstanceMethod()
    {
        // ...
    }
}
#include <string>
#include <vector>

class Complex final
{
public:
    static inline Complex FOO(L"FOO", InnerEnum::FOO, L"Foo");
    static inline Complex BAR(L"BAR", InnerEnum::BAR, L"Bar");

private:
    static inline std::vector<Complex> valueList;

    class StaticConstructor
    {
    public:
        StaticConstructor()
        {
            valueList.push_back(FOO);
            valueList.push_back(BAR);
        }
    };

    static inline StaticConstructor staticConstructor;

public:
    enum class InnerEnum
    {
        FOO,
        BAR
    };

    const InnerEnum innerEnumValue;
private:
    const std::wstring nameValue;
    const int ordinalValue;
    static inline int nextOrdinal = 0;

    const std::wstring value;

public:
    Complex(const std::wstring &name, InnerEnum innerEnum, const std::wstring &enumValue) : nameValue(name), ordinalValue(nextOrdinal++), innerEnumValue(innerEnum)
    {
        this->value = enumValue;
    }

    virtual void InstanceMethod()
    {
        // ...
    }

    bool operator == (const Complex &other)
    {
        return this->ordinalValue == other.ordinalValue;
    }

    bool operator != (const Complex &other)
    {
        return this->ordinalValue != other.ordinalValue;
    }

    static std::vector<Complex> values()
    {
        return valueList;
    }

    int ordinal()
    {
        return ordinalValue;
    }

    std::wstring toString()
    {
        return nameValue;
    }

    static Complex valueOf(const std::wstring &name)
    {
        for (auto enumInstance : Complex::valueList)
        {
            if (enumInstance.nameValue == name)
            {
                return enumInstance;
            }
        }
    }
};

The C++ 'range for' syntax and Java 'for each' syntax is identical:

C++ Java
for (std::string s : StringList)
{
    ...
}
for (String s : StringList)
{
    ...
}

C++ function pointer typedefs correspond to Java functional interfaces.

Here's an example using two different formats for function pointer typedefs:

C++ Java
class TestFunctionPointers
{
    typedef void(TestFunctionPointers::*Foo1)();
    using Foo2 = void(TestFunctionPointers::*)(); // C++11 syntax

    void method()
    {
        Foo1 TestPtr1 = &TestFunctionPointers::matchedMethod;
        (this->*TestPtr1)();
        Foo2 TestPtr2 = &TestFunctionPointers::matchedMethod;
        (this->*TestPtr2)();
    }
    void matchedMethod()
    {
    }
};
public class TestFunctionPointers
{
    @FunctionalInterface
    private interface Foo1
    {
        void invoke();
    }
    @FunctionalInterface
    private interface Foo2
    {
        void invoke();
    }

    private void method()
    {
        Foo1 TestPtr1 = () -> this.matchedMethod();
        TestPtr1.invoke();

        Foo2 TestPtr2 = () -> this.matchedMethod();
        TestPtr2.invoke();
    }
    private void matchedMethod()
    {
    }
}

Java generics and C++ templates are implemented in totally different ways — Java generics uses the concept of 'type erasure' (compiling to Object and casts), while C++ templates result in separate classes created at compile-time, but you can usually achieve the same result by converting one to the other.

Creating a List

Java C++
ArrayList<Integer> myVar = new ArrayList<Integer>(); std::vector<int> myVar;

Creating a Dictionary

Java C++
HashMap<String, Integer> myVar = new HashMap<String, Integer>(); std::unordered_map<std::string, int> myVar;

Defining a Generic Class

Java C++
public class GenericClass<T>
{
}
template<typename T>
class GenericClass
{
};

Defining a Generic Class with a Constraint

Java C++
public class GenericClass<T extends SomeBase>
{
}
#include <type_traits>

template<typename T>
class GenericClass
{
    static_assert(std::is_base_of<SomeBase, T>::value, "T must inherit from SomeBase");
};

Defining a Generic Method

Java C++
public <T> int Compare(T param1, T param2)
{
}
public:
template<typename T>
int Compare(T param1, T param2)
{
}

Defining a Generic Method with a Constraint

Java C++
public <T extends SomeBase> int Compare(T param1, T param2)
{
}
#include <type_traits>

public:
template<typename T>
int Compare(T param1, T param2)
{
    static_assert(std::is_base_of<SomeBase, T>::value, "T must inherit from SomeBase");
}
Java C++
import Foo.*;
import static Foo.Bar.*;
using namespace Foo;
*no equivalent*

Java does not have indexers, so you must use get/set methods instead:

C++ Java
public:
int &operator [](int index)
{
    return field[index];
}
public final int get(int index)
{
    return field[index];
}
public final void set(int index, int value)
{
    field[index] = value;
}
C++ Java
class DerivedClass : public BaseClass
{
public:
    virtual void MethodOverrideOne() override
    {
    }
    virtual void MethodOverrideTwo() final override
    {
    }
};
public class DerivedClass extends BaseClass
{
    @Override
    public void MethodOverrideOne()
    {
    }
    @Override
    public final void MethodOverrideTwo()
    {
    }
}

C++ doesn't have a separate 'interface' concept, but this is done just as easily in C++ using a class with only 'pure virtual methods'.

Java C++
public interface IFoo
{
    void Method();
}
class IFoo
{
public:
    // pure virtual method:
    virtual void Method() = 0;
};
C++ Java
myVar = [&] (const std::string &text)
{
    return text.length();
};
myVar = (string text) ->
{
    return text.Length;
}

In C++17, the std::any type offers a good equivalent to java.lang.Object.

Java C++ (C++17)
java.lang.Object o = 1;
int i = (int)o;
java.lang.Class t = o.getClass();
#include <any>
#include <typeinfo>

std::any o = 1;
int i = std::any_cast<int>(o);
std::type_info t = o.type();

Java doesn't offer operator overloading, so you have to create instance methods in the place of operator overloads:

C++ Java
class SomeType
{
private:
    int IntValue = 0;

public:
    int operator + (const SomeType &Y)
    {
        return this->IntValue + Y.IntValue;
    }
    void test()
    {
        SomeType o1, o2;
        int i = o1 + o2;
    }
};
public class SomeType
{
    private int IntValue = 0;

    public int add (SomeType Y)
    {
        return this.IntValue + Y.IntValue;
    }
    public void test()
    {
        SomeType o1 = new SomeType();
        SomeType o2 = new SomeType();
        int i = o1.add(o2);
    }
}
Java C++
package FooPackage; // only one per file

public class FooClass
{
}
namespace FooPackage // can have many per file
{
    class FooClass
    {
    };
}
C++ Java

Raw pointers:

Foo *f = new Foo();

Smart pointers:

std::shared_ptr<Foo> f = std::make_shared<Foo>();
Foo f = new Foo();

Java 15 has 'text blocks', but check the documentation — the rules about indentation are very convoluted. Prior to Java 15, the closest you can get is a string concatenation which spans multiple lines.

C++ Java
std::string s = R"(multiline
    raw
    string)";
// Java 15 text blocks:
String s = """
multiline
    raw
    string""";

// before Java 15:
String s = "multiline" + "\r\n" +
    " raw" + "\r\n" +
    " string";

The C++ equivalent to a Java static initializer block uses a private nested class.

Java C++
class Foo
{
    public static int field;

    static
    {
        field = 1;
    }
}
class Foo
{
public:
    static inline int field = 0;

private:
    class StaticConstructor
    {
    public:
        StaticConstructor()
        {
            field = 1;
        }
    };

private:
    static inline Foo::StaticConstructor staticConstructor;
};
Java C++ (C++17)
synchronized (x)
{
    ...
}
#include <mutex>

...

{
    std::scoped_lock<std::mutex> lock(x);
    ......
}
Java C++
try (Foo f = new Foo())
{
    f.method();
}

{
    Foo *f = new Foo();
    f->method();
    delete f;
}

// or, if 'Foo' is designed for RAII:

{
    Foo f;
    f.method();
}

There is no direct equivalent in C++ to the Java 'instanceof' operator, but you can replicate the behavior by testing the result of a 'dynamic_cast':

Java C++
boolean b = f instanceof Foo;
Smart pointers:

bool b = std::dynamic_pointer_cast<Foo>(f) != nullptr;

Raw pointers:

bool b = dynamic_cast<Foo*>(f) != nullptr;

Copyright © 2004 – 2024 Tangible Software Solutions, Inc.