{"id":1964,"date":"2025-06-14T13:13:45","date_gmt":"2025-06-14T01:13:45","guid":{"rendered":"https:\/\/www.ronella.xyz\/?p=1964"},"modified":"2025-06-14T13:13:45","modified_gmt":"2025-06-14T01:13:45","slug":"understanding-covariance-invariance-and-contravariance-in-java-generics","status":"publish","type":"post","link":"https:\/\/www.ronella.xyz\/?p=1964","title":{"rendered":"Understanding Covariance, Invariance, and Contravariance in Java Generics"},"content":{"rendered":"<p>Java generics are a powerful feature that enable developers to write flexible, type-safe code. However, when it comes to subtyping and how generic types relate to each other, things can get a bit tricky. Three key concepts\u2014<strong>covariance<\/strong>, <strong>invariance<\/strong>, and <strong>contravariance<\/strong>\u2014help explain how generics behave in different scenarios. Let\u2019s break down each one with clear explanations and examples.<\/p>\n<hr \/>\n<h2>Invariance: The Default Behavior<\/h2>\n<p>In Java, generics are <strong>invariant<\/strong> by default. This means that even if one type is a subtype of another, their corresponding generic types are not related.<\/p>\n<h3>Example:<\/h3>\n<pre><code class=\"language-java\">List&lt;Number&gt; numbers = new ArrayList&lt;Integer&gt;(); \/\/ Compilation error!<\/code><\/pre>\n<p>Even though <code>Integer<\/code> is a subtype of <code>Number<\/code>, <code>List&lt;Integer&gt;<\/code> is <strong>not<\/strong> a subtype of <code>List&lt;Number&gt;<\/code>. This strictness ensures type safety, preventing accidental misuse of collections.<\/p>\n<hr \/>\n<h2>Covariance: Flexibility with Reading<\/h2>\n<p>Covariance allows a generic type to be a subtype if its type parameter is a subtype. In Java, you express covariance with the wildcard <code>? extends Type<\/code>.<\/p>\n<h3>Example:<\/h3>\n<pre><code class=\"language-java\">List&lt;? extends Number&gt; numbers = new ArrayList&lt;Integer&gt;();<\/code><\/pre>\n<p>Here, <code>numbers<\/code> can point to a <code>List&lt;Integer&gt;<\/code>, <code>List&lt;Double&gt;<\/code>, or any other list whose elements extend <code>Number<\/code>. However, you <strong>cannot add<\/strong> elements to <code>numbers<\/code> (except <code>null<\/code>) because the actual list could be of any subtype of <code>Number<\/code>. You <strong>can<\/strong> read elements as <code>Number<\/code>.<\/p>\n<p><strong>Use covariance when you only need to read from a structure, not write to it.<\/strong><\/p>\n<hr \/>\n<h2>Contravariance: Flexibility with Writing<\/h2>\n<p>Contravariance is the opposite of covariance. It allows a generic type to be a supertype if its type parameter is a supertype. In Java, you use <code>? super Type<\/code> for contravariance.<\/p>\n<h3>Example:<\/h3>\n<pre><code class=\"language-java\">List&lt;? super Integer&gt; integers = new ArrayList&lt;Number&gt;();\nintegers.add(1); \/\/ OK\nObject obj = integers.get(0); \/\/ Allowed\nInteger num = integers.get(0); \/\/ Compilation error!<\/code><\/pre>\n<p>Here, <code>integers<\/code> can point to a <code>List&lt;Integer&gt;<\/code>, <code>List&lt;Number&gt;<\/code>, or even a <code>List&lt;Object&gt;<\/code>. You <strong>can add<\/strong> <code>Integer<\/code> values, but when you retrieve them, you only know they are <code>Object<\/code>.<\/p>\n<p><strong>Use contravariance when you need to write to a structure, but not read specific types from it.<\/strong><\/p>\n<hr \/>\n<h2>Summary Table<\/h2>\n<table>\n<thead>\n<tr>\n<th style=\"text-align: left;\">Variance<\/th>\n<th style=\"text-align: left;\">Syntax<\/th>\n<th style=\"text-align: left;\">Can Read<\/th>\n<th style=\"text-align: left;\">Can Write<\/th>\n<th style=\"text-align: left;\">Example<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td style=\"text-align: left;\">Invariant<\/td>\n<td style=\"text-align: left;\"><code>List&lt;T&gt;<\/code><\/td>\n<td style=\"text-align: left;\">Yes<\/td>\n<td style=\"text-align: left;\">Yes<\/td>\n<td style=\"text-align: left;\"><code>List&lt;Integer&gt;<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\">Covariant<\/td>\n<td style=\"text-align: left;\"><code>List&lt;? extends T&gt;<\/code><\/td>\n<td style=\"text-align: left;\">Yes<\/td>\n<td style=\"text-align: left;\">No<\/td>\n<td style=\"text-align: left;\"><code>List&lt;? extends Number&gt;<\/code><\/td>\n<\/tr>\n<tr>\n<td style=\"text-align: left;\">Contravariant<\/td>\n<td style=\"text-align: left;\"><code>List&lt;? super T&gt;<\/code><\/td>\n<td style=\"text-align: left;\">No*<\/td>\n<td style=\"text-align: left;\">Yes<\/td>\n<td style=\"text-align: left;\"><code>List&lt;? super Integer&gt;<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>*You can only read as <code>Object<\/code>.<\/p>\n<hr \/>\n<h2>Conclusion<\/h2>\n<p>Understanding covariance, invariance, and contravariance is essential for mastering Java generics. Remember:<\/p>\n<ul>\n<li><strong>Invariant<\/strong>: Exact type matches only.<\/li>\n<li><strong>Covariant<\/strong> (<code>? extends T<\/code>): Flexible for reading.<\/li>\n<li><strong>Contravariant<\/strong> (<code>? super T<\/code>): Flexible for writing.<\/li>\n<\/ul>\n<p>By choosing the right variance for your use case, you can write safer and more expressive generic code in Java.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Java generics are a powerful feature that enable developers to write flexible, type-safe code. However, when it comes to subtyping and how generic types relate to each other, things can get a bit tricky. Three key concepts\u2014covariance, invariance, and contravariance\u2014help explain how generics behave in different scenarios. Let\u2019s break down each one with clear explanations [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[17],"tags":[],"_links":{"self":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/1964"}],"collection":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1964"}],"version-history":[{"count":1,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/1964\/revisions"}],"predecessor-version":[{"id":1965,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/1964\/revisions\/1965"}],"wp:attachment":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1964"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1964"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1964"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}