编程语言
首页 > 编程语言> > java – (Co)Lala上的差异与Scala中的Stacks不同吗?

java – (Co)Lala上的差异与Scala中的Stacks不同吗?

作者:互联网

当我编写这段代码时,我在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

由于通配符,这相当于Java中的协变集合;它确切的类型在未知,所以我们不能添加东西到堆栈.

但是对于列表,我不会得到同样的错误:

   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

现在我甚至可以添加一个浮点数,但事实上我相信列表是一个整数列表,所以不允许浮点数.

1)为什么这个列表允许,而不是Stacks?这是由于cons(::)运算符吗?

2)列表的类型是什么?它是动态的吗?

3)为什么在Scala而不是Java中允许这样做?

4)我可以在堆栈中添加一些东西吗? (null不起作用,在Java中,因为泛型类型只允许引用类型)

解决方法:

::不是变异操作.这意味着x :: xs将返回List类型List [commonSupertypeOf [typeOf [x],elementTypeOf [xs]]](这不是实际的scala代码,但我希望我的观点能够实现),但它不会改变xs的类型.如果xs的类型为List [Float]且x的类型为Integer,则表达式x :: xs将具有类型List [Numeric],但xs的类型仍然是List [Float],因此没有任何中断.

然而,添加是一个变异操作. xs.add(x)会将一个Integer添加到Stack类型为Stack< Float>的堆栈中,这显然是一个错误.

这解释了为什么做x :: xs并不危险.现在来解释为什么它出现了类型:

列表[A]上::的单字节是:def :: [B>:A](x:B):List [B].

这意味着对于任何类型A和B,其中B是A的超类型,::给定类型B的值,类型A的列表将生成类型B的列表.所以当你做一些someInteger :: someFloats ,编译器推断B是Numeric,A是Float,一切正常.

在Java术语中,它将是< B supertypeOf A>列表与LT; B个prepend(B item),但supertypeOf不是合法的java.

标签:java,scala,covariance,generics
来源: https://codeday.me/bug/20190722/1497571.html