泛型
定义:
泛型指得是“参数化的类型”。通俗来讲就是我们要传入一个变量a,但是a具体是什么类型我们暂不确定,就给它定义为一个泛型(成为类型形参),等到后面a类型确定再传入具体类型(成为类型实参)。
使用:
泛型的使用有三种场景:在类中的使用、在接口中的使用、在方法中的使用。
-
类中的使用:
// 定义一个泛类 public class ClassName<T>{ private T data; public T getData() { return data; } public void setData(T data) { this.data = data; } }
-
接口中的使用:
public interface IntercaceName<T>{ T getData(); } 实现接口时,可以选择指定泛型类型,也可以选择不指定, 如下: 指定类型: public class Interface1 implements IntercaceName<String> { private String text; @Override public String getData() { return text; } } 不指定类型: public class Interface1<T> implements IntercaceName<T> { private T data; @Override public T getData() { return data; } }
-
在方法中的使用:
private static <T>返回类型 方法名(T a,T b){}
泛型的范围限定
泛型的范围限定指的是后面只能有指定的类型才能传入泛型中。
注意的是类名也可以作为一种类型
例如:private Express a;(Express为类)
在泛型范围的限制上有两种场合:
- 在类上限制类型:
interface Fruit{}
class Apple implements Fruit{}
class Plate<T extends Fruit>{
T data;
}
Plate<Apple> p = new Plate<>();
第三行在泛型的限定中,无论是接口还是类统一使用extends
结果:这样限定的泛型T,只能是Fruit的子类。
-
在使用中限制类型:
这种限制就是使用关键字"?"泛型中的通配符;
<? extends Parent>指定泛类型的上界
<? super Child>指定了泛型类型的下届Plate<? extends Fruit> p = new Plate<Apple>(); 指定了泛型只能为Fruit中的子类
<?> 指定了没有限制的泛型类型<? super Apple> p = new Plate<Fruit>(); 泛型只能为Apple的父,或父类的父;
可以简单理解为Object
泛型的作用:
- 提高代码的复用率。
- 泛型中的类型在使用时自动,不需要进行强转,使用更广泛。
泛型的注意事项:
在编译之后程序会采取去泛型化的措施。
也就是说Java中的泛型,只在编译阶段有效。
在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。也就是说,泛型信息不会进入到运行时阶段。