Java (Co)Scala中列表上的差异与堆栈上的差异?

Java (Co)Scala中列表上的差异与堆栈上的差异?,java,generics,scala,covariance,Java,Generics,Scala,Covariance,当我编写这段代码时,Scala中出现了一个编译错误 var s: Stack[_ <: Number] = new Stack[Integer]; s.push(new Integer(1)); //compile-error: type mismatch; found :Integer required: _$bqjyh where type _$bqjyh <: Number s.push(null); //compile-error: type mismatch; found

当我编写这段代码时,Scala中出现了一个编译错误

var s: Stack[_ <: Number] = new Stack[Integer]; 
s.push(new Integer(1)); //compile-error: type mismatch; found :Integer required: _$bqjyh where type _$bqjyh <: Number
s.push(null); //compile-error: type mismatch; found   : Null(null) required: _$2 where type _$2 <: Objects.Vehicle

vars:Stack[\up>
不是一个变异操作。这意味着
x::xs
将返回类型列表
List[commonSupertypeOf[typeOf[x],elementTypeOf[xs]]]
(这不是实际的scala代码,但我希望我的观点能被理解),但它不会更改
xs
的类型。如果
xs
具有type
List[Float]
并且
x
具有type
Integer
,则表达式
x::xs
将具有type
List[Numeric]
,但
xs
的类型仍然是
List[Float]
,因此没有中断

add
不过是一个变异操作。
xs.add(x)
将向类型为
Stack
堆栈添加一个
整数
,这显然是一个错误

这就解释了为什么做
x::xs
并不危险。现在来解释为什么它会选择:

列表[a]
上的
::
的性质是:
def::[B>:a](x:B):列表[B]

这意味着,对于任何类型
A
B
,其中
B
A
的超类型,
给定类型
B
的值和类型
A
的列表将生成类型
B
的列表。因此,当您执行一些
someInteger::someFloats
,编译器推断de>B
是数值的,A
是浮动的,一切都正常


在java术语中,这将是
List prepend(B项)
除了
supertypeOf
不是合法的java之外。

Scala语言使用定义站点差异注释,而不是使用站点差异注释。列表的协方差在列表特性中定义,而堆栈不定义为协方差。通常,可变集合不能协方差,因为这会导致类型错误n正在考虑向集合中插入新元素(这是Java协变数组的一个主要问题)。

总结一下:列表是不可变的,并且::创建了一个新的列表,所以没有中断;这与堆栈相反。这是正确的吗?但这是合法的Java?(所以这是可能的,但没有完成?)类列表{list prepend(B项)}@j-Verdurman:是的,这是合法的java,但这是错误的:
A
必须扩展
B
才能使其有意义,而不是相反。prepend的主体看起来像这样:
List result=new LinkedList();result.add(item);result.addAll(this);返回结果;
。但是,只有当
A扩展了B
,而不是
B扩展了A
时,才会编译。对于Scala的所有集合,其中既有不可变的变量,也有可变的变量,不可变的形式是协变的,可变的形式是不变的。
   var list: List[_ <: Number] = Nil;
   var intList : List[Integer] = new Integer(1) :: Nil;
   list = intList ; //no error
   list = new Float(2) :: vehicles;  //even float allowed