1,什么是泛型
所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量,创建对象时)确定(即传入实际的类型参数,也称为类型实参)
import java.util.ArrayList;
import java.util.Iterator;
public class GenericTest {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("AA");
arrayList.add("BB");
arrayList.add("CC");
Iterator<String> iterator = arrayList.iterator();
while (iterator.hasNext()){
//如果取出ArrayList集合中的元素,类型为String类型
System.out.println(iterator.next());
}
for(String s:arrayList){
System.out.println(s);
}
}
}
在上述例子中对ArrayList运用到了泛型,因此在ArrayList中只能存储String类型的数据
jdk1.5之前没有泛型,如果集合没有指定泛型,那么其存放的类型为Object类型
泛型是在编译阶段限制类型就是为泛型指定类型,泛型是jdk5中注入的一个新特性,泛型提供了翻译时类型的安全检测机制,该机制允许程序员在编译时检测到非法的类型
泛型---该类型只能使用引用;类型比如说,int就不能用于泛型,而是要用Integer来代替
泛型可以使用在方法、接口、类,分别称作:泛型类,泛型方法,泛型接口
2,泛型类
泛型类定义的格式:
格式:修饰符 class类名<类型>{}
范例:public class Mayikt<T>{}
此处T可以随便写为任意标识
import org.junit.Test;
public class Mayikt<T> {
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
private T t;
//也就是在类中定义的成员属性泛型T类型与我们在类上定义泛型类型相同的
}
以上为泛型类的举例,我们创建了一个泛型类
import org.junit.Test;
public class Test2 {
@Test
public void test1(){
Mayikt<String> mayikt = new Mayikt<>();
mayikt.setT("AA");
System.out.println(mayikt.getT());
Mayikt<Integer> integerMayikt = new Mayikt<>();
integerMayikt.setT(111);
System.out.println(integerMayikt.getT());
}
}
在以上代码中,我们运用了之前定义的一个泛型类Mayikt分别创建了两个对象,分别为类型为String和Integer的对象
3,泛型方法
泛型方法的格式:
格式:修饰符<类型>返回值类型 方法名(类型 变量名){....}
范例:public<T>void show(T t){....}
在通常情况下,我们在定义一个方法时,如果要使该方法适用于多个类型的数据,就需要将该方法重载数次,而通过使用泛型方法,就可以使其更加简便,不需要进行多次重载,从而简化了代码
public class Meite {
public String show(String str){
return str;
}
public Integer show(Integer integer){
return integer;
}
public Boolean show(Boolean b){
return b;
}
public Double show(Double d){
return d;
}
}
以上是通过反复重载的方式使方法show()适用于多个类型的数据
public class Meite {
public<T> T show(T t){
return t;
}
}
而以上代码就是通过泛型方法使其适用于多个类型,可以看出,使用泛型方法后,代码简化了很多
4,泛型接口
泛型接口的格式:
格式:修饰符 interface接口名<类型>{....}
范例:public interface MayiktInterface<T>{....}
public interface MayiktInterfaceTest<T> {
T show(T t);
}
以上定义了一个泛型接口
而在定义完泛型接口后,我们还需要一个实现类来实现泛型接口,以下是该实现类
public class MayiktImpl<T> implements MayiktInterfaceTest<T>{
@Override
public T show(T t) {
return t;
}
}
public class Test01 {
public static void main(String[] args) {
MayiktImpl<String> mayikt = new MayiktImpl<>();
String show = mayikt.show("36");
System.out.println(show);
}
}
而上面这段代码,就将这个实现类使用了,创建了一个这个实现类的对象
4,类型通配符
1,类型通配符<?>一般用于接受使用,不能够做添加。
2,List<?>:表示元素类型未知的list,它的元素可以匹配任何类型。
3,带通配符的List仅表示它是各种泛型List的父类,并不能把元素添加到其中。
4,类型通配符上限:<? extends 类型> List<? extends MayiktParent>:它表示的类型是MayiktParent或者子类型
5,类型通配符下限:<? super 类型> List<? super MayiktParent>:它表示的类型是Mayiktparent或者其父类型
一下是关于类型通配符的引用
import org.junit.Test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class TongPeiFutest {
//定义printList方法不知道接受具体List泛型是什么类型
//List<?>只能够用于接收------可接受所有的泛型类型,不能够用于添加
//是可以做get操作,获取到类型是为Object类型
public void printList(List<?> list){
Iterator<?> iterator = list.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
@Test
public void test(){
ArrayList<String> arrayList = new ArrayList<>();
for(int i=0;i<5;i++){
arrayList.add("i : "+i);
}
printList(arrayList);
ArrayList<Integer> list = new ArrayList<>();
}
}
5,可变参数
1,可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了
2,书写格式
2.1:修饰符 返回值类型 方法名 (数据类型.....量名){}
2.2:范例:public static int sum(int.....a){}
3:可变参数注意事项
这里的可变参数变量其实是一个数组。
如果一个方法有多个参数,包含可变参数,可变参数要放在最后
import org.junit.Test;
public class Test4 {
public int sum(int a,int b){
return a+b;
}
public int sum(int a,int b,int c){
return a+b+c;
}
public int sum(int a,int b,int c,int d){
return a+b+c+d;
}
}
当我们需要通过重载使一个方法的参数的数量不同时,还可以通过可变参数简化代码,如下所示
import org.junit.Test;
public class Test4 {
@Test
public void test(){
sum(1,1);//arr[0]=1 arr[1]=1
sum(2,2,2);
sum(3,3,3,3);
}
public static int sum(int...a){
int sum=0;
System.out.println(a);
for(int i=0;i<a.length;i++){
sum++;
System.out.println(a[i]);
}
System.out.println(sum+"个");
return 0;
}
}
6,泛型擦除机制
泛型原理就是在底层使用了泛型擦除机制
泛型是在编译阶段限制传递的类型---在运行阶段都是擦除的 底层class文件在运行里面是没有泛型的,因此,我们将带有泛型的代码的源代码翻译为class文件后,会发现class文件中是没有泛型的当然,我们在将一个带有泛型的集合赋值另一个集合后,会擦除该集合的泛型,使其的类型变为Object,举例如下
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class Test5 {
@Test
public void test(){
ArrayList<String> str = new ArrayList<>();
str.add("AA");
str.add("BB");
str.add("CC");
//说明:将一个List集合泛型赋值给一个没有使用泛型List集合,会直接去除泛型-----擦除机制
List list=str;
list.add(123);
}
}