TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Variance in Java

46 点作者 jxub大约 6 年前

5 条评论

BonesJustice大约 6 年前
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_lord大约 6 年前
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 未加载
brianpgordon大约 6 年前
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>
dmitryminkovsky大约 6 年前
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 未加载
zeroimpl大约 6 年前
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.