java学习笔记(九)-- java新特性 ( 可变参数 & 泛型 & 静态导入 & 类型擦除 )

JDK1.5新特性

  • 方法的可变参数

            设计一个方法,可以接收任意个数的整数,并返回他们的相加结果

            早期实现方式:

public class Test {
    public static void main(String[] args) {
        System.out.println(add(new int[]{1,2,3}));
        System.out.println(add(new int[]{1,2,3,4,5,6}));
        System.out.println(add(new int[]{1,2,3,4,5,6,7,8,9}));
    }
    public static int add(int []data){
        int result=0;
        for(int temp:data){
            result+=temp;
        }
        return result;
    }
}

            可变参数列表实现:

public class Test {
    public static void main(String[] args) {
        //可以直接接受内容
        System.out.println(add(1,2,3));
        //可变参数列表可以接受数组
        System.out.println(add(new int[]{1,2,3,4,5,6}));
        System.out.println(add(new int[]{1,2,3,4,5,6,7,8,9}));
    }
    public static int add(int ... data){
        int result=0;
        for(int temp:data){
            result+=temp;
        }
        return result;
    }
}

           可变参数--语法

            数据类型 ··· 可变参数名称

            int  ···  data 

            可变参数的本质还是数组

            一个方法中只允许一个可变参数,并且可变参数一定是方法最后一个参数,由于可变参数中传递参数的数量是未知的,所以一个方法中最多只能存在一个可变参数列表,而且当存在多类参数时,可变参数放在方法最后

public class Test {
    public static void main(String[] args) {
        //可以直接接受内容
        System.out.println(add("Hello world",1,2,3));
        //可变参数列表可以接受数组
        System.out.println(add("Hello world",new int[]{1,2,3,4,5,6}));
        System.out.println(add("Hello world",new int[]{1,2,3,4,5,6,7,8,9}));
    }
    public static int add(String msg,int ... data){
        int result=0;
        for(int temp:data){
            result+=temp;
        }
        return result;
    }
}
  • foreach循环  只用于数组,类集内容的取得,不能修改原数组,类集内容。

            for(数据类型 临时变量:数组名/类集名)

            for(int temp:data)

  • 静态导入   import  static  (了解,不使用)

            将一个类的所有静态域(包括静态属性,方法)

            全部导入的使用类中,此时调用属性和方法不再需要类名。

范例:定义一个util类

package www.Dyson.java;
public class util {
    public static int add(int n,int m){
        return m+n;
    }
    public static int sub(int n,int m){
        return n-m;
    }
}

范例:使用util方法,直接同过类名去调用

package www.Dyson.java;
import www.Dyson.java.util;
public class Test {
    public static void main(String[] args) {
        System.out.println(util.add(1,5));
        System.out.println(util.sub(5,1));
    }
}

范例:静态导入,不需要通过类名去调用

package www.Dyson.java;
import static www.Dyson.java.util.*;
public class Test {
    public static void main(String[] args) {
        System.out.println(add(1,5));
        System.out.println(sub(5,1));
    }
}
  • 泛型  (出于安全性考虑,不再有类型转换异常)解决类型转换异常 ClassCastException  Java语法糖

            1. 泛型类;所谓的泛型指在类定义的时候并不会设置类中属性或方法的参数的具体类型,而是在类使用的时候在定义

            泛型类的定义

            语法:

class  Myclass<T>{
      T t;
}

<>中的T被称为参数类型,用于指代任何类型。处于规范起见类型参数一般由单个大写字母表示。

            T:用于泛型声明上,指代泛型类;

            E:一般用于属性

            K,V:键值对

            当泛型类中需要多个不同类型变量时,<>以,分隔声明不同大写字母即可

class MyClass <T,E>{
    T t;
    E e;
}

            泛型的出现彻底解决了向下转型带来的ClassCastException异常

            泛型只能使用引用类型,基本类型使用包装类

范例:使用泛型类

Myclass<String> myClass1 = new MyClass<String>();
MyClass<Integer> myClass = new MyClass<Integer>();

使用范例:

package www.Dyson.java;
class Point<T>{
    private T x;
    private T y;
    public T getX() {
        return x;
    }
    public T getY() {
        return y;
    }
    public void setX(T x) {
        this.x = x;
    }
    public void setY(T y) {
        this.y = y;
    }
}
public class Test {
    public static void main(String[] args) {
        Point<String> p=new Point<String>();
        p.setX("东经20度");
        p.setY("北纬40度");
        //避免了向下转型
        String x=p.getX();
        String y=p.getY();
        System.out.println("x="+x+" y="+y);
    }
}

            2. 泛型方法

            语法:

            泛型方法   返回值   参数

