第十六节 泛型与注解

本节主要内容

  1. 泛型(Generic Type)简介
  2. 注解(Annotation)简介
  3. 注解常用场景

1. 泛型(Generic Type)简介

泛型用于指定方法或类可以接受任意类型参数,参数在实际使用时才被确定,泛型可以有效地增强程序的适用性,使用泛型可以使得类或方法具有更强的通用性。泛型的典型应用场景是集合及集合中的方法参数,可以说同Java一样,Scala中泛型无处不在,具体可以查看scala的api

1 泛型类

//单个泛型参数的使用情况
class Person[T](var name:T)

class Student[T](name:T) extends Person(name)

object GenericDemo {
  def main(args: Array[String]): Unit = {
    println(new Student[String]("摇摆少年梦").name)
  }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

多个泛型参数的使用情况:

class Person[T](var name:T)

class Student[T,S](name:T,var age:S) extends Person(name)

object GenericDemo {
  def main(args: Array[String]): Unit = {
    println(new Student[String,Int]("摇摆少年梦",18).name)
  }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
D:\ScalaWorkspace\ScalaChapter16\bin\cn\scala\xtwy>javap -private Person.class
Compiled from "GenericDemo.scala"
public class cn.scala.xtwy.Person<T> {
  private T name;
  public T name();
  public void name_$eq(T);
  public cn.scala.xtwy.Person(T);
}

D:\ScalaWorkspace\ScalaChapter16\bin\cn\scala\xtwy>javap -private Student.class
Compiled from "GenericDemo.scala"
public class cn.scala.xtwy.Student<T, S> extends cn.scala.xtwy.Person<T> {
  private S age;
  public S age();
  public void age_$eq(S);
  public cn.scala.xtwy.Student(T, S);
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

从上面的代码不难看出,scala泛型对应于java中的泛型,掌握了java中的泛型也就掌握了scala中的泛型

2. 注解(Annotation)简介

Annotation是一种对程序代码进行描述的结构化信息。Annotation可以分布在程序的任何地方,能够注解变量、类、方法、参数等多种元素,它的主要功能有以下几种: 
1 自动生成scala文档

scala.collection.immutable.HashMap类对应部分源码:

/** This class implements immutable maps using a hash trie.
 *
 *  '''Note:''' The builder of this hash map may return specialized representations for small maps.
 *
 *  @tparam A      the type of the keys contained in this hash map.
 *  @tparam B      the type of the values associated with the keys.
 *
 *  @author  Martin Odersky
 *  @author  Tiark Rompf
 *  @version 2.8
 *  @since   2.3
 *  @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#hash_tries "Scala's Collection Library overview"]]
 *  section on `Hash Tries` for more information.
 *  @define Coll `immutable.HashMap`
 *  @define coll immutable hash map
 *  @define mayNotTerminateInf
 *  @define willNotTerminateInf
 */
@SerialVersionUID(2L)
class HashMap[A, +B] extends AbstractMap[A, B]
                        with Map[A, B]
                        with MapLike[A, B, HashMap[A, B]]
                        with Serializable
                        with CustomParallelizable[(A, B), ParHashMap[A, B]]
{
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

上述annotation生成的文档内容如下: 
这里写图片描述

2 检查程序中可能出现的语法问题

//当程序使用该API时,给出相应提示,属于语法检查范畴
 @deprecated("Use the `merged` method instead.", "2.10.0")
  def merge[B1 >: B](that: HashMap[A, B1], mergef: MergeFunction[A, B1] = null): HashMap[A, B1] = merge0(that, 0, liftMerger(mergef))

 
 
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

3 规定程序行为

//@BeanProperty,要求程序生成相应getter,setter方法,与java命名规范一致
class Student[T,S](name:T,var age:S) extends Person(name)
{
  @BeanProperty var studentNo:String=null
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

当然,annotation还有其它功能,上面三种只是平时在编写程序时最为常用的功能

annotation具有如下语法格式:

class A
class B extends A{
  //同java一样,采用@+注解关键字对方法、变量
  //类等进行注解标识
  //下面的注解用于标识getName方法在未来会被丢弃
  //不推荐使用
  @deprecated def getName()="Class B"
}

object AnnotationDemo{
  def main(args: Array[String]): Unit = {
    var b=new B()
    //在调用的时候,编译器出给出相应提示
    b.getName()
  }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

3. 注解常用场景

注解的常用场景包括volatile,transient,native,SerialVersionUID,serializable5个,用于对变量或方法进行注解,其中volatile用于标识变量可能会被多个线程同时修改,它不是线程安全的;transient用于标识变量是瞬时的,它不会被持久化;native用于标识算法来自C或C++代码实现



abstract class A
{ 
  //native用于标记 cplusplusMethod为c或c++中实现的本地方法
  @native def cplusplusMethod()
}

//标记B可被序列化
//注解声明序列化版本
@SerialVersionUID(1000330L)
@serializable
class B extends A{
  //volatile注解标记变量name非线程安全
  @volatile var name:String="B"
  //transient注解用于标记变量age不被序列化
  @transient var age:Int=40

}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

下面举下对象序列化的例子:

//下面的代码编译时不会出问题,但执行时会抛出异常
class Person{
  var name:String="zzh"
  var age:Int=0
  override def toString()="name="+name+" age="+age
}

object Serialize {
  def main(args: Array[String]): Unit = {
     val file = new File("person.out")

        val oout = new ObjectOutputStream(new FileOutputStream(file)) 
        val person = new Person 
        oout.writeObject(person)  
        oout.close()

        val oin = new ObjectInputStream(new FileInputStream(file)) 
        val newPerson = oin.readObject()
        oin.close();  
        println(newPerson)
  }
}

Exception in thread "main" java.io.NotSerializableException: cn.scala.xtwy.serialize.Person
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at cn.scala.xtwy.serialize.Serialize$.main(Serialize.scala:22)
    at cn.scala.xtwy.serialize.Serialize.main(Serialize.scala)

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

此时在Person类前加@serializable则可以对对象进行正常序列化

//声明对象可序列化
@serializable
class Person{
  var name:String="zzh"
  var age:Int=0
  override def toString()="name="+name+" age="+age
}

object Serialize {
  def main(args: Array[String]): Unit = {
     val file = new File("person.out")

        val oout = new ObjectOutputStream(new FileOutputStream(file)) 
        val person = new Person 
        oout.writeObject(person)  
        oout.close()

        val oin = new ObjectInputStream(new FileInputStream(file)) 
        val newPerson = oin.readObject()
        oin.close();  
        println(newPerson)
  }
}
//反序列化后的输出结果为:
//name=zzh age=0
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

如果给成员变量加@transient注解的话,则相应的成员变量不会被序列化,此时如果进行反序列化的话,对应成员变量为null,如:

package cn.scala.xtwy.serialize

import java.io.File
import java.io.ObjectOutputStream
import java.io.FileOutputStream
import java.io.ObjectInputStream
import java.io.FileInputStream

@serializable
class Person{
  //@transient注解声明后,成员变量不会被充列化
  @transient var name:String="zzh"
  var age:Int=0
  override def toString()="name="+name+" age="+age
}

object Serialize {
  def main(args: Array[String]): Unit = {
     val file = new File("person.out")

        val oout = new ObjectOutputStream(new FileOutputStream(file)) 
        val person = new Person 
        oout.writeObject(person)  
        oout.close()

        val oin = new ObjectInputStream(new FileInputStream(file)) 
        val newPerson = oin.readObject()
        oin.close();  
        println(newPerson)
  }
}
//反序列化后的输出
//name=null age=0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值