TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Variance in Java

46 pointsby jxubabout 6 years ago

5 comments

BonesJusticeabout 6 years ago
Java is interesting in that variance is defined at a reference site. Contrast that to, say, C#, where variance is defined at a type&#x27;s declaration site.<p>In C#, a type `Function&lt;in T, out R&gt;` is always contravariant with `T` and covariant with `R`. An assignment target of `Function&lt;String, Object&gt;` can always accept a `Function&lt;Object, String&gt;` because the definition of `Function&lt;,&gt;` says that&#x27;s okay.<p>In Java, there is no way to impose variance rules at a type&#x27;s declaration site. An assignment target of `Function&lt;String, Object&gt;` can only (barring unchecked cheats) ever refer to a `Function&lt;String, Object&gt;`. However, I can declare a reference of `Function&lt;? super String, ? extends Object&gt;`, and suddenly it can be assigned a `Function&lt;Object, String&gt;`.<p>I always found this difference interesting. C# is much stricter: all members of a type with generic variance must obey that variance, or that type will not compile. The type `List&lt;T&gt;` can only be invariant with `T` because `T` appears as both an input (e.g., in `Add(T)`) and as an output (e.g., `T this[int]`). In Java, enforcement happens at the usage site. If I declare a `List&lt;? extends String&gt;`, the compiler will happily let me call methods for which `T` is an <i>output</i> (e.g., `get(int)`), but it prohibits me from calling methods for which `T` is an <i>input</i> (e.g., `add(T)`).<p>As an interesting consequence of this decision, Java allows for the concept of &#x27;bivariance&#x27;: it&#x27;s possible to declare a variable of type `List&lt;?&gt;` in Java and assign any instantiation of `List&lt;&gt;` to it. Moreover, I can still invoke members which do not contain `T` in their signature (e.g., I can call `int size()`). In C#, this is simply not possible. To work around this, some generic interfaces have non-generic counterparts. For example, every `IEnumerable&lt;&gt;` instantiation is also an instance of the <i>non-generic</i> `IEnumerable` type.<p>I am curious which approach is more common across other programming languages.
noir_lordabout 6 years ago
Is there a good general book on type theory as it related to programming languages or a good place to start?<p>I don&#x27;t have a strong comp-sci background even though I&#x27;ve been a professional programmer for a long time, I&#x27;ve always preferred strongly typed languages with ADT&#x27;s just from experience but I&#x27;d really like to understand this type of stuff better.
评论 #19637195 未加载
brianpgordonabout 6 years ago
This covers a lot of the same things as my own blog post on the topic:<p><a href="https:&#x2F;&#x2F;briangordon.github.io&#x2F;2014&#x2F;09&#x2F;covariance-and-contravariance.html" rel="nofollow">https:&#x2F;&#x2F;briangordon.github.io&#x2F;2014&#x2F;09&#x2F;covariance-and-contrav...</a>
dmitryminkovskyabout 6 years ago
Great post, this is a tricky subject. I find myself referring to these diagrams from time to time: <a href="https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;33246935&#x2F;741970" rel="nofollow">https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;33246935&#x2F;741970</a>
评论 #19634936 未加载
zeroimplabout 6 years ago
I always find the ArrayStoreException funny. I&#x27;ve written a lot of Java code over the years, including a fair bit pre-generics, and yet I don&#x27;t believe I&#x27;ve ever triggered this exception.