Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the differences between "generic" types in C++ and Java?

People also ask

Are there generic types in C?

Generics are syntax components of a programming language that can be reused for different types of objects. Typically, generics take the form classes or functions, which take type(s) as a parameter.

What are the different types of generic boxes in Java?

Therefore, Box is the raw type of the generic type Box<T>. However, a non-generic class or interface type is not a raw type. The warning shows that raw types bypass generic type checks, deferring the catch of unsafe code to runtime.

What is generic data type in Java?

Generics means parameterized types. The idea is to allow type (Integer, String, … etc., and user-defined types) to be a parameter to methods, classes, and interfaces. Using Generics, it is possible to create classes that work with different data types.

What is the difference between generic class and generic method in Java?

Java Generic methods and generic classes enable programmers to specify, with a single method declaration, a set of related methods, or with a single class declaration, a set of related types, respectively. Generics also provide compile-time type safety that allows programmers to catch invalid types at compile time.


There is a big difference between them. In C++ you don't have to specify a class or an interface for the generic type. That's why you can create truly generic functions and classes, with the caveat of a looser typing.

template <typename T> T sum(T a, T b) { return a + b; }

The method above adds two objects of the same type, and can be used for any type T that has the "+" operator available.

In Java you have to specify a type if you want to call methods on the objects passed, something like:

<T extends Something> T sum(T a, T b) { return a.add ( b ); }

In C++ generic functions/classes can only be defined in headers, since the compiler generates different functions for different types (that it's invoked with). So the compilation is slower. In Java the compilation doesn't have a major penalty, but Java uses a technique called "erasure" where the generic type is erased at runtime, so at runtime Java is actually calling ...

Something sum(Something a, Something b) { return a.add ( b ); }

So generic programming in Java is not really useful, it's only a little syntactic sugar to help with the new foreach construct.

EDIT: the opinion above on usefulness was written by a younger self. Java's generics help with type-safety of course.


Java Generics are massively different to C++ templates.

Basically in C++ templates are basically a glorified preprocessor/macro set (Note: since some people seem unable to comprehend an analogy, I'm not saying template processing is a macro). In Java they are basically syntactic sugar to minimize boilerplate casting of Objects. Here is a pretty decent introduction to C++ templates vs Java generics.

To elaborate on this point: when you use a C++ template, you're basically creating another copy of the code, just as if you used a #define macro. This allows you to do things like have int parameters in template definitions that determine sizes of arrays and such.

Java doesn't work like that. In Java all objects extent from java.lang.Object so, pre-Generics, you'd write code like this:

public class PhoneNumbers {
    private Map phoneNumbers = new HashMap();
    
    public String getPhoneNumber(String name) {
      return (String) phoneNumbers.get(name);
    }
}

because all the Java collection types used Object as their base type so you could put anything in them. Java 5 rolls around and adds generics so you can do things like:

public class PhoneNumbers {
    private Map<String, String> phoneNumbers = new HashMap<String, String>();
    
    public String getPhoneNumber(String name) {
        return phoneNumbers.get(name);
    }
}

And that's all Java Generics are: wrappers for casting objects. That's because Java Generics aren't refined. They use type erasure. This decision was made because Java Generics came along so late in the piece that they didn't want to break backward compatibility (a Map<String, String> is usable whenever a Map is called for). Compare this to .Net/C# where type erasure isn't used, which leads to all sorts of differences (e.g. you can use primitive types and IEnumerable and IEnumerable<T> bear no relation to each other).

And a class using generics compiled with a Java 5+ compiler is usable on JDK 1.4 (assuming it doesn't use any other features or classes that require Java 5+).

That's why Java Generics are called syntactic sugar.

But this decision on how to do generics has profound effects so much so that the (superb) Java Generics FAQ has sprung up to answer the many, many questions people have about Java Generics.

C++ templates have a number of features that Java Generics don't:

  • Use of primitive type arguments.

    For example:

    template<class T, int i>
    class Matrix {
        int T[i][i];
        ...
    }
    

    Java does not allow the use of primitive type arguments in generics.

  • Use of default type arguments, which is one feature I miss in Java but there are backwards compatibility reasons for this;

  • Java allows bounding of arguments.

    For example:

    public class ObservableList<T extends List> {
        ...
    }
    

It really does need to be stressed that template invocations with different arguments really are different types. They don't even share static members. In Java this is not the case.

Aside from the differences with generics, for completeness, here is a basic comparison of C++ and Java (and another one).

And I can also suggest Thinking in Java. As a C++ programmer a lot of the concepts like objects will be second nature already but there are subtle differences so it can be worthwhile to have an introductory text even if you skim parts.

A lot of what you'll learn when learning Java is all the libraries (both standard--what comes in the JDK--and nonstandard, which includes commonly used things like Spring). Java syntax is more verbose than C++ syntax and doesn't have a lot of C++ features (e.g. operator overloading, multiple inheritance, the destructor mechanism, etc) but that doesn't strictly make it a subset of C++ either.


C++ has templates. Java has generics, which look kinda sorta like C++ templates, but they're very, very different.

Templates work, as the name implies, by providing the compiler with a (wait for it...) template that it can use to generate type-safe code by filling in the template parameters.

Generics, as I understand them, work the other way around: the type parameters are used by the compiler to verify that the code using them is type-safe, but the resulting code is generated without types at all.

Think of C++ templates as a really good macro system, and Java generics as a tool for automatically generating typecasts.

 


Another feature that C++ templates have that Java generics don't is specialization. That allows you to have a different implementation for specific types. So you can, for example, have a highly optimized version for an int, while still having a generic version for the rest of the types. Or you can have different versions for pointer and non-pointer types. This comes in handy if you want to operate on the dereferenced object when handed a pointer.


There is a great explanation of this topic in Java Generics and Collections By Maurice Naftalin, Philip Wadler. I highly recommend this book. To quote:

Generics in Java resemble templates in C++. ... The syntax is deliberately similar and the semantics are deliberately different. ... Semantically, Java generics are defined by erasure, where as C++ templates are defined by expansion.

Please read the full explanation here.

alt text
(source: oreilly.com)