JAVA5新特性

JAVA5新特性
                    
1>Java在逐漸與C++融合
2>五小點,四大點

一、五小點

 

1、自動封箱AutoBoxing/自動解封
   自動封箱和自動拆箱,它實現了簡單類型和封裝類型的相互轉化時,實現了自動轉化。 
    byte b     -128~127
    Byte b     在以上數量的基礎上多一個null

   簡單類型和封裝類型之間的差別
   封裝類可以等於null  ,避免數字得0時的二義性。
   Integer i=null;
   int ii=i;  //會拋出NullException 異常。相當於 int ii=i.intValue();
   Integer i=1; //相當於Integer i=new Integer(1);
   i++;    // i = new Integer(i.intValue()+1);

   在基本數據類型和封裝類之間的自動轉換
   5.0之前
   Integer i=new Integer(4);
   int  ii= i.intValue();

   5.0之後
   Integer i=4;
   Long l=4.3;
  
   public void m(int i){......}
   public void m(Integer i){......}
   以上兩個函數也叫方法重載
   自動封箱解箱只在必要的時候才進行。能不封箱找到匹配的就不封箱。
  
   注意:Integer 和 int 的默認值是不一樣的,Integer 是null(對象嘛),int 是0(基本數據類型嘛);

 

2、靜態引入 StaticImport
   使用類中靜態方法時不用寫類名
  
   System.out.println(Math.round(PI));
   可以用以下代碼實現:
   import static java.lang.System.*;  //注意,要寫" 類名.* "
   import static java.lang.Math.*;
   out.println(round(PI));
  
   注意:靜態引入的方法不能重名
  
3、for-each
   統一了遍歷  數組  和遍歷  集合  的方式  
   for(Object o:list){     //Object o 表示每個元素的類型 ,list 表示要遍歷的數組或集合的名字
       System.out.println(o);  //打印集合或數組中的每個元素
   }


4、可變長參數
   處理方法重載中,參數類型相同,個數不同的情況     
   public void m(int... is){.....}
  
   int... is 相當於一個 int[] is
   編譯器會把給定的參數封裝到一個數組中,再傳給方法
   在一個方法中只能有一個可變長參數,而且,必須放在最後一個參數的位置
  
5、格式化輸入/輸出
   java.util.Formatter類 對格式的描述
   System.out.printf("Hello %s",str);  //打印字符串類型的變量,用一個佔位符  
  
   格式化I/O(Formatted I/O)
   java.util.Sacner類可以進行格式化的輸入,可以使用控制檯輸入,結合了BufferedReader和StringTokener的功能。
  


二、四大點  

 

1、枚舉(Enum)
  枚舉是一個類,並且這個類的對象是現成的,在定義類的時候,即定義好了對象
  程序員要使用的時候,只能從中選擇,無權創建
  enum 枚舉名{
 枚舉值1(..),枚舉值2(..),.....;
  }
 
(1) 在5.0之前使用模式做出一個面向對象的枚舉
    final class Season{
        public static final Season SPRING=new Season();
        public static final Season WINTER=new Season();
        public static final Season SUMMER=new Season();
        public static final Season AUTUMN=new Season();
        private Season(){}
    }
    完全等價於
    enum Season2{
 SPRING(..),//枚舉值
 SUMMER(..),
 AUTUMN(..),
 WINTER(..)
    }     
 
    枚舉本質上也是一個類,Enum是枚舉的父類。
    這個類編譯以後生成一個.class類
    這個類有構造方法,但是是私有的
 
    枚舉中的values()方法會返回枚舉中的所有枚舉值
    枚舉中可以定義方法和屬性,最後的一個枚舉值要以分號和類定義分開,枚舉中可以定義的構造方法。
    枚舉不能繼承類(本身有父類),但可以實現接口,枚舉不能有子類也就是final的,枚舉的構造方法是private(私有的)。
    枚舉中可以定義抽象方法,可以在枚舉值的值中實現抽象方法。
    枚舉值就是枚舉的對象,枚舉默認是final,枚舉值可以隱含的匿名內部類來實現枚舉中定義抽象方法。
 
