当前位置: 首页 > 知识库问答 >
问题:

关于Java和Scala中的泛型

金赤岩
2023-03-14

共有1个答案

郎华皓
2023-03-14

首先要注意,方差是泛型类型参数的属性,而不是参数化类型本身的属性。

其次:关于scala类型的参数在默认情况下是不变的,您是错误的。让我们调查一下!

Java有use-site差异注释。也就是说,可以这样声明方法:

boolean addAll(Collection<? extends T> c);

然而,有一种形式的“参数化类型”(我用的是松散的术语),其中类型参数是协变的:Java数组!(这实际上是疯狂的,因为数组是可变的,因此很容易绕过类型系统)。请考虑以下内容:

public static void subvert(Object[] arr) { arr[0] = "Oh Noes!"; }

后来呢:

Integer[] arr = new Integer[1];
subvert(arr); //this call is allowed as arrays are covariant
Integer i = arr[0];
trait Function1[-I, +O]

这表示特征function1有两个类型参数io,它们分别是反变量和协变量。如果没有声明+/-注释,则类型参数是不变的。例如,Set在其类型参数中是不变的:

scala> def foo(set: Set[Any]) = ()
foo: (set: Set[Any])Unit

scala> Set(1)
res4: scala.collection.immutable.Set[Int] = Set(1)

scala> foo(res4)
<console>:10: error: type mismatch;
 found   : scala.collection.immutable.Set[Int]
 required: Set[Any]
Note: Int <: Any, but trait Set is invariant in type A.
You may wish to investigate a wildcard type such as `_ <: Any`. (SLS 3.2.10)
              foo(res4)
                  ^

然而,列表被声明为协变的:

scala> def bar(list: List[Any]) = ()
bar: (list: List[Any])Unit

scala> List(1)
res6: List[Int] = List(1)

scala> bar(res6)

演示这一点的另一种方法是直接向编译器询问子类型证据:

scala> class Cov[+A]
defined class Cov

scala> implicitly[Cov[Int] <:< Cov[Any]]
res8: <:<[Cov[Int],Cov[Any]] = <function1>

但具有不变类型参数

scala> class Inv[A]
defined class Inv

scala> implicitly[Inv[Int] <:< Inv[Any]]
<console>:9: error: Cannot prove that Inv[Int] <:< Inv[Any].
              implicitly[Inv[Int] <:< Inv[Any]]
                        ^

最后,违反:

scala> class Con[-A]
defined class Con

scala> implicitly[Con[Any] <:< Con[Int]]
res10: <:<[Con[Any],Con[Int]] = <function1>

另请参见标识符<:<

 类似资料:
  • 问题内容: 我已经读过Clojure vs. Scala的各种论述,而我意识到两者都有自己的位置。关于将Clojure和Scala进行比较时,有一些注意事项尚未得到完整的解释: 1.)两种语言中哪一种通常 更快 ?我意识到这从一种语言功能到另一种语言功能都会有所不同,但是对性能进行总体评估会有所帮助。例如:我知道Python字典的速度非常快。但作为一个整体,它是一个 多 比Java慢语。我不想和C

  • 我想通过一个自定义的泛型unapply函数压缩我的计算器,该函数计算参数并在成功时返回值。 但是这失败了,错误 有什么方法可以实现这一点吗?我已经研究了类型标签,不适用方法的隐式转换,但我不知道如何将它们集成到这个问题中。如何正确定义Eval?

  • 做作业的时候,算法的实现洪流填满了。我正在为这个指南编写一个程序:http://en.wikipedia.org/wiki/flood_fill。我有一些问题: 指定函数中的参数替换任何字符的颜色是否正常,我不知道这些坐标最初是什么颜色? 算法正确吗?例如,我在维基百科中编写了它,但我的程序的结果如下: 我的代码:

  • 问题内容: 我正在尝试使用scala json库Circe,将其包装在一个简单的特征中以提供往返于json的转换,我对此具有以下要求: 这样做的目的是简单地能够用任何对象调用JsonConverter并将其转换成json之类的东西,但是当我尝试对其进行编译时,我得到以下信息: 我当然可以拥有一个类,打算通过转换器放入的所有内容都继承自该类,但是我有一个印象,大约可以自动生成编码器/解码器? 问题答

  • 我正在学习java通用编程。我在核心Java(第9版)中看到了这些图表: 我在Java编程综合版第十版简介中看到了这些图表: 但我相信应该是这样的: 有人能告诉我我是否正确吗?

  • 我不知道为什么下面的代码运行得很好,没有< code>gcc错误(< code >-f strict-aliasing-Wstrict-aliasing = 1 )。 如果我遵循严格的别名规则: n1570,§6.5表达式 对象的存储值只能由具有以下类型之一的左值表达式访问: -与对象的有效类型兼容的类型, — 与对象的有效类型兼容的类型的限定版本, -与对象的有效类型对应的有符号或无符号类型的类