泛型的理解和好处
泛型的好处
- 编译时,检查添加元素的类型,提高了安全性
- 减少了类型转换的次数,提高效率
不使用泛型
Dog-加入->Object-取出->Dog(向下转型) Dog放入到ArrayList 会先转成Object,在转出时,还需要转换成Dog
使用泛型
Dog->Dog->Dog 放入和取出时,不需要类型转换,提高效率 - 不再提示编译警告
泛型的介绍
泛型:广泛类型
- 泛型又称参数化类型,是JDK5.0 出现的新特性,解决数据类型的安全性问题
- 在类声明或实例化时(在定义对象时,即编译期间),只要指定好需要的具体类型即可
- Java 泛型可以保证如果程序在编译时,没有发出警告,运行时就不会产生,ClassCastException异常。同时,代码更加简洁
- 泛型的作用:可以在类声明时通过一个标识表示类中某个属性的类型,或者某个方法的返回值类型,或者是参数类型
public class Generic01 {public static void main(String[] args) {//注意:E 具体的数据类型在定义Person对象时指定(即在编译期间),就确定E是什么类型Person<Integer> integerPerson = new Person<>(1);//E的数据类型是IntegerintegerPerson.show();}
}
//泛型的作用:可以在类声明时通过一个标识表示类中某个属性的类型、某个方法的返回值类型 或 参数类型
class Person<E>{E S;//E表示s的数据类型,该数据类型在定义Person对象的时候指定,即在编译期间,就确定E是什么类型public Person(E s) {//E也可以是参数类型S = s;}public E f(){//E也可以是返回类型return S;}public void show(){System.out.println("S的运行类型="+S.getClass());}
}
结果
泛型的语法
泛型的声明
- interface 接口{} 和 class类<K,V>{}
1,其中 T K V 不代表值,而是表示类型
2,任意字母都可以,常用T表示,是Type的缩写
泛型的实例化
要在类名后面指定类型参数的值(类型)。如:
- 1,List strList = new ArrayList();
- 2,Iterator iterator = customers.iterator();
泛型使用实例
public class GenericExercise {public static void main(String[] args) {//使用泛型方式给HashSet放入三个学生对象,遍历时可以直接调用Student1中的方法Set<Student1> objects = new HashSet<Student1>();objects.add(new Student1("jack"));//当调用add方法时,显示调用Student1 对象objects.add(new Student1("tom"));objects.add(new Student1("smith"));// 遍历for(Student1 o:objects){System.out.println(o.getName());}//使用泛型方式给 HashMap 放入 3 个学生对象//K -> String V->Student//一旦添加了泛型,编译器就会规范调用类型Map<String, Student1> map = new HashMap<String, Student1>();//public class HashMap<K,V> {}Student1 student1 = new Student1("jack");Student1 student2 = new Student1("tom");Student1 student3 = new Student1("smith");map.put("jack",student1);map.put("tom",student2);map.put("smith",student3);//遍历//迭代器 EntrySet/*public Set<Map.Entry<K,V>> entrySet() {Set<Map.Entry<K,V>> es;return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;}*///1,map.entrySet();Set<Map.Entry<String, Student1>> entries = map.entrySet();/*public final Iterator<Map.Entry<K,V>> iterator() {return new EntryIterator();}*///2,调迭代器 entries.iterator()Iterator<Map.Entry<String, Student1>> iterator = entries.iterator();//3,先判断hasNext 下一个是否还有while (iterator.hasNext()) {Map.Entry<String, Student1> next = iterator.next();System.out.println(next.getKey()+"-"+next.getValue());}}
}
class Student1{private String name;public Student1(String name) {this.name = name;}public String getName() {return name;}@Overridepublic String toString() {return "Student1{" +"name='" + name + '\'' +'}';}
}
结果
泛型的注意事项
- 1,interface List{} public class HashSet{}
说明:T E 只能是引用类型 - 2,在给泛型指定具体类型后,可以传入该类型或其子类类型
- 3,泛型使用形式
List list1 = new ArrayList ();
List list1 = new ArrayList <>();
如果我们这样写List list1 = new ArrayList (); 默认他的泛型是 E 就是Object
public class GenericDetail {public static void main(String[] args) {//1,泛型指向的数据类型是引用类型Integer,不能是基本数据类型intList<Integer> list = new ArrayList<Integer>();//List<int> list = new ArrayList<int>(); 错误//2,E指定了A类型,构造器传入 new A()// 在给泛型指定具体类型后,可以传入该类型或者子类类型Pig<A> aPig = new Pig<A>(new A());aPig.f();Pig<A> aPig1 = new Pig<A>(new B());aPig1.f();//3,泛型的使用形式List<Integer> list1 = new ArrayList <Integer>();//实际开发中往往简写为:List<Integer> list2 = new ArrayList <>();//4,如果我们这样写List list1 = new ArrayList (); 默认他的泛型是 <E> E 就是ObjectList list3 = new ArrayList ();//等价 ArrayList<Object> arrayList = new ArrayList<Object>();}
}
class A{}
class B extends A{}
class Pig<E>{E e;public Pig(E e) {this.e = e;}public void f(){System.out.println("Pig类中的f方法");}
}