Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Comparison of C Sharp and Java
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
=== Type erasure versus reified generics === [[Generics in Java]] are a language-only construction; they are implemented only in the compiler. The generated classfiles include generic signatures only in form of metadata (allowing the compiler to compile new classes against them). The runtime has no knowledge of the generic type system; generics are not part of the [[Java virtual machine]] (JVM). Instead, generics classes and methods are transformed during compiling via a process termed [[type erasure]]. During this, the compiler replaces all generic types with their ''raw'' version and inserts casts/checks appropriately in client code where the type and its methods are used. The resulting byte code will contain no references to any generic types or parameters (See also [[Generics in Java]]). The Java language specification intentionally prohibits certain uses of generics; this is necessary to allow for implementing generics through [[type erasure]], and to allow for migration compatibility.<ref>{{cite web |url=http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#113528 |title=Java SE Specifications |publisher=Java.sun.com |access-date=24 February 2015}}</ref> Research into adding reified generics to the Java platform is ongoing, as part of [[Project Valhalla (Java language)|Project Valhalla]]. C# builds on support for generics from the virtual execution system, i.e., it is not just a language feature. The language is merely a front-end for cross-language generics support in the [[Common Language Runtime|CLR]]. During compiling generics are verified for correctness, but code generation to ''implement'' the generics are deferred to class-load time. Client code (code invoking generic methods/properties) are fully compiled and can safely assume generics to be type-safe. This is called [[Reification (computer science)|reification]]. At runtime, when a unique set of type parameters for a generic class/method/delegate is encountered for the first time, the class loader/verifier will synthesize a concrete class descriptor and generate method implementations. During the generation of method implementations all reference types will be considered one type, as reference types can safely share the same implementations. This is merely for the purpose of ''implementing'' code. Different sets of reference types will still have unique type descriptors; their method tables will merely point to the same code. The following list illustrates some differences between Java and C# when managing generics. It is not exhaustive:<ref>{{cite web |author=Angelika Langer |url=http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html |title=Java Generics FAQs β Frequently Asked Questions β Angelika Langer Training/Consulting |publisher=AngelikaLanger.com |access-date=24 February 2015}}</ref> {| class="wikitable" |- ! style="width:50%;"|Java !! style="width:50%;"|C# |- | Type checks and downcasts are injected into client code (the code ''referencing'' the generics). Compared to non-generic code with manual casts, these casts will be the same,<ref>{{cite web |author=Angelika Langer |url=http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ110 |title=Java Generics FAQs β Under The Hood of the Compiler β Angelika Langer Training/Consulting |publisher=AngelikaLanger.com |date=16 April 2013 |access-date=18 August 2013}}</ref> but compared to compile-time verified code that would not need runtime casts and checks, these operations represent a performance overhead. | C#/.NET generics guarantee type-safety and are verified at compile time, making extra checks/casts are unnecessary at runtime. Hence, generic code will run ''faster'' than non-generic (or type-erased) code that require casts when handling non-generic or type-erased objects. |- | Cannot use primitive types as type parameters; instead, the developer must use the wrapper type corresponding to the primitive type. This incurs extra performance overhead by requiring boxing and unboxing conversions as well a memory and garbage collection pressure, as the wrappers will be heap-allocated as opposed to stack-allocated. | Primitive and value types are allowed as type parameters in generic realizations. At runtime code will be synthesized and compiled for each unique combination of type parameters upon first use. Generics that are realized with primitive/value type do not require boxing/unboxing conversions. |- | Generic exceptions are not allowed<ref>{{cite web |author=Angelika Langer |url=http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ302 |title=Java Generics FAQs β Under The Hood of the Compiler β Angelika Langer Training/Consulting |publisher=AngelikaLanger.com |date=16 April 2013 |access-date=18 August 2013}}</ref> and a type parameter cannot be used in a catch clause<ref>{{cite web |author=Angelika Langer |url=http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ304 |title=Java Generics FAQs β Under The Hood of the Compiler β Angelika Langer Training/Consulting |publisher=AngelikaLanger.com |date=16 April 2013 |access-date=18 August 2013}}</ref> | Can both define generic exceptions and use those in catch clauses |- | Static members are shared across all generic realizations<ref>{{cite web |author=Angelika Langer |url=http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeParameters.html |title=Java Generics FAQs β Type Parameters β Angelika Langer Training/Consulting |publisher=AngelikaLanger.com |date=13 February 2014 |access-date=24 February 2015}}</ref> (during type erasure all realizations are folded into a single class) | Static members are separate for each generic realization. A generic realization is a unique class. |- | Type parameters cannot be used in declarations of static fields/methods or in definitions of static inner classes | No restrictions on use of type parameters |- | Cannot create an array where the component type is a generic realization (concrete parameterized type) <syntaxhighlight lang=Java> Pair<String, String>[] tenPairs = new Pair[10]; //OK </syntaxhighlight> | A generic realization is a 1st class citizen and can be used as any other class; also an array component <syntaxhighlight lang="csharp"> object tenPairs = new Pair<int, string>[10]; // OK </syntaxhighlight> |- | Cannot create an array where the component type is a type parameter, but it is valid to create an <code>Object</code> array and perform a typecast on the new array to achieve the same effect. <syntaxhighlight lang="java"> public class Lookup<K, V> { public V[] getEmptyValues(K key) { return (V[]) new Object[0]; // OK } } </syntaxhighlight> When a generic type parameter is under inheritance constraints the constraint type may be used instead of <code>Object</code> <syntaxhighlight lang=Java> public class Lookup<K, V extends Comparable<V>> { public V[] getEmptyValues(K key) { return (V[]) new Comparable[0]; } } </syntaxhighlight> | Type parameters represent actual, discrete classes and can be used like any other type within the generic definition. <syntaxhighlight lang="csharp"> public class Lookup<K, V> { public V[] GetEmptyValues(K key) { return new V[0]; // OK } } </syntaxhighlight> |- | There is no class literal for a concrete realization of a generic type | A generic realization is an actual class. |- | {{mono|instanceof}} is not allowed with type parameters or concrete generic realizations | The {{mono|is}} and {{mono|as}} operators work the same for type parameters as for any other type. |- | Cannot create new instances using a type parameter as the type | With a constructor constraint, generic methods or methods of generic classes can create instances of classes that have default constructors. |- | Type information is erased during compiling. Special extensions to reflection must be used to discover the original type. | Type information about C# generic types is fully preserved at runtime, and allows full reflection support and instantiation of generic types. |- | Reflection cannot be used to construct new generic realizations. During compilation extra code (typecasts) are injected into the ''client'' code of generics. This precludes creating new realizations later. | Reflection can be used to create new realizations for new combinations of type parameters. |} C# allows generics directly for primitive types. Java, instead, allows the use of boxed types as type parameters (e.g., {{java|List<Integer>}} instead of {{csharp|List<int>}}). This comes at a cost since all such values need to be boxed/unboxed when used, and they all need to be heap-allocated. However, a generic type can be specialized with an array type of a primitive type in Java, for example {{java|List<int[]>}} is allowed.<ref name="generics">{{cite web |url=http://www.artima.com/intv/genericsP.html |title=Generics in C#, Java, and C |publisher=Artima.com |access-date=24 February 2015}}</ref> Several third-party libraries implemented the basic collections in Java with backing primitive arrays to preserve the runtime and memory optimization that primitive types provide.<ref name="trove4j">{{cite web |url=https://bitbucket.org/trove4j/trove |title=trove4j / Trove |access-date=30 June 2017}}</ref>
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)