黑马程序员--十一、Java1.5部分新特性

来源:互联网 发布:复制网站源码 编辑:程序博客网 时间:2024/06/13 06:20
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------

一、   自动装包/拆包

自动装包/拆包大大方便了基本类型数据和它们包装类地使用。

 

自动装包:基本类型自动转为包装类.(int>>Integer)

自动拆包:包装类自动转为基本类型.(Integer>>int)

下面这个例子可以很好的说明:

int a = 3;

List c = new ArrayList();

c.add(a);// 自动转换成Integer.

 

Integer b = new Integer(2);

c.add(b + 2);// Integer先自动转换为int进行加法运算,然后int再次转换为Integer

自动装包/拆包解决了:无需在基本类型(primitive types)(例如double)和包装类型(wrapper types)(例如Double)之间人工地进行转换。 


二、静态导入

当我们采用import关键字导入某个包下面的某个类时,如:

当我们使用Math下面的静态方法max(),所使用的格式是“类名.静态方法名”。为了简化书写,通过JDK1.5新特性静态导入,可以在编辑时就可以省去前面的“类名.

具体方法是:

import static两个关键字一起使用,后面如正常导入指定某包的文件

示例:

package 加强Day01.黑马;

import static java.lang.Math.*;

public class ImportStatic {

public static void main(String[] args) {

//没有使用静态导入

//System.out.println(Math.max(4,6));

//System.out.println(Math.abs(2-9));

//使用静态导入,代码简化

System.out.println(max(4,6));

System.out.println(abs(2-9));

}

}

三、可变参数

经典面试题:OverloadOverride的区别?

在回答时不仅仅要回答出我们知道的一般的东西,还有深入回答为什么

Overload是重载

是在一个类中多态的的一种表现,如果一个类定义了多个同名方法,它们可能有不同的参数个数或者不同参数类型。在重载的时候该方法是可以改变返回值类型的。

Override是重写

是父类和子类之间多态的表现,如果在子类中定义某方法与父类中的方法名且参数相同,可以认为该方法被重写,但是若父类中的方法被Private修饰,那就不是重写。在重写的时候不可以改变返回值类型

问题:当一个方法接收的参数个数不固定,如:

System.out.println(add(1,2,3));

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

当我们用重写,但是若添加的参数多了,那么写出来很死板,代码重复很多很臃肿。

这时我们可以将参数封装成数组,在调用方法。但是有比较麻烦,所以就有了可变参数。

可变参数的特点:

1, 只能出现在参数列表的最后;

2, …位于变量类型和变量名之间,前面有无空格都可以;

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

例如:private static int addint num1int… num

package 加强Day01.黑马;

 

public class VariableParameter {

 

public static void main(String[] args) {

System.out.println(add(1,2));

System.out.println(add(1,2,3,4));

}

public static int add(int...args){

int num = 0;

for(int x=0;x<args.length;x++){

num+=args[x];

}

return num;

}

}打印结果:3 10

基本数据类型的自动拆箱及享元模式

package 加强Day01.黑马;

public class Demo {

public static void main(String[] args) {

Integer num1 = 12;//自动装箱

int num2 = num1+11;//自动拆箱

//判断两个整数是否相同

Integer num3 = 11;

Integer num4 = 11;

System.out.println(num3==num4);

//再次判断两个整数是否相同

Integer num5 = 133;

Integer num6 = 133;

System.out.println(num5==num6);

//判断两个包装类型的对象是否相同

Integer num7 = Integer.valueOf(12);

Integer num8 = Integer.valueOf(12);

System.out.println(num7==num8);

}

}打印输出,true false true

小知识

当一个整数大小在一个字节(-128+127)的取值时,会被自动包装为相对应的对象,其地址值是相同的。

JVM在识别很小的基本数据类型时,认为它的使用几率很大,没有必要再new对象,就把它存储在缓存池中,一遍程序复返的使用这个对象。简单说:尝尝使用的东西放在公共空间大家享用,这样就节省内存空间资源。

在这里就体现出了享元设计模式的思想

什么是享元设计模式?

当有很多小的对象,他们的属性很多相同,把他们变成一个对象。把那些不同的属性变成方法的参数,称之为这个对象的外部状态。那些相同的属性称之为这个对象的内部状态

四、枚举


枚举的作用介绍

为什么要有枚举?

问题:要定义星期几或性别的变量,该怎么定义?

假设用1-7分别表示星期一到星期日,但有人可能会写成:int weekday = 0

枚举的作用就是要让某个类型的变量的取值只能为若干个固定值中的一个,否则,编译器就报错。枚举可以让编译器在编译时期就可以控制源程序中填写的非法值,普通变量的方式在开发阶段无法实现这一目标。

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

1, 先私有构造方法;

2, 每个元素分别用一个公有的静态成员表示;

3, 可以有若干公有方法或抽象方法,例如:要提供nextDay方法必须是抽象的,采用抽象方法定义nextDay就将大量的ifElse语句转移成了一个个独立的子类。

示例:

用普通类模拟枚举的实现原理

package 加强Day01.黑马;

public abstract class WeekDay {

private WeekDay(){}//将构造函数私有化

 //每一个元素分别用public static final的成员表示

//创建一个WeekDay的子类对象,并复写父类的nextDay方法

public final static WeekDay SUN = new WeekDay(){

public WeekDay nextDay(){

return MON;

}

};

public final static WeekDay MON = new WeekDay(){

public WeekDay nextDay(){

return SUN;

}

};

//若干想在一个类中编写完各个枚举类和测试调用类,那么可以将枚举类定义成调用类的内部类。

public String toString(){

return this ==SUN?"MON":"SUN";

}

}