(2)枚舉類(Enumeration Classes)和類一樣,具有類所有特性。Season2的父類是java.lang.Enum;
    隱含方法: 每個枚舉類型都有的方法。
    Season2[] ss=Season2.values();     ----獲得所有的枚舉值 
    for(Season2 s:ss){
      System.out.println(s.name());   ----- 打印枚舉值
      System.out.println(s.ordinal()); ----- 打印枚舉值的編號
    }
 
 
(3)  enum可以switch中使用(不加類名)。
  switch( s ){
 case SPRING:
   …………….
 case SUMMER:
   …………….
 …………..
  }


(4)枚舉的有參構造
  enum Season2{
 SPRING(“春”),-------------------------------逗號
 SUMMER(“夏”),-----------------------------逗號
 AUTUMN(“秋”),-----------------------------逗號
 WINTER(“冬”);------------------------------ 分號
 private String name;
 Season2(String name){    //構造方法必須是私有的,可以不寫private,默認就是私有的
  this.name=name;
        }
        String getName(){
         return name;
        }

  }
  Season2.SPRING.getName()         ---------------------春
 

(5)枚舉中定義的抽象方法,由枚舉值實現:
  enum Operation{
 ADD('+'){
  public double calculate(double s1,double s2){
   return s1+s2;
  }
 },
 SUBSTRACT('-'){
  public double calculate(double s1,double s2){
   return s1-s2;
  }
 },
 MULTIPLY('*'){
  public double calculate(double s1,double s2){
   return s1*s2;
  }
 },
 DIVIDE('/'){
  public double calculate(double s1,double s2){
   return s1/s2;
  }
 };
 char name;
 public char getName(){
  return this.name;
 }
 Operation(char name){
  this.name=name;
 }
 public abstract double calculate(double s1 ,double s2);
  }
  有抽象方法枚舉元素必須實現該方法。
 
  Operator[] os = Operator.values();
  for(Operator o:os){
     System.out.println("8 "+o.name()+" 2="+o.calculate(8,2));
  }
  for(Operator o:os){
     System.out.println("8 "+o.getName()+" 2="+o.calculate(8,2));
  } 
 
  運行結果:
  8 ADD 2=10.0
  8 SUBSTRACT 2=6.0
  8 MULTIPLY 2=16.0
  8 DIVIDE 2=4.0
  8 + 2=10.0
  8 - 2=6.0
  8 * 2=16.0
  8 / 2=4.0
 
 
2、泛型  (Generic)
(1)增強了java的類型安全,可以在編譯期間對容器內的對象進行類型檢查,在運行期不必進行類型的轉換。
   而在java se5.0之前必須在運行期動態進行容器內對象的檢查及轉換,泛型是編譯時概念,運行時沒有泛型

   減少含糊的容器,可以定義什麼類型的數據放入容器
  
(2)List<Integer> aList = new ArrayList<Integer>();
   aList.add(new Integer(1));
   // ...
   Integer myInteger = aList.get(0);  //從集合中得到的元素不必強制類型轉換
   支持泛型的集合,只能存放制定的類型,或者是指定類型的子類型。  

   HashMap<String,Float> hm = new HashMap<String,Float>();
  
   不能使用原始類型
   GenList<int> nList = new GenList<int>(); //編譯錯誤
  
   編譯類型的泛型和運行時類型的泛型一定要一致。沒有多態。
   List<Dog> as = new ArrayList<Dog>();
   List<Animal> l = as;  //error  Animal與Dog的父子關係不能推導出List<Animal> 與 List<Dog> 之間的父子類關係
  
(3)泛型的通配符"?"  
   ?   是可以用任意類型替代。
   <?> 泛型通配符表示任意類型
   <? extends 類型>  表示這個類型是某個類型或接口的子類型。
   <? super 類型>    表示這個類型是某個類型的父類型。

  import java.util.*;
  import static java.lang.System.*;
  public class TestTemplate {
 public static void main(String[] args) {
  List<Object> l1=new ArrayList<Object>();
  List<String> l2=new ArrayList<String>();
  List<Number> l3=new ArrayList<Number>();  //Number --- Object的子類,所有封裝類的父類
  List<Integer> l4=new ArrayList<Integer>();
  List<Double> l5=new ArrayList<Double>();
  
  print(l1);
  print(l2);
  print(l3);
  print(l4);
  print(l5);
 }
       static void print(List<? extends Number> l){    //所有Number及其子類 l3,l4,l5通過
  for(Number o:l){
   out.println(o);
  }
 }
       static void print(List<? extends Comparable> l){……}    //任何一個實現Comparable接口的類 l2,l4,l5通過
       static void print(List<? super Number> l){……}          //所有Number及其父類 l1,l3通過
      // "?"可以用來代替任何類型, 例如使用通配符來實現print方法。
       public static void print(GenList<?> list){……} //表示任何一種泛型

  }

