LAB2 收获:泛型
1.定义:
- 泛型:是一种把明确类型的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,而这种参数类型可以用在类、方法和接口中,分别被称为
泛型类
、泛型方法
、泛型接口
。
注意:一般在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为Object类型。
2.优点:
- 避免了类型强转的麻烦。
- 它提供了编译期的类型安全,确保在泛型类型(通常为泛型集合)上只能使用正确类型的对象,避免了在运行时出现ClassCastException。
3.泛型的使用:
泛型虽然通常会被大量的使用在集合当中,但是我们也可以完整的学习泛型只是。泛型有三种 使用方式,分别为:泛型类、泛型方法、泛型接口。将数据类型作为参数进行传递。
3.1泛型类
泛型类型用于类的定义中,被称为泛型类。通过泛型可以完成对一组类的操作对外开放相同的接口。最典型的就是各种集合框架容器类,如: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;
}
}
泛型在定义的时候不具体,使用的时候才变得具体。在使用的时候确定泛型的具体数据类型。即:在创建对象的时候确定泛型。
例如:Generic<String> genericString = new Generic<String>("helloGenerics");
此时,泛型标识T的类型就是String类型,那我们之前写的类就可以这么认为:
public class GenericsClassDemo<String> {
private String t;
public GenericsClassDemo(String t) {
this.t = t;
}
public String getT() {
return t;
}
}
当你的泛型类型想变为Integer类型时,也是很方便的。直接在创建时,T写为Integer类型即可:
Generic<Integer> genericInteger = new Generic<Integer>(666);
- 注意: 定义的泛型类,就一定要传入泛型类型实参么?
并不是这样,在使用泛型的时候如果传入泛型实参,则会根据传入的泛型实参做相应的限制,此时泛型才会起到本应起到的限制作用。如果不传入泛型类型实参的话,在泛型类中使用泛型的方法或成员变量定义的类型可以为任何的类型。即跟之前的经典案例一样,没有写ArrayList
的泛型类型,容易出现类型强转的问题。
3.2泛型方法
泛型方法,是在调用方法的时候指明泛型的具体类型 。
定义格式:
修饰符 <代表泛型的变量> 返回值类型 方法名(参数){ }
例如:
/**
*
* @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
这里可以看出,泛型方法随着我们的传入参数类型不同,他得到的类型也不同。泛型方法能使方法独立于类而产生变化。
3.3泛型接口
泛型接口与泛型类的定义及使用基本相同。泛型接口常被用在各种类的生产器中。
定义格式
修饰符 interface接口名<代表泛型的变量> { }
看一下下面的例子,你就知道怎么定义一个泛型接口了:
/**
* 定义一个泛型接口
*/
public interface GenericsInteface<T> {
public abstract void add(T t);
}
- 使用格式
1、定义类时确定泛型的类型
public class GenericsImp implements GenericsInteface<String> {
@Override
public void add(String s) {
System.out.println("设置了泛型为String类型");
}
}
2、始终不确定泛型的类型,直到创建对象时,确定泛型的类型
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);
}
}