1.泛型(Generic)
JDK1.5后提供的新特性.用于解决安全问题,是一个类型安全机制 Generic Generic
好处:
1.将运行时期出现问题的ClassCastException,转移到了编译时期,方便于程序员解决问题,让运行时期问题减少,安全
2.避免了类型转换的麻烦
泛型格式:通过<>来定义要操作的引用数据类型.
在使用java提供的对象时,什么时候写泛型呢?
通常在集合框架中很常见
只要见到<>就要定义泛型
其实<>就是用来接收类型的
当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可.
什么时候定义泛型类?
当类中药操作的引用数据类型不确定时,早期定义Object来完成扩展,现在定义泛型来完成扩展
泛型类:
定义的泛型,在整个类中有效,如果被方法使用,那么泛型类的对象要明确要操作的具体类型后,所有要操作的类型就已经固定了,
泛型方法:
为了让不同方法操作不同类型,而且类型还不确定,那么可以将泛型定义在方法中
例如: public <T> void show(T t){}
特殊之处:::
静态方法不可以访问类上定义的泛型
如果静态方法操作的引用数据类型不确定,可以讲泛型定义在方法上
如:public static <W> void fun(W t){}
泛型接口:
可将泛型定义在接口上,使用的时候,实现类可以传入具体类型参数,如果实现类也不知道具体类型,可将将泛型传递下去,让使用者传参
泛型高级应用:
? 通配符,也可以理解为占位符
泛型的限定: 是为了泛型扩展用的
? extends E : 可以接收E类型或者E的子类型 上限
? super E :可以接收E类型或者E的父类型 下限
2.For-Each循环
For-Each循环得加入简化了集合的遍历。假设我们要遍历一个集合对其中的元素进行一些处理。典型的代码为:
void processAll(Collection c){
for(Iterator i=c.iterator(); i.hasNext();){
MyClass myObject = (MyClass)i.next();
myObject.process();
}
}
使用For-Each循环,我们可以把代码改写成:
void processAll(Collection<MyClass> c){
for (MyClass myObject :c)
myObject.process();
}
这段代码要比上面清晰许多,并且避免了强制类型转换。
格式:
for(数据类型 变量名:被遍历的集合(Collection)或数组){ }
对集合进行遍历.只能获取元素,但是不能对集合进行操作.
迭代器除了遍历,还可以进行remove集合中元素的动作,如果使用ListIterator,还可以在遍历过程中进行增删改查的操作
传统for和高级for有什么区别?
高级for有一个局限性,必须有被遍历的目标.比如:把"hello world"打印100次
建议:在遍历数组时,还是使用传统for,因为有角标
3.自动装箱/拆箱(Autoboxing/unboxing)
基本数据类型对象包装类
byte Byte
short Short
int Integer
long Long
boolean Boolean
float Float
double Double
char character
基本数据类型对象包装类的最常见作用.
就是用于基本数据类型和字符串类型之间做转换
基本数据类型转成字符串
基本数据类型+"";
基本数据类型.toString(基本数据类型值);
如:Integer.toString(34);//将34变成"34"
字符串转成基本数据类型
1. xxx a = Xxx.parseXxx(str);
如: int a = Integer.parseInt("a12");//必须传入数字格式的字符串
double d = Double.parseDouble("12.22");
boolean b = Boolean.parseBoolean("true");
2.先通过Integer构造方法转成Integer对象,再调用Integer.intValue()方法
如:Integer i = new Integer("23");
int num = i.intValue();
Integer x = new Integer(4);
Integer x = 4; //自动装箱 //隐式的new Integer(4);
x = x/*x.intValue()*/+2; //x+2:x 进行自动拆箱,变成了int类型,和2进行加法运算,再将和进行装箱赋给x
Integer m = 128;
Integer n = 128;
m==n -->false; //可以理解;因为m和n是两个对象
Integer a = 127;
Integer b = 127;
a==b -->true; //因为a和b指向了同一个Integer对象,因为当数值在byte范围内,对于新特性,如果该数值已经存在,则不会在开辟新的空间
4.枚举(Enums)
JDK1.5加入了一个全新类型的“类”-枚举类型。为此JDK1.5引入了一个新关键字enmu. 我们可以这样来定义一个枚举类型。
public enum Color
{
Red,
White,
Blue
}
然后可以这样来使用Color myColor = Color.Red.
枚举类型还提供了两个有用的静态方法values()和valueOf(). 我们可以很方便地使用它们,例如
for (Color c : Color.values())
System.out.println(c);
5.可变参数(Varargs)
可变参数使程序员可以声明一个接受可变数目参数的方法。注意,可变参数必须是函数声明中的最后一个参数。假设我们要写一个简单的方法打印一些对象,
util.write(obj1);
util.write(obj1,obj2);
util.write(obj1,obj2,obj3);
在JDK1.5之前,我们可以用重载来实现,但是这样就需要写很多的重载函数,显得不是很有效。如果使用可变参数的话我们只需要一个函数就行了
public void write(Object... objs) {
for (Object obj: objs)
System.out.println(obj);
}
在引入可变参数以后,Java的反射包也更加方便使用了。对于c.getMethod("test", new Object[0]).invoke(c.newInstance(), new Object[0])),现在我们可以这样写了c.getMethod("test").invoke(c.newInstance()),这样的代码比原来清楚了很多。
其实就是数组参数的简写形式,不用每一次都手动的建立数组对象,只要将要操作的元素作为参数传递即可,隐式将这些参数封装成了数组
注意:在使用时,可变参数一定要定义在参数列表的最后面
6.静态导入(Static Imports)
要使用用静态成员(方法和变量)我们必须给出提供这个方法的类。使用静态导入可以使被导入类的所有静态变量和静态方法在当前类直接可见,使用这些静态成员无需再给出他们的类名。
import static java.lang.Math.*;
r = sin(PI * 2); //无需再写r = Math.sin(Math.PI);
import static java.util.Arrays.*;//导入的是Arrays这个类中的所有静态成员
//int[] arr = {3,1,5}
//Arrays.sort(arr);
//Arrays.binarySearch(arr,2);
//Arrays.toString(arr);// Object里也有toString方法.
当方法重名时,需要指定所属的对象或者类
过度使用这个特性也会一定程度上降低代码地可读性。