public <T> void method ( T  t ) {

}

            当泛型类与泛型方法共存时,泛型方法中的类型参数与泛型类的类型参数无关,泛型方法始终以自己的类型参数为准。

            规范起见,当泛型类与泛型方法共同使用时,请使用不同的参数类型来区别彼此。

class MyClass<T>{
    public void testMethod1(T t){
        System.out.println(t);
    }
    public <E> E testMethod2(E e){
        return e;
    }
}

                3 通配符   <******* 重点 *******>  面试考点

                3.1. ?通配符--作用于方法参数声明

                public static void print(MyClass<?> myClass);

                此时方法可以接收任何类型的Myclass对象

                由于无法确定入参类型,因此?通配符下的泛型参数,只能取得类中属性值,无法进行属性值的修改

public class TestDemo {    
    public static void main(String[] args) {        
        Message<Integer> message = new Message() ;         
        message.setMessage(55);        
        fun(message);    
    }    
    // 此时使用通配符"?"描述的是它可以接收任意类型,但是由于不确定类型,所以无法修改    
    public static void fun(Message<?> temp){         
        //temp.setMessage(100); 无法修改!        
        System.out.println(temp.getMessage());  
    }  
}

                3.2.设置泛型的上限--用于泛型类的声明,也可用于方法参数

                泛型类声明:T extends 类 (T <= 类)

                方法参数:?extends 类

                eg:?extends Number;

                表示方法入参只能接收Number以及子类对象

                方法参数设置泛型上限仍然只能取得类中属性值,而无法设置,因为设置父类值子类不一定能使用(父类不一定能发生向下转型变为子类)。

package www.Dyson.java;
class Message<T extends Number> {
    // 设置泛型上限
    private T message ;
    public T getMessage() {
        return message;
    }
    public void setMessage(T message) {
        this.message = message;
    }
}
public class Test {
    public static void main(String[] args) {
        Message<Integer> message = new Message();
        message.setMessage(55);
        fun(message);
    }
    // 此时使用通配符"?"描述的是它可以接收任意类型,但是由于不确定类型,所以无法修改
    public static void fun(Message<? extends Number> temp) {
        //temp.setMessage(100); 仍然无法修改!
        System.out.println(temp.getMessage());
    }
}

                3.3. 设置泛型下限--只能用于方法参数

                ?super 类(>= 类)

                表示方法入参只能接收类以及其父类对象

                只有super可以设置属性值,天然的向下转型,不能使用extends类设置属性值,因为不确定其子类类型

                方法参数设置泛型下限,不仅可以取得类中属性值,还可以设置属性值。因为子类可以天然的向上转型变为父类。

package www.Dyson.java;
class Message<T> {
    private T message ;
    public T getMessage() {
        return message;
    }
    public void setMessage(T message) {
        this.message = message;
    }
}
public class Test {
    public static void main(String[] args) {
        Message<String> message = new Message() ;
        message.setMessage("Hello World");
        fun(message);
    }
    public static void fun(Message<? super String> temp){
        // 此时可以修改!!
        temp.setMessage("bit!");
        System.out.println(temp.getMessage());
    }
}

                4. 泛型接口

                定义一个泛型接口

interface Imessage<T>{
    public void print(T t);
}

               1. 子类实现接口时继续保持泛型

Class MessageImp<T> implements IMessage<T>{

    public void print(T t){

        System.out.println(t);

    }
}

               2. 子类实现接口时就确定好类型

Class MessageImp<String> implements IMessage<T>{

    public void print(Strig t){
        System.our.println(t);

    }
}

                5. 类型擦除   <***** 重要 *****>  面试考点 贼重要  在JVM眼中就不存在泛型,都是确定指定类型

                便编译信息仅存在代码编译阶段,进入JVM之前,与泛型相关的信息会被擦除掉,专业术语就叫类型擦除

                换句话说,泛型类与普通类在JVM中没有任何区别

                泛型类进入JVM之前,会进行类型擦除,泛型类的类型参数如果没有指定类型上限,则擦除成为Object类;如果类型参数指定类型上限,擦除为相应类型上限

                <T> -> Object

                <T extends String> -> String

猜你喜欢

转载自blog.csdn.net/ds19980228/article/details/83750824