1. 程式人生 > >javaSE泛型——新特性、泛型

javaSE泛型——新特性、泛型

一、新特性
java之所以可以一直穩居在程式語言的前列,是因為它不是已成不變的,java的每一個版本都會有新特性,我們主要需要掌握以下幾個版本的新特性:
JDK1.2:推出了輕量級的介面包:Swing
JDK1.5:推出新程式結構的設計思想
JDK1.8:Lambda表示式、介面定義加強
1.可變引數
我們來看這樣的一個例子:
要求設計一個方法,用於計算任意引數整數相加的結果,對於不同的引數進行相加,我們一起拿在編寫函式的時候是通過方法過載的方法來實現的,但是我們知道這樣是有弊端的,因為你不到使用者到底需要進行多少個數相加,你只能將所有的情況都考慮一遍,顯然這是不可能的,所以我們希望我們的方法可以實現任意個數進行相加。所以就有了我們的可變引數:
可變引數的定義格式:
public [static] [final] 返回值 方法名稱 ([引數型別 引數名稱] [引數型別 … 引數名稱]){ }
這個引數上使用的"…"實際上表示一個數組的結構。
例子:

package com.wschase.xintexing;

/**
 * Author:WSChase
 * Created:2018/12/10
 */
public class TestXin {
    public static void main(String[] args) {
        //1.方法的可變引數
        System.out.println(add(1,4,5,6));
        System.out.println(add(new int[]{1,2,3}));
        System.out.println(add(new int[]{1,2,3,4,5,6}));
    }

    private static int add(int ... data) {//其實可變引數本質上還是陣列
        int result=0;
        //正是因為可變引數的本質還是陣列,所以我們下面的處理還是用陣列來處理的
        for(int i=0;i<data.length;i++){
            result +=data[i];
        }
    return result;
    }
}

注意:需要傳遞多類引數的時候,可變引數一定要放在最後,並且在一個方法裡面我們只能設定一個可變引數。
例子:傳遞多了類可變引數

     //2.傳遞多類引數
    public static int add(String msg,int ... data){
        int result=0;
        for(int i=0;i<data.length;i++){
            result +=data[i];
        }
        return result;
    }
        public static void main(String[] args) {
//        //2.傳遞多類引數
        System.out.println(add("hello"));
        System.out.println(add("hello",1,4,5));
        System.out.println(add("he",new int[]{1,2,3}));
    }

}

2.foreach迴圈
foreach迴圈格式:
for(資料型別 臨時變數 : 陣列(集合)){
//迴圈次數為陣列長度,而每一次迴圈都會順序取出陣列中的一個元素賦值給臨時變數
}
例子:

//2.foreach迴圈
public class TestXin{
    public static void main(String[] args) {
        int[] data=new int[]{1,2,3,4,5};
        for(int i:data){//在這是將陣列中元素的值賦給了臨時變數i
            System.out.println(i);//在這我們使用陣列中與那素賦值直接使用臨時變數賦值就可以了
        }
    }
}

從上面我們可以看到,foreach迴圈的使用比較方便,但是它也有一個缺點就是當我們需要索引取得陣列中的元素值的時候這個就不可以了,我們得單獨用一個變數來自增進行。但是如果我們姿勢給陣列中元素進行整體賦值或者整體取得陣列中的元素的時候我們使用foreach迴圈比較好。
3.靜態匯入
就是在一個類裡面是static修飾的方法,在另外一個類裡面使用的時候我們直接用方法名使用,這個時候就需要我們用靜態匯入的方法將這個靜態方法從一個類裡面匯入到另外一個類中。
二、泛型
從JDk1.5以後引入了三大常用新特性:泛型、列舉、註解。後面的兩種我們在前面已經學習過了,這個泛型主要是為了解決程式引數轉換的問題。
1.為什麼會出現泛型?
當我們的一個方法要接收不同型別的引數的時候,我們需要定義的這個型別得是Object,但是最後我們都需要通過強制型別轉換來實現。泛型就是為了解決這一類問題。
2.泛型的格式
(1)泛型類的基本語法
class MyClass{
T value1;
}
這裡尖括號<>中的T表示型別引數,可以用於指代任何型別。實際上這個T可以是任意的,但是我們為了規範問題,還是用引數型別的首字母表示。常見的如下:
T:表示一般的任何類
E: 白哦是Element的意思,或者Exception異常的意思
K:表示Key的意思
V:表示Values的意思,通常與K一起使用
S:表示Subtype的意思
(2)泛型類定義:如果一個類被的形式定義了,那麼它就被稱為泛型類。定義泛型類之後的使用:

