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