JAVA—>泛型
文章目录
泛型的引入
1.传统的方法中,不能对加入到集合中的数据类型进行约束(不安全)
2.遍历得到时候,需要类型转换,如果集合数据过多会对效率有影响
main方法:
ArrayList<Dog> arrayList = new ArrayList<Dog>();
arrayList.add(new Dog("旺财",5));
arrayList.add(new Dog("小白",3));
arrayList.add(new Dog("小黑",7));
//如果不小心加入一只猫
//arrayList.add(new Cat("小花",6));
System.out.println("-----使用泛型-----");
for( Dog dog: arrayList){
//遍历的时候可直接取出Dog 而不是 Object
System.out.println(dog.getName()+"-"+dog.getAge());
}
优点:
1.编译时,检查添加元素的类型,提高了安全性
2.减少类型转换的次数,提高了效率
3.不在提示编译警告
一、泛型(Generic)
1.定义:泛型,既广泛的类型 ( E->可以表示为Integer,String,Dog)
== 可以表示数据类型的类型==
2.又称参数化类型,jdk5.0出现的新特性,可以解决安全性问题
3.泛型可以保证如果程序在编译时没有发出警告,运行时也不会产生ClassException异常。同时代码简洁,健壮。
4.泛型作用是:可以在类声明时通过一个标识标识类中的某个属性的类型;或是某个方法的返回值类型,或是参数类型
Class Person<E> {
E s; // E表示s的数据类型,定义时(编译)即确定是什么类型
public Person(E s){ //E也可以是参数类型
this.s=s;
}
public E f(){ //E也可以是返回值类型
return s;
}
}
main方法:
Person<String> person =new Person<String>("msb");
//此时上方的E-->String类型
Person<Integer> person =new Person<Integer>(100);
//此时上方的E-->Integer类型
二、泛型的语法
1.泛型的声明
interface 接口名<T<T>> / class 类名<K,V>{}
例如:List,ArrayList
其中,<>内代表类型,任意字母都可以
2.泛型的实例化
-要在类名后指定类型
List<String> strList =new ArrayList<String>();
Iterator<Customer> iterator =customers.iterator();
3.泛型的应用(举例)
package com.msbedu.generic;
import java.util.*;
public class generic01 {
public static void main(String[] args) {
//1)创建三个学生对象,放入到HashSet中学生对象,遍历
HashSet<Student> students = new HashSet<Student>();
students.add(new Student("jack",18));
students.add(new Student("lucy",19));
students.add(new Student("mark",20));
//遍历 --->增强for
//这里声明了一个循环变量student,它的类型是Student
// 表示每次循环都会从students集合中取出一个Student对象赋值给student变量。
for(Student student:students){
System.out.println(student);
}
//2)放入到HashMap中,要求key是String name,value 是学生对象,遍历
System.out.println("----------------------------------");
HashMap<String, Student> hashMap = new HashMap<String, Student>();
hashMap.put("jack",new Student("jack",18));
hashMap.put("lucy",new Student("lucy",19));
hashMap.put("mark",new Student("mark",20));
//遍历---->迭代器 EntrySet
Set<Map.Entry<String, Student>> entries = hashMap.entrySet();
Iterator<Map.Entry<String, Student>> iterator = entries.iterator();
while (iterator.hasNext()) {
Map.Entry<String, Student> next = iterator.next();
System.out.println(next.getKey()+"-"+next.getValue());
}
}
}
class Student{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
*hashmap的遍历方法没有掌握*
四、泛型的使用细节和注意事项
1.E只能是引用类型(Integer),不能是基本数据类型
List<<Integer>Integer> list= new ArrayList<<Integer>Integer>(); √
2.在给泛型指定了具体类型后,可以传入该类型或其子类类型
main方法:
{
Dog<A> dog1 = new Dog<A>(new A());
Dog<A> dog2 = new Dog<A>(new B());
//指定的是A类型 但是此时B是A的子类 所以B也可以传入
}
class A{}
class B extends A{}
class Dog<E>{
E e;
public Dog(E e) {
this.e = e;
}
}
3.书写泛型时后面<>内可以省略
List<Integer> list= new ArrayList<>();
4.不指定泛型的类型,默认为Object
List<Integer> list= new ArrayList<>();
五、自定义泛型
1.基本语法
class 类名<T,E…>{
成员
}
举例:
Class Person<E> {
E s; // E表示s的数据类型,定义时(编译)即确定是什么类型
public Person(E s){ //E也可以是参数类型
this.s=s;
}
public E f(){ //E也可以是返回值类型
return s;
}
}
2.使用细节
1).普通成员可以使用泛型(属性、方法)
2).使用泛型的数组,不能初始化
3).静态方法中不能使用类的泛型(静态属性也行)
4).泛型类中具体的类型,是在创建对象时确定的 <T,R…>
5).创建对象没有指定类型,默认Object
举例:
class Tiger<T>{
1. T t; //属性使用泛型
public Tiger(T t) { //构造器使用泛型
this.t = t;
}
public T getT() { //返回值使用泛型
return t;
}
public void setT(T t) { //方法使用泛型
this.t = t;
}
2. T[] t=new T[8];× //泛型数组不能初始化
//因为数组在new不能确定T的类型,无法在内存开空间
3. public static void m1(T t) { //×
static T t;//×
//因为静态与类相关,在类加载时,对象还没有创建(如果使用了泛型,JVM就无法完成初始化)
}
}
六、自定义泛型接口
1.基本语法
Interface 接口名<T,R...>{}
2.使用细节
1.接口中,静态成员也不能使用泛型(与泛型类规定相同)
2.泛型接口的类型,在继承接口或者实现接口时确定
3.没有指定类型,默认为Object
Interface IUsb<U,R>{
1. U name="msb"; //接口中默认属性为 public static final
U name;//×
//普通方法,可以使用接口泛型
R get(U u);
void hi(R r){}
}
2. interface IA extends IUsb<String,Double>{}
class AA implements IA{} //×实现接口必须实现接口所有方法
//实现后所有方法已经有具体的泛型
3. class BB implements IA<String,Integer>{}
class CC implements IA{}//相当于默认为两个Obj0ect
七、自定义泛型方法
1.基本语法
修饰符<T,R...> 返回类型 方法名(参数){}
2.使用细节
1.泛型方法,可以定义在普通类,也可定义在泛型类中
2.当泛型方法被调用时,类型会确定
3.public void eat(E e){},修饰符后没<T,R…>
表示:该方法不是泛型方法,而是使用了泛型
Class car{
public void run(){}//普通方法
public <T> void fly(T t){}//泛型方法
}
八、泛型的继承和通配符
1.泛型的继承和通配符说明
1.泛型不具备继承性
Object o=new String("x"); //类有继承
LIst<Object> list = new ArrayList<String>();//×
2.<?>表示支持任意泛型类型
3.<?extends A>:支持A类以及的A类的子类,规定了泛型的上限
4.<? super A>:支持A类以及A类的父类,不限于直接父类,规定了泛型的下限
//?extends 子类名AA:支持AA类以及AA的子类
public static void printCollection1(List<? extends AA> c){
for (Object obj :c){
System.out.println(obj);
}
}
//?super 子类名AA:支持AA类以及AA的父类,不限于直接父类
public static void printCollection2(list<? super AA> c){
for (Object obj :c){
System.out.println(obj);
}
}
main方法:
List<Object> list1=new ArrayList<>();
List<AA> list2=new ArrayList<>();
List<BB>list3=new ArrayList<>();
List<CC> list4=new ArrayList<>():
//如果是List<?> c,可以接受任意类型
printCollection(list1); √
printCollection(list2);√
printCollection(list3);√
printCollection(list4);√
//如果是List<? extends AA> c,可以接受AA类以及AA的子类
printCollection1(list1); ×
printCollection1(list2); √
printCollection1(list3); √
printCollection1(list4); √
//如果是List<? super AA> c,可以接受AA类以及AA的父类,不限于直接父类
printCollection2(list1); √
printCollection2(list2); ×
printCollection2(list3); ×
printCollection2(list4); ×
class AA{}
class BB extends AA{}
class CC extends BB{}
九、JUnit
1.介绍
1.JUnit是java的语言单元测试框架
2.多数java环境集成了JUnit作为单元测试的工具
2.演示
在需要测试的方法前加 @Test alt+enter-->add ‘JUnit5.4’ to classpath
自动导入包