JDK1.5java新特性

JDK1.5java增加的新特性:

   自动装箱/拆箱      增强for     泛型      枚举      静态导入      可变参数

1 自动装箱/拆箱

* JDK1.5允许开发人员把一个基本类型直接赋给对应的包装类变量或者赋给Object类型的变量,这个过程称为自动装箱。

* 自动装箱和自动拆箱相反,即把包装类对象直接赋给一个对应的基本类型变量。

也就是基本类型与其对应的引用类型之间的转换,但是不能乱用,一般我们要采用基本类型,如果在使用时不注意,可能会造成程序低效率运行。

int ----- Integer
float ----- Float
double ---- Double
char ------- Character
boolean ---- Boolean
short ---- Short
long ---- Long
byte ---- Byte

比如:

Long  sum = 0;

for(long i =0;i<10000;i++){

  sum += i;

}

此处造成程序低效率就在于频繁的进行拆箱装箱操作。注意sum被定义成了Long而不是long。

还有两个高精度的类

  BigInteger

  BigDecimal


 

2 增强for

优缺点:

  优点:遍历更简单,在集合遍历中增强for就是代替迭代器的

  弊端:增强for的目标不能为null(即数组或集合不能为null),所以在遍历之前需要进行判断

格式:

  for(元素数据类型 变量:数组或集合){

      ....................................
      使用变量,该变量就是集合或者数组中的元素
  }

举例:

String[]  names = {"小明","小李","小王"};

for(String  name : names){

   System.out.println("hello "+name);

}


 

3 泛型

引入泛型的好处:

     1)去除了原先必须的冗长的强制类型转换

     2)能够在编译期检测出错误,不至于在运行时才发现,消除了潜在的错误,提高代码运行的可靠性。

     3)使用XJad.exe反编译工具可以看到,在编译期间泛型被擦除。

泛型基本应用:

1)泛型类

*把泛型定义在类上

*格式:public class 类名<泛型类型1.....>

*注意:泛型类型必须是引用类型

2)泛型方法

* 把泛型定义在方法上:方法可以接收任意类型

* 格式:public<泛型类型> 返回类型 方法名(泛型类型)

3)泛型接口

* 把泛型定义在接口上

* 格式:public interface 接口名<泛型类型1.....>

例1:一个简单的泛型类

package basic.demo;

public class FanTypeClass<T>{
  private T obj;

  public T getObj() {
    return obj;
  }

  public void setObj(T obj) {
    this.obj = obj;
  }
}

测试类:

package basic.demo;

public class FanTypeDemo {
  public static void main(String[] args) {

    FanTypeClass<String> obj1 = new FanTypeClass<String>();  //使用泛型
    obj1.setObj("hello");   //这时候set方法接收的参数必须是String,如果不传该类型,在编译期就会报错
    String s = obj1.getObj();  //这种方式下不需要强转
    System.out.println(s);

    FanTypeClass obj2 = new FanTypeClass();  //没使用泛型
    obj2.setObj(3);
    int num = (int) obj2.getObj();          //需要进行强转,如果不小心写错了就会产生ClassCastException,即类型转换异常

    String num = (String)obj2.getObj();    //这样写在编译期并不会报错,但是一旦执行就会产生类型转换异常
    System.out.println(num);
  }
}

例2:泛型方法的使用

package basic.demo;

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

测试类:

package basic.demo;

public class FanTypeDemo {
  public static void main(String[] args) {

    FanTypeMethod ft = new FanTypeMethod();
    ft.show("hello");
    ft.show(100);
    ft.show(true);

  }

}

输出结果:

hello

100

true

例3 泛型接口

分为两种用法:子类实现时已知将来使用类型和子类实现时未知使用类型(这一种常见)

package basic.demo;

public interface FanTypeInter<T>{
  public abstract void show(T t);
}

package basic.demo;   //子类未知要使用的类型,故还是用泛型T

public class FanTypeInterImpl<T>  implements FanTypeInter<T> {
  @Override
  public void show(T t) {
    System.out.println(t);
  }
}

测试:

package basic.demo;

public class FanTypeDemo {
  public static void main(String[] args) {
    FanTypeInter<String> fti1 = new FanTypeInterImpl<String>();
    fti1.show("hello");

    FanTypeInter<Integer> fti2 = new FanTypeInterImpl<Integer>();
    fti2.show(100);

  }

}

泛型高级应用(通配符):

1)泛型通配符 <?>

  *任意类型,如果没有明确,那么就是Object以及任意的java类

2)? extends E

  * 向下限定,E及其子类

3)? super E

  * 向上限定,E及其父类

例:理解高级应用:红色标注皆为错误用法

package basic.demo;

import java.util.ArrayList;
import java.util.List;

