Saturday, April 5, 2014

Difference between templates in C++ and generics in Java


Explain the difference between templates in C++ and generics in Java.


C++ Java
In C++ templates, parameters can be any type or integral. That's why you can create truly generic functions and classes, with the caveat of a looser typing.
std::map<int, int> mapping;

But in Java, parameters can only be reference types (not primitive types). In Java they are basically syntactic sugar to minimize boilerplate casting of Objects.
Map<Integer, Integer> mapping;

For C++ templates, Separate copies of the class or function are likely to be generated for each type parameter when compiled. However for Java generics, only one version of the class or function is compiled and it works for all type parameters.
For C++ templates, Implementation source code of the template class or function must be included in order to use it (declaration sufficient).  For Java templates, Signature of the class or function from a compiled class file is sufficient to use it.
C++ templates can be specialized - a separate implementation could be provided for a particular template parameter.  In Java, generics cannot be specialized.
C++ does not support wildcard. Instead, return types are often available as nested typedefs Java supports wildcard as type parameter if it is only used once. The following Java code is valid:

void printCollection(Collection<?> c) {
    for (Object e : c) {
In C++, static variables are not shared between classes of different type parameters.  In Java, static variables are shared between instances of a classes of different type parameters.
C++ templates doesn't provide bound by default. You have to write separate template to do so. Java provides bounds. You can say, the type T extends a particular class, or implement a particular interface.
public class ObservableList<T extends List>

C# vs Java
Now lets add c# also to the picture.

Java uses the notion of type erasure - a process where the compiler removes all information related to type parameters and type arguments within a class or method. Type erasure enables Java applications that use generics to maintain binary compatibility with Java libraries and applications that were created before generics. In short the underlying compiled classes are not actually generic. They compile down to Object and casts. In effect Java generics are a compile time artifact and can easily be subverted at runtime.

generics in C# (.NET) on the other hand, by virtue of the CLR, implement generics all they way down to the byte code. There is no type erasure by the compiler, and the type checks are performed during runtime. This has its benefits that the type information is preserved in the compiled code. The CLR took several breaking changes in order to support generics in 2.0. The benefits are preformance improvements, deep type safety verification and reflection.

From Wikipedia:
This design choice is leveraged to provide additional functionality, such as allowing reflection with preservation of generic types, as well as alleviating some of the limitations of erasure (such as being unable to create generic arrays). This also means that there is no performance hit from runtime casts and normally expensive boxing conversions.
Rather than saying ".NET generics is better than Java generics", one should look into the difference in the approach to implement generics. In Java, it appears that preserving compatibility was a high priority, while in .NET (when introduced at version 2.0), the realizing the full benefit of using generics was a higher priority.
You can read the detailed differences and uses here. Also, there is a very good conversation between Bruce Eckel and Anders Hejlsberg himself describing the differences here "Generics in C#, Java, and C++".



Post a Comment