----------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -----------
JDK1.5的新特性——枚举类型
一、枚举基本使用
1、J2SE5.0中新增了枚举类型,用户可以使用该功能取代以往常量定义的方式,同时枚举类型还赋予程序在编译时检查的功能。
在学习使用枚举类型之前用户通常将常量放置在接口中,以便于在程序中能够直接使用,并且该常量不能被修改,因为在接口中定义该常量时,该常量的修饰符为final与static。
常规定义常量:
public interface Constants{public static final int Con_stants_A=1;public static final int Con_stants_B=12;}
自JDK1.5版本新增枚举类型后,枚举类型就逐渐取代了这种常量定义方式。
使用枚举类型定义常量:
public enum Constants{Contants_A,Contants_B,Constants_C}
其中,enum是定义枚举类型的关键字。
当需要在程序中使用该常量时,可以使用Constants.Constants_A来表示。
2、好处:在编译时期就会发现错误,表明值不符合,减少了运行时期的错误。
3、枚举类是一个class,而且是一个不可被继承的final类,其中的元素都是类静态常量
4、常用方法:
构造器:
1)构造器只是在构造枚举值的时候被调用。
2)构造器只有私有private,绝不允许有public构造器。这样可以保证外部代码无法重新构造枚举类的实例。因为枚举值是public static final的常量,但是枚举类的方法和数据域是可以被外部访问的。
3)构造器可以有多个,调用哪个即初始化相应的值。
例如:
enum枚举类型名称{
非静态方法:(所有的枚举类都继承了Enum方法)
1)String toString() ;//返回枚举量的名称
2)int ordinal() ;//返回枚举值在枚举类中的顺序,按定义的顺序排
3)Class getClass() ;//获取对应的类名
4) String name();//返回此枚举常量的名称,在其枚举声明中对其进行声明。
静态方法:
1)valueOf(String e) ;//转为对应的枚举对象,即将字符串转为对象,而CompareTo()方法用于比较两个枚举类型对象定义时的顺序。
2)values() ; 枚举类型实例包含一个values()方法,该方法将枚举类型的成员变量实例以数组方式返回,也可以通过该方法获取枚举类型的成员。
5、演示
6、枚举类型的优点
枚举类型提供了一种用户友好的变量定义方法,枚举了某种数据类型所有可能出现的值。
它的优点表现在:
1)类型安全
2)紧凑有效的数据定义
3)可以和程序其他部分交互
4)运行效率高
二、枚举的高级应用
1、枚举就相当于一个类,其中也可以定义构造方法、成员变量、普通方法和抽象方法。
2、枚举元素必须位于枚举体中的最开始部分,枚举元素列表的后要有分号与其他成员分隔。把枚举中的成员方法或变量等放在枚举元素的前面,编译器报告错误。
3、带构造方法的枚举
1)构造方法必须定义成私有的
2)如果有多个构造方法,该如何选择哪个构造方法?
3)枚举元素MON和MON()的效果一样,都是调用默认的构造方法。
4、带方法的枚举
演示:
说明: 1)类的方法返回的类型可以是本类的类型
2)类中可定义静态常量,常量的结果就是自己这个类型的实例对象
3)枚举只有一个成员时,就可以作为一种单例的实现方式。
4)所有的枚举都继承自java.lang.Enum类。由于Java不支持多继承,所以枚举对象不能再继承其他类。
5)switch语句支持int,char,enum类型。
高级for循环
1、概述
Iterator 不好写,1.4版本iterator方法是定义在collection里面的,可是1.5版本后,collection继承了Iterable<E>.这个接口就是将迭代方法抽取出来了。
它不但是把这个方法抽离出来集合框架,提高了扩展性,它还给集合框架提供了新功能就是高级for循环
查阅api文档,
public ingerface Iterable<T>
实现这个接口允许对象成为“foreach”语句的目标。
2、格式
高级for循环
格式
For(数据类型 变量名:被遍历的集合(Collection)或者数组)
示例:
假如al是一个ArrayList集合,那么代码
For(String s : al)//这个s第一次就指向了al的第一个元素“abc1”,并变化
{System.out.println(s)};
3、高级for循环的局限性
高级for循环的局限性:不能对集合中的元素做修改动作。
而迭代器:至少还有remove可以用。而如果使用列表迭代器,增删改查都可以使用。
总结:
对集合进行遍历,只能获取集合元素,但是不能对集合进行过多操作
迭代器:除了遍历,还可以进行remove集合中元素的动作,原集合改变。
如果使用ListIterator,还可以在遍历过程中对集合进行增删改查的动作。
4、高级for循环和传统for循环的区别:
高级for有一个局限性:必须有被遍历的目标。
例如:我们把hello world打印100次,就只能使用传统for循环。
建议在遍历数组的时候,还是希望使用传统for循环。因为传统for循环可以定义角标。
问题:
HashMap<Integer,String> hm=new HashMap<Integer,String>();
hm.put(1,“a”);
hm.put(2,“b”);
hm.put(3,“c”);
我想把hm里面的元素都取出来,用高级for如何实现。
一种方式:
Set<Integer> keySet=hm.keySet();
for(integer i:keySet)
{
System.out.println(i+”::”+hm.get(i));
}
第二种方式:
Set<Map.Entry<integer,String>> keySet=hm.entrySet();
for(Map.Entry<integer,String> me:entrySet)
简写
for(Map.Entry<Integer,String> me:hm.entrySet())
{
System.out.println(me.getKey()+”-----”+me.getValue());
}
但是如果集合里面没有定义泛型,不能使用for循环,很简单,都不知道什么类型,如何定义类型引用呢?详解在可变参数介绍中。
可变参数
一、概述
可变参数:其实就是上一种数组参数的简写方式,不用每一次都手动建立数组对象。只要将要操作的元素作为参数传递即可。隐式将这些参数封装成数组。由虚拟机完成。
想传几个参数,就定义为几个元素的数组。不传,视为长度为0的数组。
二、优点:简化开发代码,提高开发速度。
方法的可变参数:在使用时要注意,可变参数一定要定义在参数列表最后面。
三、代码演示
传统的方法:
class ParamMethodDemo
{
public static void main(String[]args)
{
show(3,4);
}
public static void show(int a,int b)
{
System.out.println(a+”,”+b);
}
public static void show(int a,int b,int c)
{.....}
}
简单点的
public static void show(int []arr)
{}
新特性是这样的。
public static void show(int...arr)
{
System.out.println(arr);
}
注意:当方法中有多个参数时,虚拟机会先把前面的匹配完,剩下的都给后面的了。
举例:
public static void show(String str,int...arr)
{
System.out.println(arr.length);
}
public static void main(String[]args)
{
show(“hha”,2,3,4,5);
}
编译通过,结果是 4
静态导入
一、概述
Jdk1.5版本的新特性。StaticImport 静态导入,用来导入静态工具类
举例:
improt java.util.*;
import static java.util.Arrays.*;//导入的是Arrays这个类中的所有静态成员。
需求:
improt java.util.*;class StaticImport{public static void main(String[]args){int[]arr={3,1,5}Arrays.sort(arr);int index=Arrays.binarySearch(arr,1)System.out.println(Arrays.toString(arr));System.out.println("Index="+index);}}
我们每次写工具类的时候,都要写类名.
如果不导入包,我们还要写 java.util.Arrays.sort(arr);导入包后,就不需要写包。
那么如果,我们把工具类Arrays导入的话,我们是不是就不用写类名.了?
因为它没有对象。不需要对象,就不需要特有数据啊。
静态导入:
Improt java.util.*;
importStatic java.util.Arrays.*;//导入的是Arrays这个类中的所有静态成员。
接下来,我们就不需要写Arrays.
import java.util.*;import static java.util.Arrays.*;//导入的是Arrays这个类中的所有静态成员。//接下来,我们就不需要写Arrays.class StaticImport{public static void main(String[]args){int[]arr={3,1,5}sort(arr);int index=binarySearch(arr,1)System.out.println(Arrays.toString(arr));System.out.println("Index="+index);}}
运行ok
接下来,我们把 System.out.println(Arrays.toString(arr));这条语句中的Arrays.也去掉,
编译,失败
无法将java.lang.object中的toString()应用于int[]
为什么呢?
因为我们知道class StaticImport 这个类首先继承的是Object类。它会认为,使用的是Object类中的toString方法。而Object类中的toString方法是没有参数的。
2、注意事项
当类名重名时,需要制定具体的包名。
当方法重名时,要指定具备所属的对象或者类。
基本数据类型的自动拆箱与装箱
1、自动装箱:Integer iObject = 3;
2、自动拆箱:iObject + 2;
3、对于基本数据类型的说明:整数在-128 ~ 127之间的数,包装成Integer类型对象,会存入常量池中的缓存,再创建一个对象的时候,如果其值在这个范围内,就会直接到常量池中寻找,因为这些小数值使用的频率很高,所以缓存到常量池中,被调用时就方便很多。
4、享元模式:
1)概述:有很多个小的对象,他们有很多相同的属性,把属性相同的部分变为同一个对象,这些属性称为内部状态。那些不同的属性,把他们变成方法的参数,称之为外部的状态。这种优化内存,只创建一个对象的模式,称之为享元模式。例如:Integer对象中对象取值范围在-128~127时,其值相同的对象想等,因为这些小的数被缓存在一个池中,被调用的频率较高,所以通常在池中取,从而导致对象相同。这就是典型的享元设计模式。
2)应用:
(1)word中输入英文字母,可创建26对象,每个对象值是出现的位置不同(坐标),所以可用一个对象调用位置的方法:如,字母i:i.display(intx,inty),将高度重复使用的char类型的字母i封装成一个对象使用。
(2)图标:window下的文件夹图标,只有名称这个属性不同,包含了很多其他相同的属性,那么可以应用享元模式。
3)valueOf(int x):Integer中静态方法,将一个整数转换为Integer,即把基本数据类型变为包装类。