泛型的理解和好处
在进行集合使用的时候存在一种隐患:
引例说明,集合中存放一类猫,再进行遍历时,属于Object的子类,可以正常向下转型,可如果程序员失误存入了一只狗,(这时编译器无法发现错误)在转型时就会出现异常:**ClassCastException :类型转换异常 **
Car car = new Car("奔驰", 6200000);
Car car1 = new Car("宝马", 6200000);
Cat cat = new Cat("画虎", 6);
ArrayList<Object> objects = new ArrayList<Car>();
objects.add(car);
objects.add(car1);
objects.add(cat);
for (Object e :
objects) {
Car car = (Car)e;//此处有可能就出现了转换异常
System.out.println(car);
}
传统的变成方式存在的这种类似弊端:
- 不能对加入到集合中的数据进行约束(不安全)
- 遍历的时候,需要进行类型转换,如果集合的数据很多,对效率影响很大
泛型使程序员在使用集合的时候更加规范,加入泛型之后,如果出现错误,会在编译期就会报错,提醒程序员
Car car = new Car("奔驰", 6200000);
Car car1 = new Car("宝马", 6200000);
Cat cat = new Cat("画虎", 6);
ArrayList<Car> objects = new ArrayList<Car>();//在这里加入数据约束
objects.add(car);
objects.add(car1);
objects.add(cat);//这里就会报编译错误
for (Object e :
objects) {
Car car = (Car)e;
System.out.println(car);
}
好处
对数据进行类型约束,减少错误
遍历的时候可以直接取出该类型的元素,减少类型转换的次数,效率更高
不再提示编译警告
ArrayList<Car> objects = new ArrayList<Car>();
for (Car e :
objects) {
System.out.println(e);
}
泛型介绍
-
泛型又称参数化类型,是JDk5.0出现的新特性,解决数据类型的安全性问题
-
在类声明或实例化时只要制定好需要的具体类型就可
-
java泛型可以保证如果程序在编译时没有警告,运行时就不会产生
ClassCastException :类型转换异常 ,同时代码更加简洁健壮
泛型的作用时:可以在类声明时通过一个标识表示类中某个属性的类型,或者某个方法的返回值的类型,或者参数类型。(编译期间)
class Person<E>{ //e该数据类型是在定义Person对象的时候指定的,即在编译期间就确定E是什么类型 默认是Object类型
E s;
public Person(E s){//e也可以是参数类型
this.s = s;
}
public E f(){//返回类型使用e
return s;
}
}
//使用方式
Person person = new Person<String>();//意思是,在使用的时候,class中的所有e 都是String类型,可以返回任何类型。如果想看E是什么类型,可以用 .getClass()方法看。
泛型语法
泛型的声明
interface 类名<T>{}和interface 类名<K,V>{}
K,T,v不代表值,只代表类型
任何字母都可以使用
例子:
HashMap<String,Student> hm =new HashMap<String,Student>();
//填入别的就会报编译错误
使用细节
- 泛型在使用的时候里边只能放入引用数据类型
- 再给泛型指定泛型之后,就可以传入该类型的子类或者该类类型
class A{}
class B extends A{}
class Cat<E>{}
Cat<A> cat = new Cat<A>(new A);
Cat<A> cat1 = new Cat<A>(new B);//编译都正确
- E不指定类型的时候 默认是Object类型
自定义泛型
泛型类
自己创建一个类使用了泛型,就被称为自定义泛型
class Person<E,R...>{ //e该数据类型是在定义Person对象的时候指定的,即在编译期间就确定E是什么类型 默认是Object类型
E s;
public Person(E s){//e也可以是参数类型
this.s = s;
}
public E f(){//返回类型使用e
return s;
}
}
注意细节
- 普通成员可以使用泛型(属性,方法)
- 使用泛型的数组,不能初始化
- 静态方法中不能使用类的泛型:因为静态是在类加载的时候就实现的,它的加载时间比类创建之前,会报错
- 泛型的类型是在创建对象时确定的
- 如果在创建对象时,欸有指定类型,默认时Object
泛型接口
自己创建一个接口
interface 接口名<T,R...>{}
细节
-
静态成员不能使用泛型
-
泛型接口的类型,是在继承接口或者实现接口时确定的
interface IUsb<T,R>{} interface IA extends IUsb<String,Double> {} class a implements IA{ //当实现有泛型的接口时,就会直接进行泛型类型的指定:因为在实现的时候需要实现方法 }
-
没有指定就是Object
泛型方法
自定义泛型方法
基本句法:
//泛型是提供给方法使用的
修饰符 <T,R> 返回类型 方法名(T t,R r){}
注意细节
- 泛型方法可以定义在普通类中,也可以当以在泛型类中
- 当泛型方法被调用的时候,类型会确定
- 不满足基本语法的方法都不是泛型方法,如果有泛型,也只是进行了使用
泛型的继承和通配符
-
泛型不具有继承性
List<Object> list = new ArrayList<String>();//这样写,泛型的类型不会进行继承
- <?> :支持任意类型的泛型
- <? extends A> :支持A类以及A的子类,规定了泛型的上限
// ? extends AA 表示上限,可以接受AA或者AA子类 public static void printCollection2(List<? extends AA> C) {}
- <? super A>:支持A类以及A类的父类,不限于直接父类,规定了泛型的下限。
//? super子类类名AA:支持AA类以及AA类的父类,不限于直接父类,//规定了泛型的下限 public static void printcolleetic I(List<? super AA> c){
Juint单元测试类
为什么需要junit?
一个类有很多功能代码需要测试,为了测试就需要写入main方法中
如果有多个功能代码需要测试,就需要来回注销,切换很麻烦
如果只运行一个方法,就方便很多,并且可以给出相关信息,===》Junit
介绍
Junit是一个java语言的单元测试框架
多数java的开发环境都继承了Junit作为单元测试工具