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

笔记摘要:

     这里主要介绍了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);		//false

Integer 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);	//MON
		System.out.println(weekday.name());	//MON
		System.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());
		}
	}
	//添加“已过时”注解
	@Deprecated
	private static void show(){
		System.out.println("Hello java!!!");
	}
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值