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

106,146

Solution 1

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 ); }

Nevertheless, Java's generics help with type-safety.

Solution 2

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.

Solution 3

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.

 

Solution 4

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.

Solution 5

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)

Share:
106,146

Related videos on Youtube

popopome
Author by

popopome

As a mobile app. developer, I have great concern in convergence of mobile,web and desktop.

Updated on April 16, 2022

Comments

  • popopome
    popopome about 2 years

    Java has generics and C++ provides a very strong programming model with templates. So then, what is the difference between C++ and Java generics?

  • OscarRyz
    OscarRyz over 15 years
    They are completely different in implmentation, but equivalent ( or at least similar ) in concept, that is what tina asked.
  • Max Lybbert
    Max Lybbert over 15 years
    They are not equivalent in concept. The best example being the curiously recurring template pattern. The second-best being policy-oriented design. The third-best being the fact that C++ allows integral numbers to be passed in the angle brackets (myArray<5>).
  • josesuero
    josesuero over 15 years
    No, they're not equivalent in concept. There is some overlap in the concept, but not much. Both allow you to create List<T>, but that's about as far as it goes. C++ templates go a lot further.
  • Yuval Adam
    Yuval Adam over 15 years
    Important to note that the type erasure issue means more than just backwards compatability for Map map = new HashMap<String, String>. It means you can deploy new code on an old JVM and it will run due to the similarities in bytecode.
  • Nemanja Trifunovic
    Nemanja Trifunovic over 15 years
    C++ templates have nothing to do with the preprocessors or macros. They never expand to text.
  • Lordn__n
    Lordn__n over 15 years
    You'll note I said "basically a glorified preprocessor/macro". It was an analogy because each template declaration will create more code (as opposed to Java/C#).
  • Nemanja Trifunovic
    Nemanja Trifunovic over 15 years
    Maybe it will and maybe won't create more code - modern compilers are pretty good at removing duplicated code; but the point is that template instantiation is nothing like macro text expansion - thinking in those terms can lead to nasty bugs.
  • Lordn__n
    Lordn__n over 15 years
    I disagree. If you odn't think in those terms you may make the mistake of thinking static instance members are shared between template types, which they aren't. Template code isn't much above copy-and-paste (and I don't mean this in a bad way) hence the macro comparison.
  • Nemanja Trifunovic
    Nemanja Trifunovic over 15 years
    Template code is very different than copy-and-paste. If you think in terms of macro expansion, sooner or later you'll be hit by subtle bugs such as this one: womble.decadentplace.org.uk/c++/…
  • Faisal Vali
    Faisal Vali almost 15 years
    +1 template specialization is incredibly important for compile-time metaprogramming - this difference in itself makes java generics that much less potent
  • Laurence Gonsalves
    Laurence Gonsalves about 14 years
    This is a pretty good, concise explanation. One tweak I'd be tempted to make is that Java generics is a tool for automatically generating typecasts that are guaranteed to be safe (with some conditions). In some ways they're related to C++'s const. An object in C++ won't be modified through a const pointer unless the const-ness is casted away. Likewise, the implicit casts created by generic types in Java are guaranteed to be "safe" unless the type parameters are manually casted away somewhere in the code.
  • Laurence Gonsalves
    Laurence Gonsalves about 14 years
    Why is this an answer and not a comment?
  • Konrad Rudolph
    Konrad Rudolph about 14 years
    @Laurence: for once, because it was posted long before comments were implemented on Stack Overflow. For another, because it’s not only a comment – it’s also an answer to the question: something like the above code isn’t possible in Java.
  • svick
    svick over 13 years
    IEnumerable<T> inherits from IEnumerable, so I wouldn't say that they bear no relation to each other.
  • alphazero
    alphazero almost 13 years
    He is perfectly correct that it is just an elaborate syntactic sugar.
  • dtech
    dtech over 11 years
    It's not purely syntactic sugar. The compiler uses this information for checking types. Even though the information isn't available at runtime I wouldn't call something the compiled uses simply "syntactic sugar". If you would call it that, well then C is just syntactic sugar for assembly, and that's just syntactic sugar for machine code :)
  • poitroae
    poitroae about 11 years
    I think syntactic sugar is useful.
  • stonemetal
    stonemetal over 10 years
    You missed a major point of difference, what you can use to instantiate a generic. In c++ it is possible to use template <int N> and get a different result for any number used to instantiate it. It is used for compile time meta progaming. Like the answer in: stackoverflow.com/questions/189172/c-templates-turing-comple‌​te
  • dfeuer
    dfeuer over 9 years
    Java Generics are not syntactic sugar, because they extend the Java type system. It is true that the limitations of the JVM prevent them from offering the kinds of efficiency advantages that other languages get from parametric polymorphism, but that's an implementation concern.
  • user207421
    user207421 about 8 years
    You do not have to 'specify a type', in the form of either extends or super. Answer is incorrect,
  • user207421
    user207421 about 8 years
    @NemanjaTrifunovic I have used several C++ compilers where templates did indeed expand to text.
  • klaar
    klaar about 8 years
    @EJP: You are right in saying that generics do not require you to specify a sub or super class. But in this specific example where a method is called on an object of this generic type, the generic type must have a super class (or interface) that declares this method.
  • Bhavuk Mathur
    Bhavuk Mathur over 7 years
    May be because Java doesn't have pointers..!! can you explain with a better example?
  • Jakub
    Jakub over 7 years
    Your explanation is so brief! And makes perfectly sense for people that understand the topic well. But for people who don't understand it yet, it doesn't help very much. (Which is the case of anybody asking question on SO, got it?)
  • clocktown
    clocktown over 7 years
    Okay, this is 3 years old but I am responding anyways. I don't see your point. The whole reason Java generates an Error for that commented Line is because you would be calling a function that expects two A's with different Arguments (A and Cons<A>) and this is really basic and also happens when no generics are involved. C++ does that too. Apart from that, this code gave me cancer because it is really horrible. However, you would still do it like that in C++, you have to so modifications of course because C++ is not Java, but that is not a diaadvantage of C++'s Templates.
  • MigMit
    MigMit over 7 years
    @clocktown no, you CAN'T do that in C++. No amount of modifications would allow that. And that IS a disadvantage of C++ templates.
  • clocktown
    clocktown over 7 years
    What your Code was supposed to do - warn about different length - it doesnt do. In your commented out example it only produces errors because of non matching Arguments. That Works in C++, too. You can Type Code that is semantically equivalent and way better than this mess in C++ and in Java.
  • MigMit
    MigMit over 7 years
    It does. Arguments are not matching exactly because lengths are different. You can't do that in C++.
  • Shelby Moore III
    Shelby Moore III over 6 years
    @klaar the subclassing wouldn’t be required if the add interface was injected as an additional function parameter also generically parametrized on T.
  • klaar
    klaar over 6 years
    @ShelbyMooreIII That is very interesting! Can you concoct an example to explain this?
  • Ayxan Haqverdili
    Ayxan Haqverdili almost 4 years
    "In C++ generic functions/classes can only be defined in headers, ..." not necessarily. See this stackoverflow.com/a/115821
  • Sourav Kannantha B
    Sourav Kannantha B about 3 years
    @user207421 Actually, you have to specify the type. If you do not, it just means extends Object, while C++ does not have this kind of mechanism behind the scene.
  • Sourav Kannantha B
    Sourav Kannantha B about 3 years
    @cletus Link you have provided for default type arguments just takes to IBM documentation home page. It might have been broken. Check it.
  • Shmuel Kamensky
    Shmuel Kamensky about 2 years
    @BhavukMathur I think Keithb meant you can overload methods using templates. Sort of a "generic" overload. Pointers were just a sample type.
  • Unixcited
    Unixcited about 2 years
    'Think of C++ templates as a really good macro system' hugely undermines the power of C++ templates
  • apple apple
    apple apple about 2 years
    I know this is a old answer, just to add in c++ you can always SFINAE or require(c++20) the constraint if you want.