Scala入门到精通——第十六节 泛型与注解
本節主要內容
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)} }多個泛型參數的使用情況:
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)} } 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); }從上面的代碼不難看出,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 Serializablewith CustomParallelizable[(A, B), ParHashMap[A, B]] {上述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))3 規定程序行為
//@BeanProperty,要求程序生成相應getter,setter方法,與java命名規范一致 class Student[T,S](name:T,var age:S) extends Person(name) {@BeanProperty var studentNo:String=null }當然,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()} }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}下面舉下對象序列化的例子:
//下面的代碼編譯時不會出問題,但執行時會拋出異常 class Person{var name:String="zzh"var age:Int=0override 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.Personat 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
此時在Person類前加@serializable則可以對對象進行正常序列化
//聲明對象可序列化 @serializable class Person{var name:String="zzh"var age:Int=0override 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如果給成員變量加@transient注解的話,則相應的成員變量不會被序列化,此時如果進行反序列化的話,對應成員變量為null,如:
package cn.scala.xtwy.serializeimport 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=0override 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總結
以上是生活随笔為你收集整理的Scala入门到精通——第十六节 泛型与注解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Scala入门到精通——第十五节 Cas
- 下一篇: Scala入门到精通——第十七节 类型参