1.泛型的概念
泛型是一种末知的数据类型,当我们不知道使用什么数据类型的时候,可以使用泛型。泛型也可以看成是一个变量用来接收数据类型。E e:Element元素,T t:Type类型。
集合中可以存储任意类型的对象元素,但是当把一个对象存入集合后,集合会“忘记”这个对象的类型,将该对象从集合中取出时,这个对象的编译类型就统一变成了 Object 类型。
换句话说,在程序中无法确定一个集合中的元素到底是什么类型,那么在取出元素时,如果进行强制类型转换就很容易出错。
2.是否使用泛型的对比
2.1 不使用泛型
创建集合对象,不使用泛型。好处:集合不使用泛型,默认的类型就是Object类型,可以存储任意类型的数据。
弊端:不安全,会引发异常。
2.1.1 好处
import java.util.*;
public class GenericDemo01 {
public static void main(String[] args) {
ArrayList arraylist=new ArrayList();//集合不使用泛型
//向集合中添加数据,用于测试,这里添加了String类型和int类型的数据
arraylist.add("ABC");
arraylist.add(123);
Iterator iterator=arraylist.iterator();
while(iterator.hasNext()) {//取出的元素的类型默认是Object类型
System.out.print(iterator.next() + " ");
}
}
}
2.1.2 弊端
import java.util.*;
public class GenericDemo02 {
public static void main(String[] args) {
ArrayList arraylist=new ArrayList();
arraylist.add("ABC");
arraylist.add(123);
Iterator iterator=arraylist.iterator();
while(iterator.hasNext()) {
//取出的数据,默认是Object类型
Object obj=iterator.next();
/*假如想使用String类特有的length()方法来获取字符串的长度,是不可以的
需要将Object类型向下转型为String类型才能使用它的特有方法
但是集合里面还有数据类型为Integer的数据,所以不能进行向下转型为String类型,
如果强行转换,那么在运行时会抛出ClassCastException异常*/
String str=(String)obj;
System.out.println("该元素的长度为:" + str.length());
}
}
}
2.2 使用泛型
2.2.1 好处及弊端
import java.util.*;
public class GenericDemo03 {
public static void main(String[] args) {
//使用泛型限定数据类型为String类的字符串
ArrayList<String> arraylist=new ArrayList<String>();
arraylist.add("ABC");
/*假如添加的数据的类型不是String类型
arrayList.add(123);这条语句会抛出错误:
方法java.util.Collection.add(java.lang.String)不适用*/
Iterator<String> iterator=arraylist.iterator();
while(iterator.hasNext()) {
String str=iterator.next();
System.out.print("该元素为:" + str + "\n" +
"长度为:" + str.length());
}
}
}
3.定义和使用含有泛型的类
3.1 说明
泛型,用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数进行传递。
定义和使用含有泛型的类的格式如下:修饰符 class 类名称<代表泛型的变量类型> { . . . }
修饰符 class 类名称<代表泛型的变量类型> { . . . }
3.2 举例
class GenericClass<E> {
private E name;
public void setName(E name) {
this.name=name;
}
public E getName() {
return this.name;
}
}
public class GenericDemo04 {
public static void main(String[] args) {
//使用泛型,限定该类的数据类型为String类
GenericClass<String> name1=new GenericClass<String>();
name1.setName("使用泛型:这里只能添加指定类型的数据!");
String str1=name1.getName();
System.out.println(str1);
//不使用泛型,该类的数据类型默认为Object类
GenericClass name2=new GenericClass();
name2.setName("不使用泛型:这里能添加不同类型的数据!");
Object obj1=name2.getName();
System.out.println(obj1);
}
}
4.定义和使用含有泛型的方法
4.1 说明
定义含有泛型的方法:泛型定义在方法的修饰符和返回值类型之间。
格式:修饰符 <泛型> 返回值类型 方法名(参数列表(使用泛型)){ 方法体 };
含有泛型的方法,在调用方法的时候确定泛型的数据类型,传递什么类型的参数,泛型就是什么类型 。
4.2 举例
class GenericMethod {
public <W> String method1(W w) {
return "一个使用泛型的普通方法:" + w;
}
public static <Z> String method2(Z z) {
return "一个使用泛型的静态方法:" + z;
}
}
public class GenericDemo05 {
public static void main(String[] args) {
GenericMethod use=new GenericMethod();//创建一个类对象
/*调用包含泛型的普通方法
对应的普通方法为:public <Integer> String method1(Integer 666),w=666*/
System.out.println(use.method1(666));
//对应的普通方法为:public <String> String method1(String LOVE),w=LOVE
System.out.println(use.method1("LOVE"));
/*调用包含泛型的静态方法
虽然可以通过对象来调用,但还是推荐使用类进行调用
对应的静态方法为:public static <String> String method2(String ABC),z=ABC*/
System.out.println(GenericMethod.method2("ABC"));
//对应的静态方法为:public static <Double> String method2(Double 521.1314),z=521.1314
System.out.println(GenericMethod.method2("521.1314"));
}
}
5.定义和使用含有泛型的接口
5.1 说明
①含有泛型的接口第一种使用方式:通过定义接口的实现类,实现接口,指定接口的泛型。
②含有泛型的接口第二种使用方式:接口使用什么泛型,实现类就使用什么泛型,类跟着接口走。就相当于定义了一个含有泛型的类,创建对象的时候确定泛型的类型。
5.2 举例
5.2.1 含有泛型的接口第一种使用方式
//博主在这里有点懒,将接口和实现接口的类都写在了一个.java源文件中
//推荐大家将接口和其他的类都单独的写在一个.java源文件中
interface GenericInterface<I> {
public void method(I i);//接口中的一个抽象方法
}
class Genericing implements GenericInterface<String> {
public void method(String s) {
System.out.println("通过定义接口的实现类,实现接口,指定接口的泛型\n" +
"这个方法传入指定类型参数是:" + s);
}
}
public class GenericDemo06 {
public static void main(String[] args) {
Genericing generic=new Genericing();
generic.method("定义和使用接口的第一种方式!");
}
}
5.2.2 含有泛型的接口第二种使用方式
interface GenericInterface01<I> {
public void method(I i);
}
class Genericing01<I> implements GenericInterface01<I> {
public void method(I i) {
System.out.println("接口使用什么泛型,实现类就使用什么泛型,类跟着接口走\n" +
"创建对象的时候传入指定类型参数是:" + i);
}
}
public class GenericDemo07 {
public static void main(String[] args) {
Genericing01 generic=new Genericing01();
generic.method(2020);
}
}
6.泛型通配符
6.1 说明
通配符基本使用泛型的通配:不知道使用什么类型来接收的时候,此时可以使用 ?,? 表示未知通配符,即:表示任意的数据类型。
使用方式:不能创建对象使用,只能作为方法的参数使用。
注意:一但使用泛型的通配符,那么,只能使用Object类中的共性方法,集合中元素的自身方法无法使用。
6.2 举例
import java.util.*;
class IteratorArrayList {
//由于不确定接收的ArrayList集合中的元素是什么类型,所以使用泛型通配符 ?
//array1的元素为Integer类型,array2的元素为String类型
public static void printing(ArrayList<?> array1) {
Iterator<?> iterator=array1.iterator();
while(iterator.hasNext()) {
Object obj=iterator.next();//next()方法取出的元素类型是Object,可以接收任意的数据类型
System.out.print(obj + " ");
}
}
}
public class GenericDemo08 {
public static void main(String[] args) {
//array1集合限定数据类型为Integer
ArrayList<Integer> array1=new ArrayList<Integer>();
array1.add(111);
array1.add(222);
array1.add(333);
array1.add(444);
array1.add(555);
System.out.print("遍历Integer数据类型的array1集合:");
IteratorArrayList.printing(array1);
System.out.println();
System.out.println("====================================");
//array2集合限定数据类型为String
ArrayList<String> array2=new ArrayList<String>();
array2.add("一号元素");
array2.add("二号元素");
array2.add("三号元素");
array2.add("四号元素");
array2.add("五号元素");
System.out.print("遍历String数据类型的array2集合:");
IteratorArrayList.printing(array2);
}
}
那么,以上就是我对 Java 泛型的理解,欢迎大家留言评论,一起学习,共同进步!!!😄😄😄