新特性(JDK1.5)
1.可变参数:位移并且只有一个
引入一个参数计算任意整数的相加结果
以前通常用一个整形数组,接收一个匿名数组,然后将数组的值相加
现在,有一个新特性,可变参数
如果参数列表有String和可变参数时,可变参数一定写到最后面,因为它的长度不确定并且能有一个可变参数
2.for-each
形式 for(Object i:数组/集合){}
可以用break终止,
3.静态导入(不推荐使用,因为引用静态方法不需要类名,不知道是哪个类的方法)
import static java.util.Array.*;//倒入Array类中的所有静态方法
import static 包名.类名.*;
泛型
1.在描述一个商品时 我们通常会有商品的名称,和价格 有小数和整数
这时我们会将价格设置成Object ,在取出的时候进行向下转型 但是这时候就会产生危险,如果错误的向下转型两个毫无关系的类,会产生 java.lang.ClassCastException (非受查异常,在运行时才可以发现)
class Computer{
private String Name;
private Object price;
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public Object getPrice() {
return price;
}
public void setPrice(Object price) {
this.price = price;
}
}
public class Fanxin {
public static void main(String[] args) {
Computer com = new Computer();
com.setName("Apple");
com.setPrice(1900);
Computer com2=new Computer();
com2.setPrice("lenovo");
com2.setPrice(1243.3);
Integer p1=(Integer) com.getPrice();
Integer p2=(Integer) com2.getPrice();
System.out.println(p1);
System.out.println(p2);
}
}
所以 引入一个新的 特性
**
泛型 :类型守门员
**
修饰符<>,在使用的时候在定义类型
重点:所有的泛型只接受包装类
1(泛型类)
class Computer<T>{}
class IMessage<T,E>{}
间括号<>里面的T 叫做类型参数;可以是任何值
注:看是不是泛型类不是看类型参数耳饰看有没有<>,括号里面的类型参数可以有多个
在实例化时的具体方法
Computer<具体的类型> c1=new Computer<具体类型>();
//在JDK1.7后 后面的类型可以省略
Computer<具体的类型> c1=new Computer<>();
//也可以不写基本类型 ,这样默认为类型参数默认Object
Computer c1=new Computer<>();
关键
2.泛型方法;同样看是不是泛型方法也不是看可变参数 而是看方法体上有没有<>符号
class Computer<T>{
public <T> T print(T e){
return e;
}
}
注:泛型方法中的可变参数优先,即泛型方法以自己定义的参数为准
3.泛型接口;
public interface IMessage <T>{
T print();
}
子类实现泛型接口
1.不进行类型的声明:默认Object
public class p implements IMessage {
@Override
public Object print() {
return null;
}
}
2.进行类型的声明:这时 T为String
class I implements IMessage<String>{
@Override
public String print() {
return null;
}
}
3.继续保留泛型 这个时候子类依旧是个泛型类 需要在使用时声明类型
class F<T> implements IMessage<T>{
@Override
public T print() {
return null;
}
}
注:上述1、2 的两种方式 子类都不再是泛型类,进行实例化的时候直接实例化就可以了
3、子类依旧是一个泛型类,所以实例化的时候依旧要遵守泛型类的实例化方式;
通配符
在Object进行对不确定数据的接收前,我们如果要将一个数据传入方法中,只需要Object类接收就可以,因为发生天然的向上转型;
但是为了避免 java.lang.ClassCastException,我们引入了泛型,但是又会后一个问题,就是参数统一化;
以前只需要用Object 接收 类的对象就可以了 ;
代码:
class Person <T>{
private T Name;
public Person(T name) {
Name = name;
}
public T getName() {
return Name;
}
}
public class Test {
public static void main(String[] args) {
Person<String> per1 = new Person<>("1");
print(per1);
Person<Integer> per2 =new Person<>(2);
}
public static void print(Person<String> per){
System.out.println(per.getName()+" "+per.getAge());
}
//--------------------------错-----------------------
//下面的print方法也不是重载,因为参数完全一样,不能通过编译
public static void print(Person<Integer> per){
System.out.println(per.getName()+" "+per.getAge());
}
//--------------------------------------------------
}
上面代码 print方法的参数表完全一样,不是重载,如果要这样进行类型的接收的话,就要再写一个方法
如果现在有许多个类型不同对象,那么你就要写相同多的方法来接收这个对象,在传参数时还有特别注意:
所以我们引入下面的概念:
通配符:
第一种 <?> 作用在方法上,可以接收任意类型
public static void print(Person<?> per){//接收任意数据类型
System.out.println(per.getName()+" "+per.getAge());
}
第二种 <? extends 类> 作用在类和方法上 表示接收的类型必须是 extends后面那个类及其子类,规定上限
//方法
public static void print(Person<? extends Number> per ){//表示只能接收 基本数据类型包装类
}
//类
class Person<? extends Number>{}
第三种<? super 类> 作用在方法上 表示接收类型必须是 super后面那个类及其父类,规定下限
public static void print(Person<? extends String> per ){//表示只能接收 String类和他的父类
}
现在我们来考虑一下 上面三种通配符,哪一种可以在方法内使用per的setter()方法修改对象属性值
<?>:不能 因为传入的类型不确定,所以无法用setter修改 <? extend Number> 不能 ,只确定父类,向下转型不确定,依旧无法进行属性值的修改 (在编译器就会有红色波浪线) <? super String> 可以,确定子类,设置了上限,发生天然的向上转型,所以可以进行属性值的修改; **类型擦除** 在JVM中时没有泛型这一个概念的,如果设置上限<? extend Number>就会被擦除成相应的上限, 如果没有设置上限,那么直接擦除成Object类,目的是为了向下兼容;