分析总结:

1, 模拟枚举类,单例模式,工具类的第一步都是私有化构造函数。

2, 私有化可以让外部调用者不能创建这个类的对象,枚举类在它定义的时候就固定下来。

3, 每一个枚举成员标示一个全局常量即:public final static

4, 可以定义若干公共方法和抽象方法,并有其子类的内部类去实现。

枚举的基本应用

概述:

枚举是通过关键字enum来定义枚举类;枚举类是一个特殊的类,每个元素都是该类的一个实例对象;

常用方法:

非静态方法:

1, string toString();//返回枚举常量的名称;

2, int ordinal();//返回枚举值在枚举类中的顺序,按对应的顺序排;

3, class getClass();//获取对应的类名;

4, string name();//返回次枚举常量的名称,在其枚举声明中对其进行声明;

静态方法:

1, valueOf();//转为对应的枚举对象,将字符串转为对象;

2, values();//获取所有的枚举对象元素;

示例:

package 加强Day01.黑马;

public class EnumTest {

public static void main(String[] args) {

WeekDay weekday = WeekDay.MON;

System.out.println(weekday);//打印枚举常量名

System.out.println(weekday.name());//对应对象名

System.out.println(weekday.ordinal());//此对象在枚举中的次序

System.out.println(weekday.getClass());//对应类

System.out.println(WeekDay.valueOf("SUN"));//静态方法,将字符串转换为枚举常量

System.out.println(WeekDay.values().length);//静态方法,获取所有的枚举元素,打印其长度即个数

}

//定义枚举内部类

public enum WeekDay{

SUN,MON,TUE,WED,THI,FRI,SAT;//分号可有可无,若下面还有其成员必须用分号;

}

}

带有构造函数的枚举(JDK5

枚举的书写规则及注意点:

1, 枚举成员常量必须位于枚举类的其他所有成员之前;

2, 若枚举成员常量列表之后,存在其他非枚举成员,那么必须用分号与前面的枚举成员分开。

3, 在定义枚举构造方法时候,必须使用私有private做访问修饰符;

4, 在调用构造方法时候,需要在枚举成员后加上“()”;

默认定义枚举常量,和添加()没有区别,调用的都是枚举类的空参数构造函数;

5, 若枚举成员后面是带有实参数的(),调用的就是知道枚举类型的构造函数。

6, 因为枚举成员默认的类型是public final static 类型,所以枚举类型已加载到内存,相应的静态函数就会调用枚举类的构造函数。

示例:

//定义枚举内部类

public enum WeekDay{

SUN(),MON(1),TUE,WED,THI,FRI,SAT;//分号可有可无,若下面还有其他方法成员时必须加上;

private WeekDay(){

System.out.println("first");

}

private WeekDay(int day){

System.out.println("second");

}

}


五、增强for循环

增强for循环,可以用更简单地方式来遍历数组和Collection等类型的对象。

增强for循环的语法为:for(type 变量名:集合变量名){...}

例如:

List<Integer> list = new ArrayList<Integer>();  

        list.add(1);  

        list.add(2);  

        list.add(3);  

        for (int i : list) {  

            System.out.println(i);  

        } 


能够使用加强for循环遍历的可以归纳为两种:

1、数组

2、所有实现了Iterable接口的类

我们一些常用CollectionListQueueSet接口也都实现了Iterable接口,同理他们的所有子类都可以利用加强for循环来进行遍历。它们运用加强for循环遍历其实是利用了底层的iterator迭代器。

 List<Integer> list = new ArrayList<Integer>();  

        list.add(1);  

        list.add(2);  

        list.add(3);  

        Iterator<Integer> iterator = list.iterator();  

        while (iterator.hasNext()) {  

            System.out.println(iterator.next());  

        }  

   其实这段代码跟之前使用增强for循环的代码是一样的。

增强for的不足:不能在增强循环里动态的删除集合内容;不能获取下标


六、泛型

  

jdk1.4版本之前,容器什么类型的对象都可以存储。但是在取出时。需要用到对象的特有内容时,需要做向下转型。

但是对象的类型不一致,导致了向下转型发生了ClassCastException异常。

为了避免这个问题,只能主观上控制,往集合中存储的对象类型保持一致。

JDK1.5以后解决了该问题,在定义集合时,就直接明确集合中存储元素的具体类型。

这样,编译器在编译时,就可以对集合中存储的对象类型进行检查。

一旦发现类型不匹配,就编译失败。这个技术就是泛型技术。

好处:

1,将运行时期的问题转移到了编译时期,可以更好的让程序员发现问题并解决问题。

2,避免了向下转型的麻烦。

 

总结:

泛型就是应用在编译时期的一项安全机制。

 

泛型的擦除:

编译器通过泛型对元素类型进行检查,只要检查通过,就会生成class文件,但在class文件中,就将泛型标识去掉了。

 

泛型的表现:

泛型技术在集合集合框架中应用的范围很大。

什么时候需要写泛型呢?1,只要看到类,或者接口在描述的时右边定义<>,就需要泛型。

其实是,容器在不明确操作元素的类型的情况下,对外提供了一个参数<>

使用容器时,只要将具体的类型实参传递给该参数即可。

说白了,泛型就是,传递类型参数。

 


 ---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


0 0
原创粉丝点击