java基础加强--JDK1.5新特性

来源:互联网 发布:软件测试工资待遇2015 编辑:程序博客网 时间:2024/05/17 20:40

笔记摘要:

     这里主要介绍了JDK1.5的一些新特性:静态导入、可变参数、增强for循环、基本数据类型的自动装箱与拆箱以及枚举和注解。

     其中的自动装箱与拆箱涉及到了享元模式,另外的一个新特性:泛型,由于内容过多,单独成篇。


一、静态导入

      1、import语句可以导入一个类或某个包中的所有类

      2、import static语句导入一个类中的某个静态方法或所有静态方法

      3、语法举例:

              import staticjava.lang.Math.sin;

              import static java.lang.Math.*; 


二、可变参数

   1、   问题:一个方法接受的参数个数不固定,例如:

           System.out.println(countScore(2,3,5));

           System.out.println(countScore(1,2,3,5));     

   2、   可变参数的特点:

         1>  只能出现在参数列表的最后;这个要记住

         2> "..."位于变量类型和变量名之间,前后有无空格都可以;

         3>  调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。


可变参数示例  

package cn.xushuai.Test;public class VariableArgs {public static void main(String[] args) {System.out.println(add(1,2,3,4));System.out.println(add(1,4));}public static int add(int x,int ...args){int sum = 0;for(int i=0;i<args.length;i++){sum+= args[i];}return sum;}}

四、增强for循环

    1、    语法:

              for ( type 变量名:集合变量名 )  { … }

    2       注意事项:

           迭代变量必须在( )中定义!

          集合变量可以是数组或实现了Iterable接口的集合类


举例: 

public static int add(int x,int ...args) {int sum = x;for(int arg:args) {sum += arg;}return sum;}


五、基本数据类型的自动拆箱与装箱

  

    1、自动装箱:

          Integer num1 = 12;

    2、自动拆箱:

          System.out.println(num1 + 12);

    3 、基本数据类型的对象缓存:

Integer num1 = 12;Integer num2 = 12;这里相等,-128----127之间时,会使用同一个对象System.out.println(num1 == num2);Integer num3 = 129;                这里不相等,因为是不同的对象Integer num4 = 129;System.out.println(num3 == num4);//falseInteger num5 = Integer.valueOf(12);Integer num6 = Integer.valueOf(12)  ;   这块的道理同上System.out.println(num5 == num6);//true

  4、享元模式(flyweight):

    有很多个小的对象,它们有很多属性相同,又频繁使用,这时把它们变成一个对象,将该对象缓存起来。将那些不同的属性变成方法的参数,称之

    为外部状态,那些相同的属性叫做内部状态


六、 枚举


1,. 为什么要枚举?

    枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就会报错,枚举可以让编译器在编译时间就可以控制源程序中填写的

    非法值,普通变量的方式在开发阶段无法实现这一目标。

例如:

    要定义星期几或性别的变量,该怎么定义?假设用1-7分别表示星期一到星期日,但有人可能会写成int weekday = 0;或即使使用常量方式也无法阻止意外。


 2 、枚举的特性

      1> 枚举也是一种特殊形式的java类

       2> 枚举类中声明的每一个枚举值就代表枚举类的一个实例对象,

         例如可以调用WeekDay.SUN.getClass()getName(),和WeekDay.class.getName(),并且已经覆盖了toString()方法。

      3> 枚举的构造函数必须是私有的,而且枚举列表要放在最上面,且末尾必须是';’

      4> 与java中的普通类一样,在声明枚举时,也可以声明属性、构造函数、成员变量、普通方法和抽象方法, 枚举也可以实现接口,或继承抽象类。

      5> JDK5中扩展了switch语句,它除了可以接收int,byte,char,short类型外,还可以接收一个枚举类型。

      6> 若枚举只有一个枚举值,则可以当做单例设计模式使用。(作为单例模式的补充)

          enumA{  A; },枚举的单例模式避免了lazy Loader单例模式中的double check locking,并且传统的单例如果序列化,则就不再是单例了。而枚举会仍保持其单例特性。

       具体可以参考:http://www.importnew.com/6461.html


3、带有构造方法的枚举:

        1>  构造方法必须是定义为私有的,如果有多个构造方法。

        1>  枚举元素MON和MON()的效果一样,都是调用默认的构造方法

        3>  在枚举值后面加个括号就可以调用指定的构造函数

