泛型
泛型的概念
泛型是一种未知的数据类型,是在定义某些类时,我们不知道使用什么数据类型时,就可以用泛型。然后在创建对象时,确定泛型的数据类型。
泛型也可以看出是一个变量,用来接受数据类型
例如ArrayList在定义的时候不知道集合中都会存储什么类型的数据,所以类型使用泛型。
E:未知的数据类型
例如有如下ArrayList类,定义时用泛型
public class ArrayList{
public boolean add(E e) {}
public String get(int index) {}
}
创建集合对象的时候,如下:
ArrayList list = new ArrayList();
就会把数据类型String传给泛型E。
使用泛型的好处
创建集合对象时,不适用泛型的好处:
默认类型就是Object类型,可以存储任意类型的数据
弊端:
不安全,会引发异常
代码示例:
import java.util.ArrayList;
import java.util.Iterator;
public class EClass {
private static void show01() {
ArrayList list = new ArrayList();
list.add("ab");
list.add(1);
list.add(2);
list.add(3);
list.add(4);
//接下来使用迭代器遍历list集合
//获取迭代器
Iterator it = list.iterator();
while(it.hasNext()) {
Object obj = it.next();
System.out.println(obj);
//如果想要用String类特有的方法,
//length获取字符串的长度,不能使用,
//多态Object需要向下转型
String s = (String)obj;
System.out.println(s.length());
}
}
public static void main(String[] args) {
show01();
}
}
ArrayList可以存储任意类型的数据,所以在向下转型为String使用length()方法求字符串长度时,容易出错。会提示类型转换异常。
创建集合对象,使用泛型的好处
- 避免了类型转换的麻烦,存储的是什么类型,取出来就是什么类型
- 把运行期异常(代码运行之后会出现的异常,提升到了编译期(写代码时候会报错) 。
弊端:
泛型是什么类型,就只能存储什么类型的数据
private static void show02() {
ArrayList<String> list = new ArrayList<>();
list.add("abcdefg");
list.add("abcdef");
list.add("abcde");
list.add("abcd");
list.add("abc");
list.add("ab");
list.add("a");
//list.add(1); //此时会报异常,add(int, String)
//in the type ArrayList<String> is not applicable
//for the arguments (int)
//使用迭代器遍历list集合
Iterator<String> it = list.iterator();
while(it.hasNext()) {
String s = it.next();
System.out.println(s + "->" + s.length());
}
}
调用这个方法输出结果如下:
用了泛型之后并且讲创建对象时把泛型定义为String之后,只能存储String类型的数据,所以取出来的一定是String类型,可以直接用length()方法求字符串长度。不需要向下转型,也不会出现类型转换异常。
泛型的定义和使用
泛型,用来灵活地将数据类型应用到不同的类,方法,接口当。将数据类型作为参数进行传递。
定义含有泛型的类
定义格式
修饰符 class 类名 <代表泛型的变量> { }
class ArrayList{
public boolean add(E e){ }
public E get(int index){ }
.....
}
示例代码如下(E为泛型):
public class GenericClass<E> {
private E name;
public E getName() {
return name;
}
public void setName(E name) {
this.name = name;
}
}
public class DemoTestClass {
public static void main(String[] args) {
//如果不写泛型 则默认为Object类型
GenericClass gc= new GenericClass();
gc.setName("字符串");
Object obj = gc.getName();
//创建GenericClass对象泛型用Integer类型
GenericClass<Integer> gc1 = new GenericClass<>();
gc1.setName(1);
Integer name = gc1.getName();
System.out.println(name);
//创建GenericClass对象泛型用String类型
GenericClass<String> gc2 = new GenericClass<>();
gc2.setName("132456asc");
String str = gc2.getName();
System.out.println(str);
}
}
```输出结果:
![输出结果](https://img-blog.csdnimg.cn/20200131184806229.png)
### 定义含有泛型的方法
泛型定义在方法的修饰符和返回值类型之间
格式:
**修饰符 <泛型> 返回值类型 方法名(参数列表 (使用泛型)){
方法体;
}**
含有泛型的方法,在调用方法的时候确定泛型的数据类型,传递什么类型的数据,泛型就是什么类型
示例代码:
```java
public class GenericClassTwo {
//定义一个含有泛型的方法
public <M> void method(M m) {
System.out.println(m);
}
//定义一个含有泛型的静态方法
public static <S> void method02(S s) {
System.out.println(s);
}
}
public class DemoTestClass02 {
public static void main(String[] args) {
//创建GenericMethod对象
GenericClassTwo gm = new GenericClassTwo();
//调用method方法时,传递的是什么类型,泛型就是什么类型
gm.method(1);
gm.method("avf");
GenericClassTwo.method02("静态方法");
}
}
泛型通配符
当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示。但是一旦使用泛型的通配符后,只能使用0bject类中的共性方法,集合中元素自身方法无法使用。
泛型通配符:
?: 代表任意的数据类型
使用方式:
不能创建对象使用
只能作为方法的参数使用
import java.util.ArrayList;
import java.util.Iterator;
public class TongPeiFuClass {
/**
* 定义一个方法,能够遍历任意类型ArrayList的集合
* 如果不知道ArrayList集合使用什么数据类型,可以
* 用泛型的通配符?来接收数据类型
* 注意; 泛型没有继承概念
* @param list
*/
public static void printArray(ArrayList<?> list) {
Iterator<?> it = list.iterator();
while(it.hasNext()) {
//it.next()取出的元素Object类型,可以接受任意的数据类型
Object o = it.next();
System.out.println(o);
}
}
public static void main(String[] args) {
ArrayList<Integer> list01 = new ArrayList<>();
list01.add(1);
list01.add(2);
ArrayList<String> list02 = new ArrayList<>();
list02.add("aa");
list02.add("dd");
printArray(list01);
printArray(list02);
}
}
输出结果: