看下面这段代码:
(资料图片)
private static int add(int a, int b) { System.out.println(a + "+" + b + "=" + (a + b)); return a + b;}private static float add(float a, float b) { System.out.println(a + "+" + b + "=" + (a + b)); return a + b;}private static double add(double a, double b) { System.out.println(a + "+" + b + "=" + (a + b)); return a + b;}
如果没有泛型,要实现不同类型的加法,每种类型都需要重载一个add方法;通过泛型,我们可以复用为一个方法:
private static double add(T a, T b) { System.out.println(a + "+" + b + "=" + (a.doubleValue() + b.doubleValue())); return a.doubleValue() + b.doubleValue();}
泛型中的类型在使用时指定,不需要强制类型转换(类型安全,编译器会检查类型)
下面这段代码:
List list = new ArrayList();list.add("xxString");list.add(100d);list.add(new Person());
我们在使用上述list中,list中的元素都是Object类型(无法约束其中的类型),所以在取出集合元素时需要人为的强制类型转化到具体的目标类型,且很容易出java.lang.ClassCastException`异常。
引入泛型,它将提供类型的约束,提供编译前的检查:
List list = new ArrayList();// list中只能放String, 不能放其它类型的元素
泛型的好处1、编译时,检查添加元素的类型,提高了安全性
2、减少了类型转换的次数,提高效率
3、不再提示编译警告
介绍1.泛型又称参数化类型,是Jdk5.0出现的新特性,解决数据类型的安全性问题
2.在类声明或实例化时只要指定好需要的具体的类型即可。
3.Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException.异常。同时,代码更加简洁、健壮
4.泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方法的返回值的类型,或者是参数类型。
代码举例:
public class Generic03 { public static void main(String[] args) { //注意,特别强调:E具体的数据类型在定义Person对象的时候指定,即在编译期间,就确定E是什么类型 Person person = new Person<>("dfdfs"); person.show();//String /** * Person类相当于下面这样子 * class Person{ * String s;//E表示s的数据类型,该数据类型在定义Person对象的时候指定,即在编译期间,就确定E是什么类型 * * public Person(String s) {//E也可以是参数类型 * this.s = s; * } * * public String f(){//返回类型使用E * return s; * } * public void show(){ * System.out.println(s.getClass());//显示s的运行类型 * } * } */ Person person2 = new Person<>(100); person2.show(); /** * Person类相当于下面这样子 * class Person{ * Integer s;//E表示s的数据类型,该数据类型在定义Person对象的时候指定,即在编译期间,就确定E是什么类型 * * public Person(Integer s) {//E也可以是参数类型 * this.s = s; * } * * public Integer f(){//返回类型使用E * return s; * } * public void show(){ * System.out.println(s.getClass());//显示s的运行类型 * } * } */ }}//泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方法的返回值的类型,或者是参数类型class Person{ E s;//E表示s的数据类型,该数据类型在定义Person对象的时候指定,即在编译期间,就确定E是什么类型 public Person(E s) {//E也可以是参数类型 this.s = s; } public E f(){//返回类型使用E return s; } public void show(){ System.out.println(s.getClass());//显示s的运行类型 }}
语法泛型的声明interface 接口名
说明:
1)其中,T,K,V不代表值,而是表示类型
2)任意字母都可以。常用T表示,是Type的缩写
泛型的实例化要在类名后面指定类型参数的值(类型)。如:
List strList = new ArrayList();Iterator iterator = customers.iterator();
泛型使用举例需求:
1.创建3个学生对象
2.放入到HashSet中学生对象,使用.
3.放入到HashMap中,要求Key 是String name,Value就是学生对象
4.使用两种方式遍历
public class GenericExercise { public static void main(String[] args) { //使用泛型方式给HashSet放入3个学生对象 HashSet students = new HashSet<>(); students.add(new Student("jack",18)); students.add(new Student("tom",18)); students.add(new Student("ml",18)); //第一种遍历方式,增强for循环 for (Student student:students){ System.out.println(student); } //使用泛型方式给HashMap放入3个学生对象 HashMap hm = new HashMap<>(); hm.put("milan",new Student("milan",34)); hm.put("jack",new Student("jack",31)); hm.put("tom",new Student("tom",30)); //2.迭代器 Set> entries = hm.entrySet(); Iterator> iterator = entries.iterator(); System.out.println("=========================="); while (iterator.hasNext()){ Map.Entry next = iterator.next(); System.out.println(next.getKey()+"-"+next.getValue()); } }}class Student{ private String name; private int age; public Student(String name, int age) { this.name = name; this.age = 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; } @Override public String toString() { return "Student{" + "name="" + name + "\"" + ", age=" + age + "}"; }}
泛型使用注意事项1.interface 接口名
List list = new ArrayList();//这样写正确List list = new ArrayList();//这样写错误
2.在给泛型指定具体类型后,可以传入该类型或者其子类类型
3.泛型使用形式
//1.第一种方式List list1 = new ArrayList();//2.第二种方式List Iist2 = new ArrayList<>();
3.如果我们这样写List list3=new ArrayList();默认给它的泛型是 E就是Object.,等价于ArrayList