(4)泛型方法的定義 --- 相當於方法的模版
  把數組拷貝到集合時,數組的類型一定要和集合的泛型相同。
  <...>定義泛型,其中的"..."一般用大寫字母來代替,也就是泛型的命名,其實,在運行時會根據實際類型替換掉那個泛型。
  在方法的修飾符和返回值之間定義泛型
  <E> void copyArrayToList(E[] os,List<E> lst){……}
  static <E extends Number & Comparable> void copyArrayToList(E[] os,List<E> lst){……}   //定義泛型的範圍 類在前接口在後
  static<E , V extends E> void copyArrayToList(E[] os,List<E> lst){……} //定義多個泛型
  "super"只能用在泛型的通配符上,不能用在泛型的定義上
 
  import java.util.*;
  public class TestGenerics3 {
 public static void main(String[] args) {
  List<String> l1=new ArrayList<String>();
  List<Number> l2=new ArrayList<Number>();
  List<Integer> l3=new ArrayList<Integer>();
  List<Double> l4=new ArrayList<Double>();
  List<Object> l5=new ArrayList<Object>();
  String[] s1=new String[10];
  Number[] s2=new Number[10];
  Integer[] s3=new Integer[10];
  Double[] s4=new Double[10];
  Object[] s5=new Object[10];
  copyFromArray(l1,s1);
  copyFromArray(l2,s2);
  copyFromArray(l3,s3);
  copyFromArray(l4,s4);
  copyFromArray(l5,s5);
  
 }
 //把數組的數據導入到集合中
 public static <T extends Number&Comparable> void copyFromArray(List<T> l,T[] os){
  for(T o:os){
   l.add(o);
  }
 }
  }
 
  受限泛型是指類型參數的取值範圍是受到限制的. extends關鍵字不僅僅可以用來聲明類的繼承關係, 也可以用來聲明類型參數(type parameter)的受限關係.
  泛型定義的時候,只能使用extends不能使用 super,只能向下,不能向上。
  調用時用<?>定義時用 <E>
 
(5)泛型類的定義
  類的靜態方法不能使用泛型,因爲泛型類是在創建對象的時候產生的。
  class MyClass<E>{
 public void show(E a){
  System.out.println(a);
 }
 public E get(){
  return null;
 }
 
  }

  受限泛型
  class MyClass <E extends Number>{
      public void show(E a){

      }
  } 
 
3、註釋(Annotation)
(1)、定義:Annotation描述代碼的代碼(區:描述代碼的文字)
             給機器看         給人看的
(2)、註釋的分類:
  1>、標記註釋:沒有任何屬性的註釋。@註釋名
  2>、單值註釋:只有一個屬性的註釋。@註釋名(value=___)
在單值註釋中如果只有一個屬性且屬性名就是value,則“value=”可以省略。
  3>、多值註釋:有多個屬性的註釋。多值註釋又叫普通註釋。
      @註釋名(多個屬性附值,中間用逗號隔開)
(3)、內置註釋:
  1>、Override(只能用來註釋方法)
   表示一個方法聲明打算重寫超類中的另一個方法聲明。如果方法利用此註釋類型進行註解但沒有重寫超類方法,則編譯器會生成一條錯誤消息。
  2>、Deprecated
用 @Deprecated 註釋的程序元素,不鼓勵程序員使用這樣的元素,通常是因爲它很危險或存在更好的選擇。在使用不被贊成的程序元素或在不被贊成的代碼中執行重寫時,編譯器會發出警告。
  3>、SuppressWarnings(該註釋無效)
指示應該在註釋元素(以及包含在該註釋元素中的所有程序元素)中取消顯示指定的編譯器警告。

(4)、自定義註釋
自定義註釋
    public  @interface Test{
   
    }
    在自定義註釋時,要用註釋來註釋(描述)註釋。
    @target(),用來描述(註釋)註釋所能夠註釋的程序員元素。
    @Retention(),描述(註釋)註釋要保留多久。
    註釋的屬性類型可以是
    8種基本類型
    String
    Enum
    Annotation
    以及它們的數組

