jdk1.5新特性:静态导入、增强for循环、自动装箱和拆箱、可变参数、枚举、注解、泛型。
静态导入:
程序1:
public class StaticImportTest {
public static void main(String[] args) throws Exception {
int num=Math.max(7,6);
System.out.println(num);
}
}
程序2:
import static java.lang.Math.*;
public class StaticImportTest {
public static void main(String[] args) throws Exception {
int num=max(7,6);
System.out.println(num);
}
}
从程序1和程序2中的区别可以看出,当调用一个静态的方法时,可以用类名.方法名,如果用import static java.lang.Math.*,只需写出方法,不需要写出类名.方法名.程序2第一行代码就是所谓的静态导入。
增强for循环:
增强for循环和一般的循环不一样,它的格式是for(类型 变量名:集合变量名),集合变量必须是数组或者是实现了Iterable接口。
下面用普通的for循环和增强for循环进行比较。
public class ForTest {
public static void main(String[] args) throws Exception {
int[] nums=new int[]{4,5,6,7,3};
for(int i=0;i<nums.length;i++){ //普通for循环
System.out.print(nums[i]+" ");
}
System.out.println();
for(int num : nums){ //增强for循环
System.out.print(num+" ");
}
}
}
自动装箱和拆箱:
所谓装箱,就是把基本类型用它们相对应的引用类型包起来,使它们可以具有对象的特质,而拆箱是将引用类型的对象重新简化为基本类型。
public class Test {
public static void main(String[] args) throws Exception {
Integer i=1; //自动装箱
int j=i; //自动拆箱
}
}
再来看看下面程序为什么结果不同:
public class StaticImportTest {
public static void main(String[] args) throws Exception {
Integer m=3;
Integer n=3;
Integer i=128;
Integer j=128;
System.out.println(m==n);
System.out.println(i==j);
}
}
运行结果:true 、false
因为对于自动装箱在-128~127之间,它们被装箱为Integer对象时,在内存中会被重用。而在-128~127之外时被装箱为Integer对象时就是创建了一个新的Integer对象。
享元模式: 有很多小的对象,他们有很多属性相同把他们变成一个对象,那些不同的属性把他们变成方法的参数称之为外部状态,哪些相同的属性称之为这个对象的内部状态。
可变参数:
public class Test {
public static void main(String[] args) {
int[] arrs=new int[]{2,4,5,6,7};
int sum=add(4,arrs);
System.out.println(sum);
}
public static int add(int sum,int... arrs) { //int... args 是可变参数
for(int arr:arrs){
sum+=arr;
}
return sum;
}
}
枚举:枚举就是让某个类型的变量只能在几个固定的范围内取值,枚举是一种特殊的类,其中的每个元素都是该类的一个实例对象
程序如下:
public enum Deng {
RED,GREEN,YELLO;
}
如果枚举类有抽象的方法那么子类必须去实现抽象的方法用内部类实现
public enum Deng{
RED { //子类实现抽象方法
public Deng nextLamp() {
return GREEN;
}
},
GREEN {
public Deng nextLamp() {
return YELLO;
}
},
YELLO {
public Deng nextLamp() {
return RED;
}
};
public abstract Deng nextLamp(); //抽象方法
}
构造方法是可以接收参数的,带有参数的枚举那么必须要将构造方法私有化是为了防止外界new出新的对象
public enum Deng{
RED(40){
public Deng nextLamp() {
return GREEN;
}
},
GREEN(50){
public Deng nextLamp() {
return YELLO;
}
},
YELLO(10){
public Deng nextLamp() {
return RED;
}
};
private int time;
public abstract Deng nextLamp();
private Deng(int time){
this.time=time;
}
}
注解:
注解相当于一种标记,在程序中加了注解就等于打上了某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何标记,看你有什么标记就去干相应的事情。标记可以加在包、类、字段、方法、方法的参数以及局部变量上。
java提供的三个基本注解:@SuppressWarnings 、@Deprecated 、@Override
@Retention元注解的三种取值:RetetionPolicy.SOURCE、RetetionPolicy.CLASS、RetetionPolicy.RUNTIME分别对应java源文件、class文件、内存中字节码。如果数组属性中只有一个属性,这时候属性部分可以省略大括号
枚举和注解都是特殊的类,不能new创建它们的实例对象,创建枚举的实例对象就是在其中增加元素
在程序中直接用@放上一个标记即可创建一个注解的实例对象。
如何写一个注解类:
public @interface MyAnnotation { //注解类
}
利用反射技术获取注解类:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}
@MyAnnotation
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Class clazz=Test.class;
if(clazz.isAnnotationPresent(MyAnnotation.class)){ //判断是否有这个注解
MyAnnotation myAnnotation=(MyAnnotation) clazz.getAnnotation(MyAnnotation.class); //获取此注解
System.out.println(myAnnotation);
}
}
}
设置注解类属性:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String Color();
int num() default 3;
String[] str() default {"3","5","6"};
}
泛型:java中的泛型类型(或者泛型)类似于C++中的模版。但是这种相似性仅限于表面,java语言中的泛型基本上完全是在编译器中实现。用于编译器执行类型检查和类型推断,然后生成普通的非泛型的字节码,这种实现技术称为擦(编译器使用泛型类型信息保证类型安全,然后在生成字节码之前将其清除)。这是因为扩展虚拟机指令集来支持泛型被认为是无法接受的,这会为java厂商升级其jvm造成难以逾越的障碍。所以,java的泛型采用了可以完全在编译器中实现的擦除方法。
泛型的好处:
程序1:
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
List list=new ArrayList();
list.add("abc");
for(Object obj : list){
String str=(String) obj;
System.out.println(str);
}
}
}
程序2:
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
List<String> list=new ArrayList<String>();
list.add("abc");
for(String str : list){
System.out.println(str);
}
}
}
从两个程序比较就可以看出增加了泛型,在往集合中存入数据时是被限定了类型,程序2中只能存入String类型,因为存入的时候就已经限定了类型,在取出时必定还是那个类型,所以不像程序1那样还要强制转换类型。
java中的泛型是提供给编译器使用的。在编译时就限定了存入数据的类型。由于编译器生成的字节码会去掉泛型的类型信息,所以跳过编译器是可以存入其他类型的数据的。
程序如下:
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) throws Exception {
List<Integer> list=new ArrayList<Integer>(); //泛型限定只能存储Integer类型的数据
Class clazz=list.getClass();
List ls=(List) clazz.getConstructor(null).newInstance(null);
ls.add("abc"); //通过反射技术存入String类型的数据
for(Object l : ls){
System.out.println(l);
}
}
}
?通配符:
使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量注意用作引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法
泛型上限定: ? extends T
泛型下限定:? super T