public class FanTypeSeniorDemo {
  public static void main(String[] args) {
    //泛型如果明确写,必须前后一致
    // List<Object> list1 = new ArrayList<Object>();
    // List<Object> list2= new ArrayList<Person>(); //error
    // List<Object> list3 = new ArrayList<Student>(); //error
    // List<Object> list4 = new ArrayList<Teacher>(); //error


    //?表示任意类型都是可以的
    // List<?> list1 = new ArrayList<Object>();
       // List<?> list2= new ArrayList<Person>();
    // List<?> list3 = new ArrayList<Student>();
    // List<?> list4 = new ArrayList<Teacher>();


    //? extends E 向下限定:E及其子类
    // List<? extends Person> list1 = new ArrayList<Object>(); //error
    // List<? extends Person> list2= new ArrayList<Person>();
    // List<? extends Person> list3 = new ArrayList<Student>();
    // List<? extends Person> list4 = new ArrayList<Teacher>();


    //? super E 向上限定 E及其父类
    List<? super Person> list1 = new ArrayList<Object>();
    List<? super Person> list2= new ArrayList<Person>();
    List<? super Person> list3 = new ArrayList<Student>(); //error
    List<? super Person> list4 = new ArrayList<Teacher>(); //error

  }

}
class Person{

}
class Student extends Person{

}
class Teacher extends Person{

}


 

4 枚举

 关键字Enum,用于定义一个枚举类

 为什么需要枚举?
一些方法在运行时,它需要的数据不能是任意的,而必须是一定范围内的值,此类问题在JDK5以前采用自定义带有枚举功能的类解决,Java5以后可以直接使用枚举予以解决。

枚举类具有如下特性
  枚举类也是一种特殊形式的Java类。
  枚举类中声明的每一个枚举值代表枚举类的一个实例对象。
  与java中的普通类一样,在声明枚举类时,也可以声明属性、方法和构造函数,但枚举类的构造函数必须为私有的(这点不难理解)。
  枚举类也可以实现接口、或继承抽象类。
  JDK5中扩展了switch语句,它除了可以接收int, byte, char, short外,还可以接收一个枚举类型。
  若枚举类只有一个枚举值,则可以当作单例设计模式使用。

Java中声明的枚举类,均是java.lang.Enum类的子类,它继承了Enum类的所有方法。

常用方法:
  name():返回此枚举常量的名称,在其枚举声明中对其进行声明。
  ordinal():返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。也可以称为索引
  valueOf(Class enumClass, String name)
  values()     此方法虽然在JDK文档中查找不到,但每个枚举类都具有该方法,它遍历枚举类的所有枚举值非常方便。


 

5 静态导入

可以直接导入到方法的级别。

格式:import static 包名....类名.方法名;

注意:

  *方法必须是静态的

  *如果有多个同名的静态方法,容易不知道使用谁??这个时候要使用该特性,需要加前缀。由此可见,意义不大。所以一般不用,仅需知道就行。

例1:使用静态导入,使用静态方法时直接使用。

package basic.demo;

import static java.lang.Math.max;
import static java.lang.Math.min;

public class StaticImportDemo {
  public static void main(String[] args) {

    int num1 = 23;
    int num2 = 30;

    max(num1,num2);
    min(num1,num2);
  }
}

例2:编写重名的静态方法,然后一起在StaticImportDemo使用:

package basic.demo;

public class MyMath {
  public static int max(int num1,int num2){
    return num1>num2?num1:num2;
  }

  public static int min(int num1,int num2){
    return num1>num2?num2:num1;
  }
}

package basic.demo;

import static java.lang.Math.max;
import static java.lang.Math.min;

import static basic.demo.MyMath.max;
import static basic.demo.MyMath.min;  //使用都加前缀了,也就不需要静态导包了


public class StaticImportDemo {
  public static void main(String[] args) {

    int num1 = 23;
    int num2 = 30;

    java.lang.Math.max(num1,num2);  //必须加包名前缀,否则报错
    basic.demo.MyMath.min(num1,num2);//必须加包名前缀,否则报错,但是这样一加前缀就没有导包的意义了。。。。。
  }
}


 

6 可变参数

Effective Java不建议使用该特性,而且在java编程思想中也说了此特性的隐患。

 *定义方法的时候不知道定义多少个参数,故引入可变参数的概念。

使用格式:

  * 修饰符  返回值类型  方法名(数据类型...变量名){}

注意:

 * 这里的变量其实是一个数组

   *如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个,否则编译器报错。

举例:

  *Arrays工具类中的一个方法:

  public static <T>List<T> asList(T...a)

例1:简单使用:

package basic.demo;
public class ChangeParaDemo {
  public static void main(String[] args) {
    int[] data = {1,2,3,4};
    System.out.println(sum(data));

    int sum = sum(2,3,4,5);
    System.out.println(sum);

    sum = sum(2,5);
    System.out.println(sum);
  }

  private static int sum(int...num) {
    int result = 0;
    for(int i:num){
      result += i;
    }
    return result;
  }
}

例2 方法中有多个参数:java在编译器期间就强调可变参数必须在最后的位置。

package basic.demo;
public class ChangeParaDemo {
  public static void main(String[] args) {
    int sum = sum(100,1,2,3,4);
    System.out.println(sum);       //如果把可变参数放在方法参数的最后,结果是10

    int sum = sum(1,2,3,4,100);

    System.out.println(sum);   //如果可变参数放在前面,会报错
  }

  private static int sum(int special,int...num) {
    int result = 0;
    for(int i:num){
      result += i;
    }
    return result;
  }

  //error: 错误写法

  //出错原因,因为可变参数变量其实是一个数组,如果把可变参数放在前面,则special变量被视为数组的一部分,也就是说你只传了一个参数,和原方法参数个数不一致

  private static int sum(int...num,int special) {
    int result = 0;
    for(int i:num){
      result += i;
    }
    return result;
  }

}

 


 

posted @ 2016-09-24 21:39  zwbg  阅读(277)  评论(0编辑  收藏  举报