(5)、註釋的註釋:java.lang. annotation包中======元註釋
(1)、Target:指示註釋類型所適用的程序元素的種類。
 例:@Target(value = {ElementType.METHOD});
   說明該註釋用來修飾方法。
(2)、Retention:指示註釋類型的註釋要保留多久。如果註釋類型聲明中不存在 Retention 註釋,則保留策略默認爲 RetentionPolicy.CLASS。
例:Retention(value = {RetentionPolicy.xxx}
    當x爲CLASS表示保留到類文件中,運行時拋棄。
   當x爲RUNTIME表示運行時仍保留
   當x爲SOURCE時表示編譯後丟棄。
(3)、Documented:指示某一類型的註釋將通過 javadoc 和類似的默認工具進行文檔化。應使用此類型來註釋這些類型的聲明:其註釋會影響由其客戶端註釋的元素的使用。
(4)、Inherited:指示註釋類型被自動繼承。如果在註釋類型聲
明中存在 Inherited 元註釋,並且用戶在某一類聲明中查詢該註釋類型,同時該類聲明中沒有此類型的註釋,則將在該類的超類中自動查詢該註釋類型。
  注:在註釋中,一個屬性既是屬性又是方法。
 
 ■ 標註:描述代碼的文字
    描述代碼的代碼。給編譯器看的代碼,作用是規範編譯器的語法。
    class Student{
      @Override
      public String toString(){
        return “student”;
      }
   
    }
  ■ 註釋類型 java.lang
    1、標記註釋(沒有屬性)
      @Override
    2、單值註釋
      @註釋名(a="liucy")
      @註釋名(prameter=10)
      int parameter
      特例:
      @註釋名 (value=“134” )
      等價於 @註釋名 (“134” )
    3.普通註釋(多值註釋)
    (key1=value,……)
      @__(a="liucy,b=10)

  ■ @Override 只能放在方法前面
    @Deprecated 用於描述過期
    @SuppressWarnings 抑制警告
          @SuperessWarning({“ddd”,”aaa”,”ccc”})  //JVM還沒有實現這個註釋 
          

4、Java5.0中的併發

 

1>、所在的包:Java.util.concurrent
2>、重寫線程的原因:
(1)何一個進程的創建(連接)和銷燬(釋放資源)的過程都          是一個不可忽視的開銷。
(2)run方法的缺陷:沒有返回值,沒有拋例外。
3>、對比1.4和5.0的線程
       5.0            1.4
ExecutorService       取代 Thread
Callable   Future        取代 Runnable
Lock                           取代 Synchronized
SignalAll                   取代 notifyAll()
await()                       取代 wait()

 

三個新加的多線程包
    

Java 5.0裏新加入了三個多線程包:java.util.concurrent, java.util.concurrent.atomic, 
    
  java.util.concurrent.locks. 
  java.util.concurrent包含了常用的多線程工具,是新的多線程工具的主體。

 

這樣Java創建線程有 3 種方式:
1. 繼承Thread基類。實現run()方法,run()方法就是線程執行流。
    啓動:
    a. 創建Thread子類的對象。
    b. 調用該對象的start()方法來啓動它。
2. 實現Runnable接口。實現run()方法,run()方法就是線程執行流。
    啓動:
    a. 創建Runnable實現類的對象。
    b. 以Runnable實現類的對象作爲target參數,創建Thread對象
    c. 調用Thread對象的start()方法來啓動它。
前面兩種方式的線程執行體(也就是run()方法)不能聲明拋出異常,也不能有返回值。
3. 實現Callable接口(它是Runnable的增強版)。
      實現call()(run()的增強版)方法,call()方法就是線程執行流。
    a. 創建Callable實現類的對象。
    b. 將Callable實現類的對象包裝FutureTask,它代表了call()方法的返回值將來纔會返回。
    c. 以FutureTask的對象作爲target參數,創建Thread對象
    d. 調用Thread對象的start()方法來啓動它。

實現Runnable接口和實現Callable接口本質相同,
通常我們認爲通過實現實現Runnable接口或實現Callable接口的多線程實現方式比較理想。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章