MyClass<String> myClass1=new MyClass<String>();
MyClass<Integer> myClass2=new MyClass<Integer>();

注意1:泛型只能接受類,所有的基本資料型別必須使用包裝類。
注意2:泛型類裡面的屬性的型別必須是我們泛型當中規定的型別。
泛型類引入多個型別引數以及使用

class MyClass<T,E>{
T value1;
E value2;
}
public class Test{
public static void main(String[] args){
MyClass<String,Integer> myClass = new MyClass<String,Integer>();
      }
}

(3)泛型方法
語法:

class MyClass{
public <T> void testMethod(T t){
System.out.println(t);
}
}

使用型別引數做返回值的泛型方法:

//3.使用型別引數做返回值的泛型方法
class MyClass{
    public <T> T testMethod(T t){
        return t;
    }
}

注意:在泛型方法裡面,如果表示引數型別的得在方法返回值的前面有一個對應的<>裡面是引數型別。
(4)泛型方法和泛型類是共存的

//4.泛型方法和泛型類是共存的
class MyClass<T> {
//泛型類中的普通方法
    public void testMethod1(T t) {
        System.out.println(t);
    }
//泛型類中的泛型方法
    public <T> T testMethod2(T t) {
        return t;
    }
}
public class TestXin{
    public static void main(String[] args) {
        MyClass<String> myClass= new MyClass<>();//在後面這個<>裡面可以不要引數型別
        myClass.testMethod1("這是泛型類中的泛型方法");
        Integer i=myClass.testMethod2(100);
        //由於上面傳入的是100,所以返回的型別T也就是100了。
        System.out.println(i);
    }
}

上面泛型的型別容易混淆,所以為了區分我們對於泛型類的型別和泛型方法中的型別使用不同的型別進行泛型處理:

class MyClass<T> {
//泛型類中的普通方法
    public void testMethod1(T t) {
        System.out.println(t);
    }
//泛型類中的泛型方法
   public <E> E testMethod2(E e) {
        return e;
    }
}
public class TestXin{
    public static void main(String[] args) {
        MyClass<String> myClass= new MyClass<>();//在後面這個<>裡面可以不要引數型別
        myClass.testMethod1("這是泛型類中的泛型方法");
        Integer i=myClass.testMethod2(100);
        //由於上面傳入的是100,所以返回的型別T也就是100了。
        System.out.println(i);
    }
}

3.泛型的幾種情況
(1)泛型類裡面只有普通方法
(2)普通類裡面只有泛型方法
(3)泛型類裡面既有泛型方法又有普通方法

//泛型的幾種情況
//    3.泛型的幾種情況
//            (1)泛型類裡面只有普通方法
    class Person<T>{
        private T name;
        private T age;
        //泛型類中沒有引數的普通方法
        public void getInfo(){

        }
        //泛型類中有引數的普通方法
        public void fun(T t){
            System.out.println("t="+t);
        }
}
//            (2)普通類裡面只有泛型方法
    class Person1{
        private String name;
         private int age;
         //普通類中的泛型方法:注意泛型方法是需要在返回值型別前面有型別宣告(佔位)的
    public <E> void fun1(E e){
        System.out.println("e="+e);
    }
         //普通類中有返回值的泛型方法
    public <E> E fun2(E e){
        return e;
    }

}
//            (3)泛型類裡面既有泛型方法又有普通方法
class Person3<T>{
        private T name;
        private T age;
    //下面這些都是普通方法
    public Person3(T name) {
        this.name = name;
    }

    public Person3(T name, T age) {
        this.name = name;
        this.age = age;
    }

    public T getName() {
        return name;
    }

    public void setName(T name) {
        this.name = name;
    }
    //泛型方法
    public <E> void fun1(E e){
        System.out.println("e="+e);
    }
    //注意:下面的這個方法返回型別和傳參型別之所以一樣,是因為返回值型別是由傳遞的引數型別決定的,這樣的話型別肯定是一樣的。
    public <E> E fun2(E e){
        return e;
    }
}
public class TestXin{
    public static void main(String[] args) {

    }
}