public enum WeekDay{  SUN(),MON(1),TUE(2),WED,THU,FRI,SAT ;  private WeekDay()  {  System.out.println("first");  }  private WeekDay(int day)  {  System.out.println("Second");  }  }  


4. 枚举的常用方法

     name() , ordinal()  valueOf(Class enumClass,String name)将字符串转化为对应的枚举值

     values() : 此方法虽然在JDK文档中查不到,但是每个枚举类都具有该方法,它用于遍历 枚举的所有枚举值


常用方法示例:

package cn.xushuai.test;public class EnumTest {public static void main(String[] args) {WeekDay weekday = WeekDay.MON;System.out.println(weekday);//MONSystem.out.println(weekday.name());//MONSystem.out.println(weekday.ordinal());//1,枚举的位置System.out.println(WeekDay.valueOf("SUN"));//SUN,将字符串转成对应的枚举元素System.out.println(WeekDay.valueOf("SUN").toString());//SUN,返回枚举常量的名称System.out.println(WeekDay.values());//枚举元素的数组}public enum WeekDay{SUN,MON,TUE,WED,THU,FRI,SAT;}}


5、用普通类如何实现枚举功能,定义一个Grade的类来模拟枚举功能

星期的枚举类示例:

  1> 私有构造方法

  2> 每个元素分别用一个公有的静态成员表示(可以通过内部类实现抽象方法来返回自己 类型的的实例对象)

  3> 可以有若干个公有方法或抽象方法


例如:

    我们在周一至周日的枚举中,在返回值的时候要在nextDay()方法中进行大量的if-else判断,这样显得太冗杂,这时我们可以 把nextDay()方法

    定义为抽象的,只要我们在每一个nextDay()方法中进行不同的实现,就可以将大量的if else语句转换成了 一个个独立的类,就像下面的getGrade()方法一样。


public abstract class Grade {            private Grade(){}         public abstract Grade getGrade();            public static final Grade  A = new Grade(){          public Grade getGrade(){              return A;          }      };      public static final Grade  B = new Grade(){          public Grade getGrade(){              return B;          }      };      public static final Grade  C = new Grade(){          public Grade getGrade(){              return C;          }      };      public String toString(){              if(this==A){                  return "90-100";              }              if(this==B){                  return "80-90";              }              if(this==C){                  return "70-80";              }      return null;      }      }      public class Enum {                    public static void main(String[] args){              Grade ClassA = Grade.A;              Grade ClassB = Grade.B;          Grade ClassC = Grade.C;     System.out.println(ClassA.getGrade());          System.out.println(ClassB.getGrade());      System.out.println(ClassC.getGrade());      }  

6、带有抽象方法的枚举

定义枚举TrafficLamp

   1、实现抽象的nextLamp方法:

   2、每个元素分别是由枚举类的子类来生成的实例对象,这些子类采用类似内部类的方式进行定义,并在元素后面的括号中指定参数去调用指定的构造方法


  类的方法返回的类型可以是自己这个类型,类里面可以定义静态常量,常量指向的结果就是自己的实例对象


    public enum TrafficLamp{          RED(30){              public TrafficLamp nextLamp(){                  return YELLOW;              }          },          YELLOW(10){          public TrafficLamp nextLamp(){          return GREEN;          }      },      GREEN(45){          public TrafficLamp nextLamp(){          return RED;          }      };      public abstract TrafficLamp nextLamp();      private int time = 0;      private TrafficLamp(int time){this.time = time;}      public int  getTime(){          return this.time;          }      }  

七、注解

        相当于一种标记,在程序中加了注解就相当于为程序打了某种标记,以后,javac编译器开发工具和其他程序可以用反射来了解你的类及各种

        元素上有无何种标记。按照标记采取相应的措施,标记可以加在包,类,字段,方法的参数及局部变量上

 

7.1注解的应用结构图


7.2注解中需要用到的类


1、注释类型 Retention

    指示注释类型的注释的生存周期。如果注释类型声明中不存在 Retention 注释,默认为 RetentionPolicy.CLASS。

    其三种取值:RetentionPolicy.CLASS、RetentionPolicyRUNTIME.、RetentionPolicy.SOURCE

    分别对应:    java源文件------>class文件-------->内存中的字节码

 

2、注释类型 Target

    指示注释类型所适用的程序元素的种类。如果注释类型声明中不存在 Target 元注释,则声明的类型可以用在任一程序元素上。如果存在这样的元注释,

    则编译器强制实施指定的使用限制。例如,此元注释指示该声明类型是其自身,即元注释类型。它只能用在注释类型声明上:


7.3、为注解添加属性


1、  什么是注解的属性

       一个注解相当于一个胸牌,如果你胸前贴了胸牌,就是某个学校的的学生,否则,就不是。如果还想区分出是哪个班的学生,这时候可以为胸牌在

      增加一个属性来进行区分。加了属性的标记效果为:@MyAnnotation(color="red")


2、  定义基本类型的属性和应用属性:

       在注解类中增加Stringcolor();

       @MyAnnotation(color="red")


3、  用反射方式获得注解对应的实例对象后,再通过该对象调用属性对应的方法

       MyAnnotation a =(MyAnnotation)AnnotationTest.class.getAnnotation(MyAnnotation.class);

       System.out.println(a.color());

       可以认为上面这个@MyAnnotation是MyAnnotaion类的一个实例对象


4、  为属性指定缺省值:

       String color()default "yellow";


5、  value属性:

       String value()default "zxx";

       如果注解中有一个名称为value的属性,且你只想设置value属性(即其他属性都采用默认值或者你只有一个value属性),

       那么可以省略value=部分,例如:@MyAnnotation("lhm")。


7.4、为注解添加高级属性


1、  数组类型的属性

      int [] arrayAttr()   default {1,2,3};

      @MyAnnotation(arrayAttr = {2,3,4})

      如果数组属性中只有一个元素,这时候属性值部分可以省略大括


2、  枚举类型的属性

      EnumTest.TrafficLamp lamp() ;

      @MyAnnotation(lamp  =  EnumTest.TrafficLamp.GREEN)


3、  注解类型的属性:

      MetaAnnotation annotationAttr()  default @MetaAnnotation("xxxx");

      @MyAnnotation(annotationAttr = @MetaAnnotation(“yyy”) )

      可以认为上面这个@MyAnnotation是MyAnnotaion类的一个实例对象,同样的道理,可以认为上面这个@MetaAnnotation是MetaAnnotation类的

      一个实例对象,调用代码如下:

       MetaAnnotation  ma =  myAnnotation.annotationAttr();

       System.out.println(ma.value());

      注解的详细语法可以通过看java语言规范了解,即看java的language specification。


注解的定义与使用反射的方式获取注解示例

为注解添加注解类型的属性做准备

public @interface MetaAnnotation {String value();}


注解类
import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;import javax.lang.model.element.Element;//在注解类上加注解(元注解)//RetentionPolicy类是为注解的生命周期加注解,这里的生命周期,指定为运行阶段,默认值为class阶段@Retention(RetentionPolicy.RUNTIME)//Target,为定义注解的位置,这里指定可以放在方法和类上@Target({ElementType.METHOD,ElementType.TYPE})public @interface MyAnnotation {//为注解添加属性//String color();String color() default "red";     //只要value赋值,其他都为默认,即可通过编译String value();int[] array() default {1,2,3};    //为注解添加数组类型的属性MetaAnnotation annotationAttr()  default @MetaAnnotation("50");//为注解添加注解类型的属性}


调用注解类的测试类
import java.lang.annotation.Annotation;//加上一个标记,相当于获取一个注解的实例对象,同时初始化属性值:注解,颜色和值@MyAnnotation(annotationAttr=@MetaAnnotation("90"), color = "red",value="100",array=1)//如果只有value属性,可以省略"="号,如果有其他属性,那些属性可以设置为默认以便通过编译//@MyAnnotation("100")public class AnnotationTest {//@MyAnnotation//为过时的方法添加注解@SuppressWarnings("deprecation")public static void main(String[] args){//方法已过时,需要添加注解System.runFinalizersOnExit(true);//方法已过时show();//用反射进行测试AnnotationTest的定义上是否有@MyAnnotation if(AnnotationTest.class.isAnnotationPresent(MyAnnotation.class)){MyAnnotation myAnnotation = (MyAnnotation)AnnotationTest.class.getAnnotation(MyAnnotation.class);//获取注解System.out.println(myAnnotation);//获取注解的属性System.out.println(myAnnotation.color());System.out.println(myAnnotation.value());System.out.println(myAnnotation.array().length);//获取注解属性为注解的值System.out.println(myAnnotation.annotationAttr().value());}}//添加“已过时”注解@Deprecatedprivate static void show(){System.out.println("Hello java!!!");}}


原创粉丝点击