是一种把明确类型的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,而这种参数类型可以用在类、方法和接口中,分别被称为泛型类、泛型方法、泛型接口。
注意:一般在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为Object类型。
好处:
- 避免了类型强转的麻烦。
- 它提供了编译期的类型安全,确保在泛型类型(通常为泛型集合)上只能使用正确类型的对象,避免了在运行时出现ClassCastException。
使用:
泛型虽然通常会被大量的使用在集合当中,但是我们也可以完整的学习泛型只是。泛型有三种使用方式,分别为:泛型类、泛型方法、泛型接口。将数据类型作为参数进行传递。
泛型方法()
泛型方法,是在调用方法的时候指明泛型的具体类型 。
定义格式:修饰符 <代表泛型的变量> 返回值类型 方法名(参数){ }
/**
*
* @param t 传入泛型的参数
* @param <T> 泛型的类型
* @return T 返回值为T类型
* 说明:
* 1)public 与 返回值中间<T>非常重要,可以理解为声明此方法为泛型方法。
* 2)只有声明了<T>的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。
* 3)<T>表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。
* 4)与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E等形式的参数常用于表示泛型。
*/
public <T> T genercMethod(T t){
System.out.println(t.getClass());
System.out.println(t);
return t;
}
调用方法时
public static void main(String[] args) {
GenericsClassDemo<String> genericString = new GenericsClassDemo("helloGeneric"); //这里的泛型跟下面调用的泛型方法可以不一样。
String str = genericString.genercMethod("hello");//传入的是String类型,返回的也是String类型
Integer i = genericString.genercMethod(123);//传入的是Integer类型,返回的也是Integer类型
}
输出结果:
class java.lang.String
hello
class java.lang.Integer
123
结论:泛型方法随着我们的传入参数类型不同,他得到的类型也不同。泛型方法能使方法独立于类而产生变化。
泛型类
泛型类型用于类的定义中,被称为泛型类。通过泛型可以完成对一组类的操作对外开放相同的接口。最典型的就是各种集合框架容器类,如:List、Set、Map。
泛型类的定义格式:修饰符 class 类名<代表泛型的变量> { }
/**
* @param <T> 这里解释下<T>中的T:
* 此处的T可以随便写为任意标识,常见的有T、E等形式的参数表示泛型
* 泛型在定义的时候不具体,使用的时候才变得具体。
* 在使用的时候确定泛型的具体数据类型。即在创建对象的时候确定泛型。
*/
public class GenericsClassDemo<T> {
//t这个成员变量的类型为T,T的类型由外部指定
private T t;
//泛型构造方法形参t的类型也为T,T的类型由外部指定
public GenericsClassDemo(T t) {
this.t = t;
}
//泛型方法getT的返回值类型为T,T的类型由外部指定
public T getT() {
return t;
}
}
泛型在定义的时候不具体,使用的时候才变得具体。在使用的时候确定泛型的具体数据类型。即:在创建对象的时候确定泛型。
泛型接口
泛型接口与泛型类的定义及使用基本相同。泛型接口常被用在各种类的生产器中。
泛型类的定义格式:修饰符 interface接口名<代表泛型的变量> { }
/**
* 定义一个泛型接口
*/
public interface GenericsInteface<T> {
public abstract void add(T t);
}
使用格式:
定义类时确定泛型的类型
public class GenericsImp implements GenericsInteface<String> { @Override public void add(String s) { System.out.println("设置了泛型为String类型"); } }
始终不确定泛型的类型,直到创建对象时,确定泛型的类型
public class GenericsImp<T> implements GenericsInteface<T> { @Override public void add(T t) { System.out.println("没有设置类型"); } }
确定泛型:
public class GenericsTest { public static void main(String[] args) { GenericsImp<Integer> gi = new GenericsImp<>(); gi.add(66); } }
类型通配符?
当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示。但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用。
通配符基本使用
泛型的通配符:不知道使用什么类型来接收的时候,此时可以使用?,?表示未知通配符。
此时只能接受数据,不能往该集合中存储数据。 ```java // ?代表可以接收任意类型 // 泛型不存在继承、多态关系,泛型左右两边要一样 //ArrayList