黑马程序员技术交流社区
标题: JDK 1.5 特性总结 [打印本页]
作者: 朱晓杰 时间: 2013-7-9 21:39
标题: JDK 1.5 特性总结
本帖最后由 朱晓杰 于 2013-7-9 21:46 编辑
JDK 1.5 特性总结
听张老师讲课,脚的JDK 1.5 特性还蛮有意思的,所以发个总结帖,与各位交流学习。
A.静态导入
静态导入语句的语法与import语句类似,用它可以直接使用类变量和类方法:
格式如下:
import static 包名.类名.*;
import static 包名.类名.类变量的名字;
import static 包名.类名.类方法的名字;
注意:如果静态导入两个类中同名的类变量或类方法,就无法使用,必须通过对象或类名使用类变量 ,类方法
- 示例:
- import static java.lang.System.out;
- import static java.lang.Math.*;
- /**
- * 需求:演示java中静态导入的使用
- * 使用静态导入,可以减少代码的书写,提高效率
- * */
- public class StaticImport {
- public static void main(String[] args) {
- out.println(max(10, 20));
- }
- }
复制代码B.可变参数
适用于参数个数不确定,类型确定的情况,java把可变参数当做数组处理。
可变参数的特点:
(1)只能出现在参数列表的最后;
(2)... 位于变量类型和变量名之间,前后有无空格都可以;
(3)调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。- 示例:
- import static java.lang.System.*;
- /**
- * 需求:求n个整数的和
- * */
- public class VariableArguments {
- public static void main(String[] args) {
- out.println("sum=" + sum(1,2,3,4,5));
- out.println("sum=" + sum(1,2,3));
- }
- public static int sum(int num,int ... args){
- int sum = num;
- for(int i = 0; i < args.length; i++){
- sum += args[i];
- }
- return sum;
- }
- }
复制代码 C.增强for循环
语法:
for (循环变量类型 循环变量名称 : 要被遍历的对象) {
循环体
}
注意:
1.循环变量名称必须在 () 中定义
2.要遍历的对象可以是数组或者是实现了iterable的接口的集合类- 示例:
- import static java.lang.System.*;
- /**
- * 需求:求n个整数的和改进版
- * */
- public class VariableArguments {
- public static void main(String[] args) {
- out.println("sum=" + sum(1,2,3,4,5));
- out.println("sum=" + sum(1,2,3));
- }
-
- public static int sum(int num,int ... args){
- int sum = num;
-
- //防止在循环体里修改循环变量,给i重新赋值时,编译出错,Unresolved compilation problem
- for(final int i : args){
- sum += i;
- }
-
- return sum;
- }
- }
复制代码 D.基本数据的自动拆装箱- 示例:
- import static java.lang.System.*;
- /**
- * 需求:演示java1.5中基本数据类型自动拆箱装箱
- * */
- public class Auto {
- public static void main(String[] args) {
- //自动装箱:基本数据类型封装为对象类型
- Integer num = 10;
- //自动拆箱:对象类型转为为基本数据类型
- out.println(num + 10);
- }
- }
复制代码 E.枚举
为什么要使用枚举?枚举是什么?
在实际编程中,往往存在着这样的“数据集”,它们的数值在程序中是稳定的,而且“数据集”中的元素是有限的。
例如星期一到星期日七个数据元素组成了一周的“数据集”,春夏秋冬四个数据元素组成了四季的“数据集”。
在java中如何更好的使用这些“数据集”呢?因此枚举便派上了用场。 枚举就是要让某个类型变量的取值只能为若干个固定值中的一个,否则编译器就会报错。枚举可以让编译器在编译时就控制源程序中填写的非法值,普通变量的定义方式在开发阶段无法实现这一目标。所有的枚举都继承自java.lang.Enum类。由于Java 不支持多继承,所以枚举对象不能再继承其他类。如果枚举只有一个成员时,就可以作为单例的一种实现方式。
用普通类模拟java中枚举的实现(注意内部类的使用)- 示例:
- public abstract class WeekDay {
- private WeekDay(){}
- public static final WeekDay SUN = new WeekDay(){
- public WeekDay nextDay() {
- return MON;
- }
- public String toString() {
- return "MON";
- }
- };
-
- public static final WeekDay MON = new WeekDay(){
- public WeekDay nextDay() {
- return TUE;
- }
- public String toString() {
- return "TUE";
- }
- };
-
- public static final WeekDay TUE = new WeekDay(){
- public WeekDay nextDay() {
- return WES;
- }
- public String toString() {
- return "WES";
- }
- };
-
- public static final WeekDay WES = new WeekDay(){
- public WeekDay nextDay() {
- return THI;
- }
- public String toString() {
- return "THI";
- }
- };
-
- public static final WeekDay THI = new WeekDay(){
- public WeekDay nextDay() {
- return FRI;
- }
- public String toString() {
- return "FRI";
- }
- };
-
- public static final WeekDay FRI = new WeekDay(){
- public WeekDay nextDay() {
- return STA;
- }
- public String toString() {
- return "STA";
- }
- };
-
- public static final WeekDay STA = new WeekDay(){
- public WeekDay nextDay() {
- return SUN;
- }
- public String toString() {
- return "SUN";
- }
- };
-
- public abstract WeekDay nextDay();
-
- public abstract String toString();
-
- }
复制代码
作者: 朱晓杰 时间: 2013-7-9 21:39
本帖最后由 朱晓杰 于 2013-7-9 21:44 编辑
枚举的基本应用:
一:常量
在JDK1.5 之前,我们定义常量都是: public static fianl.... 。有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法。- import static java.lang.System.*;
- public class EnumDemo {
- public static void main(String[] args) {
- WeekDay weekDay = WeekDay.SUN;
- out.println(weekDay.nextDay().toString());
-
- //枚举重写了toString方法
- WeekDayEnum weekDayEnum = WeekDayEnum.SUN;
- out.println(weekDayEnum);
- out.println(weekDayEnum.name());
- //当前对象在枚举重的位置
- out.println(weekDayEnum.ordinal());
- out.println(weekDayEnum.valueOf("SUN").toString());
- //遍历枚举
- WeekDayEnum[] weekDayEnums = WeekDayEnum.values();
- out.println(weekDayEnums.length);
- for(WeekDayEnum w : weekDayEnums){
- out.println(w);
- }
- }
- public enum WeekDayEnum{
- //分号可有可无
- SUN,MON,TUE,WES,THI,FRI,STA
- }
- }
复制代码 二:switch
JDK1.6前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强。- 示例:
- enum Signal {
- GREEN, YELLOW, RED
- }
- public class TrafficLight {
- Signal color = Signal.RED;
- public void change() {
- switch (color) {
- case RED:
- color = Signal.GREEN;
- break;
- case YELLOW:
- color = Signal.RED;
- break;
- case GREEN:
- color = Signal.YELLOW;
- break;
- }
- }
- }
复制代码 三:添加新方法
如果打算自定义自己的方法,那必须在enum实例序列的最后添加一个分号。而且 Java 要求必须先定义 enum 实例。- 示例:实现带有构造方法的枚举
- public enum WeekDayEnum{
- SUN(1),MON(),TUE,WES,THI,FRI,STA;
- private WeekDayEnum(){
- out.println("first");
- }
- private WeekDayEnum(int index){
- out.println("second");
- }
- }
- 示例:实现带有抽象方法的枚举
- 注意:构造方法的修饰必须定义成为私有的
- public enum TrafficLight{
- RED(60) {
- public TrafficLight nextLight() {
- return GREEN;
- }
- },
- YELLOW(10) {
- public TrafficLight nextLight() {
- return RED;
- }
- },
- GREEN(45) {
- public TrafficLight nextLight() {
- return RED;
- }
- };
- public abstract TrafficLight nextLight();
- private int time;
- private TrafficLight(int time){
- this.time = time;
- }
- }
复制代码 四:枚举集合的使用
java.util.EnumSet和java.util.EnumMap是两个枚举集合。
EnumSet保证集合中的元素不重复;EnumMap中的 key是enum类型,而value则可以是任意类型。
F.泛型
1. 体验泛型
Jdk 1.5以前的集合类中存在什么问题
示例:
ArrayList collection = new ArrayList();
collection.add(1);
collection.add(1L);
collection.add("abc");
int i = (Integer) collection.get(1);//编译要强制类型转换且运行时出错!
Jdk 1.5的集合类希望你在定义集合时,明确表示你要向集合中装哪种类型的数据,无法加入指定类型以外的数据
示例:
ArrayList<Integer> collection2 = new ArrayList<Integer>();
collection2.add(1);
//collection2.add(1L);
//collection2.add(“abc”);//这两行代码编译时就报告了语法错误
int i2 = collection2.get(0);//不需要再进行类型转换
2. 了解泛型
泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去除掉“类型”信息,使程序运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其它类型的数据,例如,用反射得到集合,再调用其add方法即可。
ArrayList<E>类定义和ArrayList<Integer>类引用中涉及如下术语:
ArrayList<E>:泛型类型
E:类型变量或类型参数
ArrayList<Integer>:参数化的类型
Integer:类型参数的实例或实际类型参数
<>:typeof
ArrayList称为原始类型
参数化类型与原始类型的兼容性:
参数化类型可以引用一个原始类型的对象,编译报告警告,
例如,Collection<String> c = new Vector();//可不可以,不就是编译器一句话的事吗?
原始类型可以引用一个参数化类型的对象,编译报告警告,
例如,Collection c = new Vector<String>();//原来的方法接受一个集合参数,新的类型也要能传进去
参数化类型不考虑类型参数的继承关系:
Vector<String> v = new Vector<Object>(); //错误! 不写<Object>没错,写了就是明知故犯
Vector<Object> v = new Vector<String>(); //也错误!
编译器不允许创建泛型变量的数组。
3.泛型中的通配符 ?
使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法。- 问题:
- 定义一个方法,该方法用于打印出任意参数化类型的集合中的所有数据,该方法如何定义呢?
- 错误方式:
- public static void printCollection(Collection<Object> cols) {
- for(Object obj:cols) {
- System.out.println(obj);
- }
- /* cols.add("string");//没错
- cols = new HashSet<Date>();//会报告错误!*/
- }
- 正确方式:
- public static void printCollection(Collection<?> cols) {
- for(Object obj:cols) {
- System.out.println(obj);
- }
- //cols.add("string");//错误,因为它不知自己未来匹配就一定是String
- cols.size();//没错,此方法与类型参数没有关系
- cols = new HashSet<Date>();
- }
复制代码 限定通配符的上边界:
正确:Vector<? extends Number> x = new Vector<Integer>();
错误:Vector<? extends Number> x = new Vector<String>();
限定通配符的下边界:
正确:Vector<? super Integer> x = new Vector<Number>();
错误:Vector<? super Integer> x = new Vector<Byte>();
注意:限定通配符总是包括自己。
?只能用作引用,不能用它去给其他变量赋值
Vector<? extends Number> y = new Vector<Integer>();
Vector<Number> x = y;
上面的代码错误,原理与Vector<Object > x11 = new Vector<String>();相似,
只能通过强制类型转换方式来赋值。
4.自定义泛型
a. 定义泛型方法
Java的泛型方法没有C++模板函数功能强大,java中的如下代码无法通过编译:
- <T> T add(T x,T y) {
- return (T) (x+y);
- }
复制代码 用于放置泛型的类型参数的尖括号应出现在方法的其他所有修饰符之后和在方法的返回类型之前,也就是紧邻返回值之前。按照惯例,类型参数通常用单个大写字母表示。
- 交换数组中的两个元素的位置的泛型方法语法定义如下:
- static <E> void swap(E[] a, int i, int j) {
- E t = a;
- a = a[j];
- a[j] = t;
- }
- //或用一个面试题讲:把一个数组中的元素的顺序颠倒一下
复制代码 注意:
1)只有引用类型才能作为泛型方法的实际参数,swap(new int[3],3,5);语句会报告编译错误。
2)除了在应用泛型时可以使用extends限定符,在定义泛型时也可以使用extends限定符,
例如,Class.getAnnotation()方法的定义。并且可以用&来指定多个边界,
如<V extends Serializable & cloneable> void method(){}
3)普通方法、构造方法和静态方法中都可以使用泛型。
也可以用类型变量表示异常,称为参数化的异常,可以用于方法的throws列表中,但是不能用于catch子句中。
在泛型中可以同时有多个类型参数,在定义它们的尖括号中用逗号分,例如:
public static <K,V> V getValue(K key) { return map.get(key);}
作者: 朱晓杰 时间: 2013-7-9 21:45
b. 定义泛型类型
如果类的实例对象中的多处都要用到同一个泛型参数,即这些地方引用的泛型类型要保持同一个实际类型时,
这时候就要采用泛型类型的方式进行定义,也就是类级别的泛型,语法格式如下:
- <font face="宋体" size="4">public class GenericDao<T> {
- private T field1;
- public void save(T obj){}
- public T getById(int id){}
- }</font>
复制代码 注意:
A. 在对泛型类型进行参数化时,类型参数的实例必须是引用类型,不能是基本类型。
B. 当一个变量被声明为泛型时,只能被实例变量、方法和内部类调用,而不能被静态变量和静态方法调用。
因为静态成员是被所有参数化的类所共享的,所以静态成员不应该有类级别的类型参数。
作者: 朱晓杰 时间: 2013-7-9 22:27
版主,一言难尽啊,因为这份工作的原因,得推迟几个月了,你已经去了么?
作者: 神之梦 时间: 2013-7-9 22:34
很给力,帮顶
作者: 朱晓杰 时间: 2013-7-9 22:35
不过快了,我想不用等很久了
作者: 朱晓杰 时间: 2013-7-9 22:36
:D~~谢版主~~
作者: chslzj 时间: 2013-7-9 22:41
我是来看金币的
作者: 朱晓杰 时间: 2013-7-9 22:54
版主,加油,我估计云七了得,被工作搞的现在学的挺乱的,还得好好整理一下,有点儿发愁后面的面试
作者: camml 时间: 2013-7-10 10:41
楼主真伟大
作者: 朱晓杰 时间: 2013-7-10 12:19
:funk: 这玩笑开的有点儿大了哇
作者: 云游天下 时间: 2013-7-13 22:40
只求技术分 要进云五 加油
作者: 杨晓燕 时间: 2013-7-14 11:45
喔,赞一个,厉害
作者: zhou5852 时间: 2013-7-15 11:00
总结的很给力。。。。。我正愁这个怎么记忆呢 上面的图画的好啊。。。 1.6新特性呢{:soso_e107:} 1.7的。。。。额。。。。。
作者: Just_Only 时间: 2013-7-15 11:49
支持了。。。
作者: 狐狸FMF 时间: 2014-8-13 21:09
给力~~~~~~~~~~~~~~~~
作者: csc 时间: 2015-12-25 18:20
看看谢谢楼主
作者: caoshengwei 时间: 2016-4-17 01:20
这个真的可以有6666666
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |