JAVA高新技术——JDK1.5新特性
来源:互联网 发布:太空工程师编程模块 编辑:程序博客网 时间:2024/06/10 07:31
静态导入
一般导入import是导入一个类或某个包中的所有类。而静态导入是import static 导入的类名或者类名的某个静态方法。
其作用是简化书写,调用静态方法时不用再指定包名了,前提是方法名没有重复。
例:
package cn.itcast.day1;//静态导入import static java.lang.Math.*;public class StaticImport {public static void main(String[] arg){int x=1;x++;System.out.println(x);System.out.println(max(3, 6));System.out.println(abs(3 - 6));}}
可变参数
当写代码时,不知道所写方法的参数个数时,可以用可变参数 ,如public static int add(int x,int ...args)
可变参数注意点:
1、只能出现参数列表最后
2、。。。位于变量类型与变量名之间
3、调用可变参数方法时,实际上是为该可变参数创建一个数组
例:
public class VariableParam {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubSystem.out.println(add(1, 2, 3, 4, 5, 6, 7));;}public static int add(int x,int...args){int sum=x;for (int i = 0; i < args.length; i++) {sum+=args[i];}return sum;}}
增强for循环
语法:for ( type 变量名:集合变量名 ) { … }
注意:集合变量可以是数组或实现了Iterable接口的集合类
上例用增强for循环演示:
public static int add(int x,int...args){int sum=x;for (int arg : args) {sum+=arg;}return sum;
自动拆装箱
//自动装箱 :Integer num1=new Integer(num1);Integer num1=3;//自动拆箱:Integer.valueOf(num1)+3System.out.println(num1+3);//当数值在-128~127时,对象会被重用Integer i1=120;Integer i2=120;System.out.println(i1==i2); //true//不在-128~127时,与其他对象一样都再new一个对象Integer a1=200;Integer a2=200;System.out.println(a1==a2);//false
在-128~127内对象重用是一种设计模式,称为享元设计模式:对象一样,对象位置可能不一样,要接受位置参数
枚举
用途:
枚举就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就会报错。
枚举可以让编译器在编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段无法实现这一目标
枚举可以让编译器在编译时就可以控制源程序中填写的非法值,普通变量的方式在开发阶段无法实现这一目标
注意:
1、枚举类型是一种类型。也有构造函数(必须是私有的),也有成员变量以及成员函数。
2、枚举元素其实就是对象。枚举元素必须位于枚举体的最开始部分。
3、知道如何选择带参数的构造方法。
4、定义抽象成员函数时,知道如何实现成员函数。
例子:
//基本的:包含构造函数的星期类enum WeekDay{SUN(2),MON,TUE,WED,THE,FRI,SAT;//枚举的构造函数,不能是publicprivate WeekDay(){System.out.println("first");}private WeekDay(int num){System.out.println("second"+"....."+num);}}//高级的:交通灯枚举,包含构造函数及成员enum TrafficLamp{GREEN{public TrafficLamp nextLamp(){return RED;}},RED(){public TrafficLamp nextLamp(){return YELLOW;}},YELLOW(1){public TrafficLamp nextLamp(){return GREEN;}};public abstract TrafficLamp nextLamp();private TrafficLamp() {System.out.println("不带参数的构造函数");}private TrafficLamp(int num){System.out.println("带参数的构造函数");}}public class EnumDemo {public static void main(String[] args) {TrafficLamp trafficLampRed=TrafficLamp.RED;System.out.println(trafficLampRed.nextLamp());}}
注解
三个基本注解
@SuppressWarnings
该注解的作用是给编译器一条指令,告诉它对被注解的代码元素内部的某些警告保持静默。比如使用了过时的方法,eclipse会在方法上画一条横线。JAVAC命令也会产生警告。
@SuppressWarnings("dedeprecation)
此注解作用就是告诉编译器,虽然我用的方法过时了,但是我还是坚持要用,你就不要再提示了。
@Deprecated
该注解是告诉用户此方法过时了,不建议使用了。
@Override
该注解是确保重写父类函数成功。
注意:
注解是一个特殊的类型。使用注解,就相当于创建了对象。
注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记。
标记可以加在包,类,字段,方法,方法的参数以及局部变量上。
注解的应用
定义注解类————>给一个类加注解————>应用被注解过得类
测试:定义一个注解类,并给一个类加注解时。
public class AnnotationDemo {@MyAnnotationpublic static void main(String[] args) {//isAnnotationPresent判断是否使用了某个注解if(AnnotationDemo.class.isAnnotationPresent(MyAnnotation.class)){System.out.println("yes");}else{System.out.println("no");}}}发现输出结果是no,也就是我们并没有使用注解。这是为何?
答:
注解是一种类型,注解其实也是可以有自己的注解的,称为元注解。其中有一个Retention元注解。
Retention元注解默认值是RetentionPolicy.CLASS,也就是说@MyAnnotation注解在运行的时候已经被过滤掉了。
解决这个问题的方式就是在注解类上在加个元注解@Retention(RetentionPolicy.RUNTIME)。
解决这个问题的方式就是在注解类上在加个元注解@Retention(RetentionPolicy.RUNTIME)。
Tip:
@Retention元注解有三种取值:RetetionPolicy.SOURCE、RetetionPolicy.CLASS、RetetionPolicy.RUNTIME,
分别对应:java源文件-->class文件-->内存中的字节码。
分别对应:java源文件-->class文件-->内存中的字节码。
但还是没有解决,输出的还是no!
因为上面的代码,@MyAnnotation给主函数加注解了。
而 AnnotationDemo.class.isAnnotationPresent(MyAnnotation.class)判断的是类是否使用了注解MyAnnotation。所以输出no。
除了Retention元注解,还有其他的元注解。如Target元注解。限定注解适用位置(类上,方法上,变量上等)。
默认是任意位置。如果设置Target等于ElementType.METHOD,原来加在类上的注解会报错。可以通过数组限定多个适用的位置。
为注解添加属性
注意:注解的属性不是像成员变量一样,而是像成员方法一样。
比如在注解类中添加一个color属性。
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface MyAnnotation {String color();}这样在给类添加注解时给属性一个标示,属性是为了更细的区分。
一个注解相当于一个胸牌,如果你胸前贴了胸牌,就是传智播客的学生,否则,就不是。
如果还想区分出是传智播客哪个班的学生,这时候可以为胸牌在增加一个属性来进行区分。
所以在给类添加注解时需要传入属性:
如果还想区分出是传智播客哪个班的学生,这时候可以为胸牌在增加一个属性来进行区分。
所以在给类添加注解时需要传入属性:
public class AnnotationDemo {@MyAnnotation(color="red")public static void main(String[] args) {//isAnnotationPresent判断是否使用了某个注解if(AnnotationDemo.class.isAnnotationPresent(MyAnnotation.class)){System.out.println("yes");}}}
泛型
基本应用
Jdk 1.5的集合类希望你在定义集合时,明确表示你要向集合中装哪种类型的数据,无法加入指定类型以外的数据。
没有使用泛型时,只要是对象,不管是什么类型的对象,都可以存储进同一个集合中。
使用泛型集合,可以将一个集合中的元素限定为一个特定类型,集合中只能存储同一个类型的对象,这样更安全;
并且当从集合获取一个对象时,编译器也可以知道这个对象的类型,不需要对对象进行强制类型转换,更方便。
没有使用泛型时,只要是对象,不管是什么类型的对象,都可以存储进同一个集合中。
使用泛型集合,可以将一个集合中的元素限定为一个特定类型,集合中只能存储同一个类型的对象,这样更安全;
并且当从集合获取一个对象时,编译器也可以知道这个对象的类型,不需要对对象进行强制类型转换,更方便。
泛型进阶
泛型是用在编译时候的。即让问题在编译的时候就发现。而在运行的时候是否泛型是没有区别的,编译器编译带类型说明的集合时会去除掉“类型”信息,
目的就是使程序运行效率不受影响。因此,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样。
由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其它类型的数据,
例如,用反射得到集合,再调用其add方法即可。
例如,用反射得到集合,再调用其add方法即可。
import java.util.ArrayList;public class GenericsDemo {public static void main(String[] args) throws Exception{//只能放Integer类型的数据ArrayList<Integer> al=new ArrayList<Integer>();al.add(1);//自动装箱// al.add("abc"); 错误!但可以通过反射越过编译al.getClass().getMethod("add", Object.class).invoke(al, "abc");System.out.println(al); }}//输出[1, abc]
附:泛型术语:
ArrayList<E>称为泛型类型
ArrayList<E>中的E称为类型变量或类型参数
ArrayList<Integer>称为参数化的类型
ArrayList<Integer>中的Integer称为类型参数的实例或实际类型参数
ArrayList<Integer>中的<>念着typeof
ArrayList称为原始类型
ArrayList<E>中的E称为类型变量或类型参数
ArrayList<Integer>称为参数化的类型
ArrayList<Integer>中的Integer称为类型参数的实例或实际类型参数
ArrayList<Integer>中的<>念着typeof
ArrayList称为原始类型
参数化类型与原始类型的兼容性:
参数化类型可以引用一个原始类型的对象,编译报告警告,例如,ArrayList<String> a2=new ArrayList();//考虑到对以前代码的兼容性,编译器是可以通过的
原始类型可以引用一个参数化类型的对象,编译报告警告,例如,ArrayList a1=new ArrayList<String>();//原来的方法接受一个集合参数,新的类型也要能传进去
简单地说:两边缺一个没有关系!
参数化类型不考虑类型参数的继承关系:
Vector<String> v = new Vector<Object>(); //错误!不写<Object>没错,写了就是明知故犯
Vector<Object> v = new Vector<String>(); //也错误!
参数化类型可以引用一个原始类型的对象,编译报告警告,例如,ArrayList<String> a2=new ArrayList();//考虑到对以前代码的兼容性,编译器是可以通过的
原始类型可以引用一个参数化类型的对象,编译报告警告,例如,ArrayList a1=new ArrayList<String>();//原来的方法接受一个集合参数,新的类型也要能传进去
简单地说:两边缺一个没有关系!
参数化类型不考虑类型参数的继承关系:
Vector<String> v = new Vector<Object>(); //错误!不写<Object>没错,写了就是明知故犯
Vector<Object> v = new Vector<String>(); //也错误!
简单地说:两边要是都有尖括号,其内容必须相同!
tip:
编译器不允许创建泛型变量的数组。即在创建数组实例时,数组的元素不能使用参数化的类型。
例如,下面语句有错误:
例如,下面语句有错误:
思考题:
下面的代码会报错误吗?
Vector v1 = new Vector<String>();
Vector<Object> v = v1;
答案:编译的时候是不会报错的,因为编译器是一行一行按照语法检查代码的,因此不会出错。
Vector<Integer> vectorList[] = new Vector<Integer>[10];
下面的代码会报错误吗?
Vector v1 = new Vector<String>();
Vector<Object> v = v1;
答案:编译的时候是不会报错的,因为编译器是一行一行按照语法检查代码的,因此不会出错。
Vector<Integer> vectorList[] = new Vector<Integer>[10];
泛型练习:
public class GenericsDemo {public static void main(String[] args) throws Exception{HashMap<String,Integer> hm=new HashMap<String, Integer>();hm.put("xiaoming", 19);hm.put("zhangsan", 21);Set<Map.Entry<String,Integer>> entrySet=hm.entrySet();for(Map.Entry<String , Integer> en:entrySet){System.out.println(en.getKey()+"::"+en.getValue());}}}
通配符基础
问题:
定义一个方法,该方法用于打印出任意参数化类型的集合中的所有数据,该方法如何定义呢?
如果将printCollection中的参数设置为Collection<Object>类型,那么传入参数的时候,如果参数化的类型是其他类型,就会报错。
定义一个方法,该方法用于打印出任意参数化类型的集合中的所有数据,该方法如何定义呢?
如果将printCollection中的参数设置为Collection<Object>类型,那么传入参数的时候,如果参数化的类型是其他类型,就会报错。
例:
public class GenericsDemo {public static void main(String[] args) throws Exception{printCollection(new ArrayList<String>());//错误。等价于:ArrayList<Object> a=new ArrayList<String>()}public static void printCollection(ArrayList<Object> a){//函数体}}
Java1.5中使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用。
此时,printCollection方法中可以调用与参数化无关的方法,不能调用与参数化有关的方法——即方法中不能有泛型。
例如ArrayList类中的add(E e)方法就与参数化有关,不能调用。size()方法与参数化无关就可以调用。
public class GenericsDemo {public static void main(String[] args) throws Exception{printCollection(new ArrayList<String>());}public static void printCollection(ArrayList<?> a){// a.add("aaa");错误 ,与参数化有关的函数a.size(); //可以,与参数无关的函数}}
之所以add方法是错的,是因为他不知道自己未来匹配的一定是String。
比如:如果add方法可以用,那么如果你是new ArrayList<Interger>岂不是运行会出错?但编译没出错。
注:上述例子没有意义,只是为了说明哪些可以编译通过,哪些不可以。通配符拓展
限定通配符的上边界:
正确:Vector<? extends Number> x = new Vector<Integer>();
错误:Vector<? extends Number> x = new Vector<String>(); //只能是Number及其子类
限定通配符的下边界:
正确:Vector<? super Integer> x = new Vector<Number>();
错误:Vector<? super Integer> x = new Vector<Byte>();//只能是Integer及其父类
正确:Vector<? extends Number> x = new Vector<Integer>();
错误:Vector<? extends Number> x = new Vector<String>(); //只能是Number及其子类
限定通配符的下边界:
正确:Vector<? super Integer> x = new Vector<Number>();
错误:Vector<? super Integer> x = new Vector<Byte>();//只能是Integer及其父类
自定义泛型方法
由C++的模板函数引入自定义
如下函数的结构很相似,仅类型不同:
int add(int x,int y) {
return x+y;
}
float add(float x,float y) {
return x+y;
}
double add(double x,double y) {
return x+y;
}
C++用模板函数解决,只写一个通用的方法,它可以适应各种类型,示意代码如下:
template<class T>
T add(T x,T y) {
return (T) (x+y);
}
如下函数的结构很相似,仅类型不同:
int add(int x,int y) {
return x+y;
}
float add(float x,float y) {
return x+y;
}
double add(double x,double y) {
return x+y;
}
C++用模板函数解决,只写一个通用的方法,它可以适应各种类型,示意代码如下:
template<class T>
T add(T x,T y) {
return (T) (x+y);
}
Java中的泛型类型(或者泛型)类似于 C++ 中的模板。但是这种相似性仅限于表面,Java 语言中的泛型基本上完全是在编译器中实现,
用于编译器执行类型检查和类型推断,然后生成普通的非泛型的字节码,这种实现技术称为擦除(erasure)(编译器使用泛型类型信息保证类型安全,
然后在生成字节码之前将其清除)。这是因为扩展虚拟机指令集来支持泛型被认为是无法接受的,
这会为 Java 厂商升级其 JVM 造成难以逾越的障碍。所以,java的泛型采用了可以完全在编译器中实现的擦除方法。
然后在生成字节码之前将其清除)。这是因为扩展虚拟机指令集来支持泛型被认为是无法接受的,
这会为 Java 厂商升级其 JVM 造成难以逾越的障碍。所以,java的泛型采用了可以完全在编译器中实现的擦除方法。
擦除,这就是之前提到的,编译器最终会去掉“类型”信息!!
比如:
例如,下面这两个方法,编译器会报告错误,它不认为是两个不同的参数类型,而认为是同一种参数类型。
private static void applyGeneric(Vector<String> v){
}
private static void applyGeneric(Vector<Date> v){
}
private static void applyGeneric(Vector<String> v){
}
private static void applyGeneric(Vector<Date> v){
}
注意:
Java的泛型方法没有C++模板函数功能强大,java中的如下代码无法通过编译:
<T> T add(T x,T y) {
return (T) (x+y);
}
因为T类型的对象可能并不具备加法运算的功能。
用于放置泛型的类型参数的尖括号紧邻返回值之前。按照惯例,类型参数通常用单个大写字母表示。
虽然上述加法不能通过编译,但其他的一些简单的可以。
<T> T add(T x,T y) {
return (T) (x+y);
}
因为T类型的对象可能并不具备加法运算的功能。
用于放置泛型的类型参数的尖括号紧邻返回值之前。按照惯例,类型参数通常用单个大写字母表示。
虽然上述加法不能通过编译,但其他的一些简单的可以。
例如:交换数组中的两个元素的位置的泛型方法语法定义如下:
public static void main(String[] args) throws Exception{String[] s=new String[]{"abc","def","rtg"};int[] i=new int[]{1,2,3};Integer[] in=new Integer[]{1,2,3};swap(s,0,1);//swap(i,0,1);错误swap(in,0,1); //Ok}public static <T> void swap(T[] a,int x,int y){T temp=a[x];a[x]=a[y];a[y]=temp;}
0 0
- JAVA高新技术——JDK1.5新特性
- Jdk1.5新特性笔记 (Java高新技术)
- Java高新技术 JDK1.5之新特性
- Java高新技术:JDK1.5新特性
- 黑马程序员——高新技术--jdk1.5新特性
- 黑马程序员——Java高新技术——JDK1.5版本的新特性泛型
- Java基础(十四)——高新技术之jdk1.5新特性、反射
- 黑马程序员——java高新技术-jdk1.5新特性,注解,类加载器,代理
- Java生涯——高新技术---枚举及部分JDK1.5新特性
- 黑马程序员—JAVA高新技术之JDK1.5的新特性
- 黑马程序员—【Java高新技术】之eclipse开发工具枚举及JDK1.5新特性
- 黑马程序员:Java高新技术1--JDK1.5 新特性
- 黑马程序员-Java高新技术-jdk1.5简单的新特性
- Java高新技术-jdk1.5简单的新特性
- 黑马程序员--Java高新技术--JDK1.5新特性(上)
- 黑马程序员--Java高新技术--JDK1.5新特性(下)
- 黑马程序员--Java高新技术--JDK1.5新特性(上)
- 黑马程序员--Java高新技术--JDK1.5新特性(下)
- mysql 插入中文乱码解决方案 转
- 数据库数据文件有备份的恢复 ORA-01157 【续+1】
- Java Note (1) - Basic Knowledge
- 第一次作业
- html5中cellpadding和cellspacing属性不被支持,用css border-collapse:collapse来代替
- JAVA高新技术——JDK1.5新特性
- 字母图形
- NS2下实现MAC跨层设计
- tomcat conf目录下四个文件的作用
- 改变phpmyadmin的默认空密码
- 每一位Android开发者应该知道的Android体系架构和开发库
- Serizlizable Parcelable
- VS2010 LNK1123: 转换到 COFF 期间失败: 文件无效或损坏 的解决方法
- 在Ubuntu下给NS2配置GUI调试环境