JDK1.5java新特性
JDK1.5java增加的新特性:
自动装箱/拆箱 增强for 泛型 枚举 静态导入 可变参数
1 自动装箱/拆箱
* JDK1.5允许开发人员把一个基本类型直接赋给对应的包装类变量或者赋给Object类型的变量,这个过程称为自动装箱。
* 自动装箱和自动拆箱相反,即把包装类对象直接赋给一个对应的基本类型变量。
也就是基本类型与其对应的引用类型之间的转换,但是不能乱用,一般我们要采用基本类型,如果在使用时不注意,可能会造成程序低效率运行。
int ----- Integer
float ----- Float
double ---- Double
char ------- Character
boolean ---- Boolean
short ---- Short
long ---- Long
byte ---- Byte
比如:
Long sum = 0;
for(long i =0;i<10000;i++){
sum += i;
}
此处造成程序低效率就在于频繁的进行拆箱装箱操作。注意sum被定义成了Long而不是long。
还有两个高精度的类:
BigInteger
BigDecimal
2 增强for
优缺点:
优点:遍历更简单,在集合遍历中增强for就是代替迭代器的
弊端:增强for的目标不能为null(即数组或集合不能为null),所以在遍历之前需要进行判断
格式:
for(元素数据类型 变量:数组或集合){
....................................
使用变量,该变量就是集合或者数组中的元素
}
举例:
String[] names = {"小明","小李","小王"};
for(String name : names){
System.out.println("hello "+name);
}
3 泛型
引入泛型的好处:
1)去除了原先必须的冗长的强制类型转换
2)能够在编译期检测出错误,不至于在运行时才发现,消除了潜在的错误,提高代码运行的可靠性。
3)使用XJad.exe反编译工具可以看到,在编译期间泛型被擦除。
泛型基本应用:
1)泛型类
*把泛型定义在类上
*格式:public class 类名<泛型类型1.....>
*注意:泛型类型必须是引用类型
2)泛型方法
* 把泛型定义在方法上:方法可以接收任意类型
* 格式:public<泛型类型> 返回类型 方法名(泛型类型)
3)泛型接口
* 把泛型定义在接口上
* 格式:public interface 接口名<泛型类型1.....>
例1:一个简单的泛型类
package basic.demo;
public class FanTypeClass<T>{
private T obj;
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
}
测试类:
package basic.demo;
public class FanTypeDemo {
public static void main(String[] args) {
FanTypeClass<String> obj1 = new FanTypeClass<String>(); //使用泛型
obj1.setObj("hello"); //这时候set方法接收的参数必须是String,如果不传该类型,在编译期就会报错
String s = obj1.getObj(); //这种方式下不需要强转
System.out.println(s);
FanTypeClass obj2 = new FanTypeClass(); //没使用泛型
obj2.setObj(3);
int num = (int) obj2.getObj(); //需要进行强转,如果不小心写错了就会产生ClassCastException,即类型转换异常
String num = (String)obj2.getObj(); //这样写在编译期并不会报错,但是一旦执行就会产生类型转换异常
System.out.println(num);
}
}
例2:泛型方法的使用
package basic.demo;
public class FanTypeMethod {
public <T> void show(T t){
System.out.println(t);
}
}
测试类:
package basic.demo;
public class FanTypeDemo {
public static void main(String[] args) {
FanTypeMethod ft = new FanTypeMethod();
ft.show("hello");
ft.show(100);
ft.show(true);
}
}
输出结果:
hello
100
true
例3 泛型接口
分为两种用法:子类实现时已知将来使用类型和子类实现时未知使用类型(这一种常见)
package basic.demo;
public interface FanTypeInter<T>{
public abstract void show(T t);
}
package basic.demo; //子类未知要使用的类型,故还是用泛型T
public class FanTypeInterImpl<T> implements FanTypeInter<T> {
@Override
public void show(T t) {
System.out.println(t);
}
}
测试:
package basic.demo;
public class FanTypeDemo {
public static void main(String[] args) {
FanTypeInter<String> fti1 = new FanTypeInterImpl<String>();
fti1.show("hello");
FanTypeInter<Integer> fti2 = new FanTypeInterImpl<Integer>();
fti2.show(100);
}
}
泛型高级应用(通配符):
1)泛型通配符 <?>
*任意类型,如果没有明确,那么就是Object以及任意的java类
2)? extends E
* 向下限定,E及其子类
3)? super E
* 向上限定,E及其父类
例:理解高级应用:红色标注皆为错误用法
package basic.demo;
import java.util.ArrayList;
import java.util.List;
public class FanTypeSeniorDemo {
public static void main(String[] args) {
//泛型如果明确写,必须前后一致
// List<Object> list1 = new ArrayList<Object>();
// List<Object> list2= new ArrayList<Person>(); //error
// List<Object> list3 = new ArrayList<Student>(); //error
// List<Object> list4 = new ArrayList<Teacher>(); //error
//?表示任意类型都是可以的
// List<?> list1 = new ArrayList<Object>();
// List<?> list2= new ArrayList<Person>();
// List<?> list3 = new ArrayList<Student>();
// List<?> list4 = new ArrayList<Teacher>();
//? extends E 向下限定:E及其子类
// List<? extends Person> list1 = new ArrayList<Object>(); //error
// List<? extends Person> list2= new ArrayList<Person>();
// List<? extends Person> list3 = new ArrayList<Student>();
// List<? extends Person> list4 = new ArrayList<Teacher>();
//? super E 向上限定 E及其父类
List<? super Person> list1 = new ArrayList<Object>();
List<? super Person> list2= new ArrayList<Person>();
List<? super Person> list3 = new ArrayList<Student>(); //error
List<? super Person> list4 = new ArrayList<Teacher>(); //error
}
}
class Person{
}
class Student extends Person{
}
class Teacher extends Person{
}
4 枚举
关键字:Enum,用于定义一个枚举类
为什么需要枚举?
一些方法在运行时,它需要的数据不能是任意的,而必须是一定范围内的值,此类问题在JDK5以前采用自定义带有枚举功能的类解决,Java5以后可以直接使用枚举予以解决。
枚举类具有如下特性:
枚举类也是一种特殊形式的Java类。
枚举类中声明的每一个枚举值代表枚举类的一个实例对象。
与java中的普通类一样,在声明枚举类时,也可以声明属性、方法和构造函数,但枚举类的构造函数必须为私有的(这点不难理解)。
枚举类也可以实现接口、或继承抽象类。
JDK5中扩展了switch语句,它除了可以接收int, byte, char, short外,还可以接收一个枚举类型。
若枚举类只有一个枚举值,则可以当作单例设计模式使用。
Java中声明的枚举类,均是java.lang.Enum类的子类,它继承了Enum类的所有方法。
常用方法:
name():返回此枚举常量的名称,在其枚举声明中对其进行声明。
ordinal():返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。也可以称为索引
valueOf(Class enumClass, String name)
values() 此方法虽然在JDK文档中查找不到,但每个枚举类都具有该方法,它遍历枚举类的所有枚举值非常方便。
5 静态导入
可以直接导入到方法的级别。
格式:import static 包名....类名.方法名;
注意:
*方法必须是静态的
*如果有多个同名的静态方法,容易不知道使用谁??这个时候要使用该特性,需要加前缀。由此可见,意义不大。所以一般不用,仅需知道就行。
例1:使用静态导入,使用静态方法时直接使用。
package basic.demo;
import static java.lang.Math.max;
import static java.lang.Math.min;
public class StaticImportDemo {
public static void main(String[] args) {
int num1 = 23;
int num2 = 30;
max(num1,num2);
min(num1,num2);
}
}
例2:编写重名的静态方法,然后一起在StaticImportDemo使用:
package basic.demo;
public class MyMath {
public static int max(int num1,int num2){
return num1>num2?num1:num2;
}
public static int min(int num1,int num2){
return num1>num2?num2:num1;
}
}
package basic.demo;
import static java.lang.Math.max;
import static java.lang.Math.min;
import static basic.demo.MyMath.max;
import static basic.demo.MyMath.min; //使用都加前缀了,也就不需要静态导包了
public class StaticImportDemo {
public static void main(String[] args) {
int num1 = 23;
int num2 = 30;
java.lang.Math.max(num1,num2); //必须加包名前缀,否则报错
basic.demo.MyMath.min(num1,num2);//必须加包名前缀,否则报错,但是这样一加前缀就没有导包的意义了。。。。。
}
}
6 可变参数
Effective Java不建议使用该特性,而且在java编程思想中也说了此特性的隐患。
*定义方法的时候不知道定义多少个参数,故引入可变参数的概念。
使用格式:
* 修饰符 返回值类型 方法名(数据类型...变量名){}
注意:
* 这里的变量其实是一个数组
*如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个,否则编译器报错。
举例:
*Arrays工具类中的一个方法:
public static <T>List<T> asList(T...a)
例1:简单使用:
package basic.demo;
public class ChangeParaDemo {
public static void main(String[] args) {
int[] data = {1,2,3,4};
System.out.println(sum(data));
int sum = sum(2,3,4,5);
System.out.println(sum);
sum = sum(2,5);
System.out.println(sum);
}
private static int sum(int...num) {
int result = 0;
for(int i:num){
result += i;
}
return result;
}
}
例2 方法中有多个参数:java在编译器期间就强调可变参数必须在最后的位置。
package basic.demo;
public class ChangeParaDemo {
public static void main(String[] args) {
int sum = sum(100,1,2,3,4);
System.out.println(sum); //如果把可变参数放在方法参数的最后,结果是10
int sum = sum(1,2,3,4,100);
System.out.println(sum); //如果可变参数放在前面,会报错
}
private static int sum(int special,int...num) {
int result = 0;
for(int i:num){
result += i;
}
return result;
}
//error: 错误写法
//出错原因,因为可变参数变量其实是一个数组,如果把可变参数放在前面,则special变量被视为数组的一部分,也就是说你只传了一个参数,和原方法参数个数不一致
private static int sum(int...num,int special) {
int result = 0;
for(int i:num){
result += i;
}
return result;
}
}