泛型的引入
看下面这段代码:
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 <T extends Number> 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<String> list = new ArrayList<String>();
// 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<String> 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<Integer> 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>{
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<String> strList = new ArrayList<String>();
Iterator<Customer> 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<Student> 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<String, Student> 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<Map.Entry<String, Student>> entries = hm.entrySet();
Iterator<Map.Entry<String, Student>> iterator = entries.iterator();
System.out.println("==========================");
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 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<Integer> list = new ArrayList<Integer>();//这样写正确
List<int> list = new ArrayList<int>();//这样写错误
2.在给泛型指定具体类型后,可以传入该类型或者其子类类型
3.泛型使用形式
//1.第一种方式
List<Integer> list1 = new ArrayList<Integer>();
//2.第二种方式
List<Integer> Iist2 = new ArrayList<>();
3.如果我们这样写List list3=new ArrayList();默认给它的泛型是 E就是Object.,等价于ArrayList