一、定义
泛型,即“参数化类型”。就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
例如:GenericClass<T>{} 里面的T可以随意。
方法使用泛型
public class GenericMethod {
/*注意:泛型里面的字母可以自己随意写
* 定义泛型方法格式为:
* 修饰符 <泛型> 返回值类型 方法名(参数列表(使用泛型)){
* 方法体
* }
* */
public <M> void method01(M m){
System.out.println(m);
}
//静态方法
public static <s> void method02(s a){
System.out.println(a);
}
}
public class DemoGenericMethod {
public static void main(String[] args) {
GenericMethod gm = new GenericMethod();
gm.method01(1);
gm.method01(1.1);
gm.method01("abc");
System.out.println("================");
GenericMethod.method02(2);
GenericMethod.method02(2.1);
GenericMethod.method02("efg");
}
}
输出结果:
1
1.1
abc
================
2
2.1
efg
类使用泛型
GenericClass_02.java
/*
* 当不确定类型时,可以使用泛型。
* 泛型在new对象时确定,如果new对象时没有确定,默认是用的是object类型
* */
public class GenericClass_02<E> {
public E getName() {
return name;
}
public void setName(E name) {
this.name = name;
}
private E name;
}
DemoGenericClass_02A.java
public class DemoGenericClass_02A {
public static void main(String[] args) {
GenericClass_02 obj = new GenericClass_02();
obj.setName("字符串");
Object name = obj.getName();//返回的也是object类型
//可以整型
GenericClass_02<Integer> it = new GenericClass_02<>();
it.setName(123);
Integer itReturn = it.getName();
int itReturn01 = it.getName();
//可以是字符串型
GenericClass_02<String> str = new GenericClass_02<>();
str.setName("abc");
String strReturn = str.getName();
}
}
二、存在的意义
1、适用于多种数据类型执行相同的代码(代码复用)
2、泛型中的类型在使用时指定,不需要强制类型转换(类型安全,编译器会检查类型)
三、实现
修饰符 class 类名<代表泛型的变量> { }
四、什么时候确定泛型
1、在创建对象的时候确定泛型
例如,`ArrayList<String> list = new ArrayList<String>();`
2、调用方法时,确定泛型的类型
3、在实现类时确定类型
GenericInterface.java
public interface GenericInterface <I>{
public abstract void method(I i);
}
GenericInterfaceIpl01.java
public class GenericInterfaceIpl01 implements GenericInterface <String>{
@Override
public void method(String s) {
System.out.println(s);
}
}
4、实现类也和接口使用一样的泛型,具体类型在确定对象时确定
public class GenericInterfaceIpl02<I> implements GenericInterface<I> {
@Override
public void method(I i) {
System.out.println(i);
}
}
五、通配符
import java.util.ArrayList;
import java.util.Iterator;
/*
泛型的通配符:
?代表任意数据类型
使用方式:
不能创建对象使用
只能作为方法参数使用
* */
public class GenericClass02 {
public static void main(String[] args) {
ArrayList<String> str = new ArrayList<>();
str.add("abc");
str.add("def");
ArrayList<Integer> it = new ArrayList<>();
it.add(1);
it.add(2);
//==========
method(str);
//=========
method(it);
}
public static void method(ArrayList<?> a){
Iterator<?> it = a.iterator();
while(it.hasNext())
{
it.next();
}
}
}
六、受限泛型
在JAVA的泛型中可以指定一个泛型的**上限**和**下限**。
1、泛型的上限:
* 类型名称 <? extends 类 > 对象名称
* 只能接收该类型及其子类`
2、泛型的下限**:
*类型名称 <? super 类 > 对象名称
*意义: 只能接收该类型及其父类型
六、注意事项
1、一般在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为Object类型。
2、泛型不存在继承关系 Collection<Object> list = new ArrayList<String>();这种是错误的。
3、泛型里面的字母可以自己随意写
七、举例
import java.util.ArrayList;
import java.util.Iterator;
public class ClassGeneric {
public static void main(String[] args) {
//不使用泛型
methodNoGeneric();
//使用泛型
methodGeneric();
}
/*
* 不使用泛型:
* 优点:
* 1、可以存放任何类型对象
* 缺点:
* 1、不安全会引发异常
* */
private static void methodNoGeneric() {
ArrayList arry = new ArrayList();
arry.add("abc");
arry.add(1);
Iterator it = arry.iterator();
while(it.hasNext()){
Object obj = it.next();
//没有是使用泛型,如果要获取长度,需要向下转换
String str = (String) obj; //这里存在一个问题,如果某个obj存放的不是String,
// 运行时会抛出错误ClassCastException
System.out.println(str+"长度是:"+str.length());
}
}
/*
* 使用泛型的优点:
* 1、避免了类型转换的麻烦,存储期是什么类型,取时就自动是什么类型
* 2、将运行期的错误,提升到编译器
* 缺点:
* 1、使用什么泛型,就只能存储什么泛型。
* */
public static void methodGeneric(){
ArrayList<String> arry1 = new ArrayList<>();
arry1.add("abc");
arry1.add("def");
Iterator<String> it = arry1.iterator();
while(it.hasNext()){
String st =it.next();
System.out.println(st + "长度是:"+st.length());
}
}
}