`
zk_chs
  • 浏览: 214782 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

scala协变逆变与java中PECS的关系

阅读更多

在effective java 2nd中第28条,有对java范型PECS的介绍。

 

首先,我们看一个在java中经常被我们使用的方法addAll():

为什么在addAll的时候Collection的类型要通过继承范型E来进行限定? 有什么特殊的吗?接着我们再来看一看普通的add方法:

有没有觉得很奇怪?使用add方法的时候又不需要限定类型。

 

下面我们自己来写一个List进行以下测试,看看如果不限定类型的话会发生什么:

可以看到,编译报错:

Error:(24, 41) java: 不兼容的类型: java.util.List<java.lang.Integer>无法转换为java.util.Collection<java.lang.Number>

但是,单个add方法却不会报错。虽然Integer是Number的子类,但Collection<Integer>却不是Collection<Number>的子类,原因在此。

 

关于与addAllForTest对应的popAll方法,各位可以自己试一下。

PECS表示producer-extends、consumer-super,在上面的例子中,producer即addAllForTest,consumer是需要你实现的popAll,而extends与super则是针对这两个方法中参数的范型而言的。

 

下面介绍scala中的协变逆变:

这里写图片描述

这里写图片描述

进行声明时,用[+T]表示协变,[-T]表示逆变。

协变:如果String是AnyRef的子类,那么List[String]也是List[AnyRef]的子类。

逆变:如果String是AnyRef的子类,那么List[String]则是List[AnyRef]的父类。

 

协变点:方法返回值的位置称为协变点(covariant position)。

逆变点:方法参数的位置称为做逆变点(contravariant position)。

 

下面给一段代码加上注释来进行说明:

  // 声明协变,但会报错
  // covariant type A occurs in contravariant position in type A of value x
  // 协变类型A不允许出现在逆变点
  class Person[+A]{
    /** 假设该方法通过编译,那么pAnyref = pString之后,继续调用pAnyref.test(123)便会报错
      * 因为pString.test的参数为String类型,但pAnyref的test方法参数类型为Anyref类型
      * 这样一来,pAnyref = pString之后执行pAnyref.test(123)会报错,因为实际运行时是pString在运行
      */
    def test(x: A) = println(x)
  }
  var pAnyref = new Person[AnyRef]
  var pString = new Person[String]
  pAnyref = pString

 

这个例子会在def test(x: A) 处报错,无法进行编译。下面是逆变的例子:

 

  // 声明逆变,下面这行代码会编译出错
  // contravariant type A occurs in covariant position in type  A of value test
  // 逆变类型A不允许出现在协变点上
  class Person[-A] {
    /** 假设该方法通过编译,那么pString = pAnyref之后,继续调用pString.test便会报错
      * 因为pAnyref.test返回Anyref,而pString作为父类,返回值为String
      * 在pString = pAnyref之后,调用pString.test的话,返回的其实是Anyref,与pString.test应有的返回值String不匹配,发生报错
      */
    def test: A = null.asInstanceOf[A]
  }
  var pAnyref = new Person[AnyRef]
  var pString = new Person[String]
  pString = pAnyref

 

对于scala中协变逆变的使用,是可以同java中的PECS互相参考的,这样学习起来变回容易很多,毕竟大家对java还是比较熟悉的。

 

 

1
5
分享到:
评论

相关推荐

    基于maven的scala与java相互调用的简单实例

    标题"基于maven的scala与java相互调用的简单实例"揭示了这个示例的核心:在Maven项目中,使用Scala和Java代码互相调用。Scala是一种强大的静态类型编程语言,它在语法上兼容Java,并且提供了函数式编程和面向对象...

    Scala集合(二)Java开发Java经验技巧共10页

    【标题】"Scala集合(二)Java开发Java经验技巧共10页" 指的是一份关于Scala集合和Java开发技巧的文档,该文档共包含10页内容,可能是详细讲解了如何在Scala编程中使用集合,并结合了Java开发的经验和技巧。Scala是...

    SpringBoot + SpringData Jpa + Scala + Mysql(java+Scala混编)

    这种混编允许开发团队在已有的Java项目中逐渐引入Scala代码,以利用其优势,同时保持与现有Java代码的兼容性。在实际应用中,可能会在服务端逻辑或者特定组件上使用Scala,而其他部分仍然使用Java,这样可以逐步过渡...

    scala和java混合编译

    例如,避免在Scala代码中使用Java的可变集合,因为这可能导致类型不匹配的问题。同样,当Java代码调用Scala代码时,需确保导入正确的Scala类和对象。 测试方面,你可以使用JUnit(Java测试框架)和ScalaTest(Scala...

    2018 Scala for Java Developers: A Practical Primer

    Master the fundamentals of Scala and understand its emphasis on functional programming that sets it apart from Java. This book will help you translate what you already know in Java to Scala to start ...

    Scala集合Java开发Java经验技巧共9页.pdf

    Scala可以无缝地与Java代码集成,这意味着开发者可以在同一个项目中混合使用两者的特性。Java开发者可以轻松学习Scala,利用其强大的集合库和函数式编程特性,同时保持对现有Java代码库的兼容性。反之,Scala程序也...

    scala-java8-compat_2.11-0.7.0-API文档-中文版.zip

    赠送jar包:scala-java8-compat_2.11-0.7.0.jar; 赠送原API文档:scala-java8-compat_2.11-0.7.0-javadoc.jar; 赠送源代码:scala-java8-compat_2.11-0.7.0-sources.jar; 赠送Maven依赖信息文件:scala-java8-...

    scala java 简体、繁体互转换,判断是否为简体、繁体

    这里我们将详细探讨如何使用Scala和Java来实现简体与繁体中文的互换以及判断文字是简体还是繁体。 首先,让我们了解简体和繁体中文的区别。简体中文是20世纪50年代以来在中国大陆广泛使用的标准化汉字形式,特点是...

    面向Java开发人员的Scala指南

    Scala运行在Java虚拟机(JVM)上,这意味着它可以无缝地与Java代码集成,并利用已有的Java库。然而,Scala的语法更为简洁,且支持更多高级编程概念,如模式匹配、高阶函数和类型推断。对于Java开发者来说,这些新...

    scala中文教程(java 平台开发语言 scala 简单教程)

    1. **类与对象**:Scala中的类和对象概念与Java类似,但更加简洁。例如,可以使用`object`关键字创建单例对象,这在Scala中非常常见。 2. **基本类型和操作**:Scala支持各种基本数据类型,如Int、Double等,并提供...

    在Jelastic上使用Scala编程Java开发Java

    2. **代码互操作**:讲解Scala与Java之间的互操作性,如何调用Java库和方法,以及将Scala组件嵌入到Java项目中。 3. **性能优化**:在Jelastic上运行Scala应用的最佳实践,包括内存管理、并发处理和资源利用率提升。...

    scala-to-java:将Scala代码转换为Java代码的命令行工具

    在目标目录中scala-to-java.jar将创建scala-to-java.jar 使用java -jar target/scala-to-java.jar --slim运行应用程序。 可选的--slim标志可从输出中删除一些样板 输入任何scala代码,例如println("hello, world")...

    scala java相关开发工具

    标题中的“Scala Java相关开发工具”表明我们讨论的是与Java和Scala编程语言相关的开发环境和工具。Java和Scala都是在JVM(Java虚拟机)上运行的语言,它们有着紧密的联系,但各自拥有独特的特性和用途。 首先,...

    Scala语言入门

    Scala运行在Java平台上,可以无缝集成到现有的Java应用程序中。 **目的读者**:本教程的目标读者是有一定编程经验,尤其是熟悉Java语言的程序员。如果你已经掌握了基本的面向对象编程概念,并希望通过Scala来扩展...

    面向Java开发人员Scala指南,Scala和servlet的比较

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的特性,为Java开发者提供...通过阅读和实践本指南,Java开发者可以逐步了解Scala并比较其与Servlet的差异,以便于决定何时以及如何在项目中引入Scala。

    图灵书籍(Scala程序设计(第2版).pdf+Scala程序设计-JAVA虚拟机多核编程实战.pdf)

    Scala因其与Java的紧密关系和在大数据处理、分布式计算领域的广泛应用(如Apache Spark),而受到广泛的关注。学习Scala可以帮助开发者理解函数式编程思想,提升在JVM上的开发效率,并为进入大数据领域奠定基础。 *...

    面向 Java 开发人员的 Scala 指南

    这种兼容性使得Scala能够无缝地与Java代码集成,并充分利用Java的丰富生态系统。 - **面向对象与函数式编程**:Scala将这两种编程范式融为一体。它支持类、继承等面向对象编程特性,同时也支持高阶函数、不可变数据...

    scala-java8-compat_2.11-0.7.0-API文档-中英对照版.zip

    赠送jar包:scala-java8-compat_2.11-0.7.0.jar; 赠送原API文档:scala-java8-compat_2.11-0.7.0-javadoc.jar; 赠送源代码:scala-java8-compat_2.11-0.7.0-sources.jar; 赠送Maven依赖信息文件:scala-java8-...

    Scala语法入门.pdf

    学习Scala需要了解它与Java的关系。Scala基于Java,可以使用Java的大部分类库,并且Scala的类库对Java类库进行了包装,以提供更简洁的接口。虽然Scala是基于Java的,但Scala提供了一套与Java不同的语法和类库,这...

Global site tag (gtag.js) - Google Analytics