Java泛型基础总结(代码总结)
1.泛型类
假设不使用泛型,可存储任意类型元素,返回的是Object类型,但是后期操作容易存在类型转换错误。
泛型的本质:类型参数化,将所操作的数据类型指定为一个参数
泛型类的定义
/*
泛型类的定义
T 创建对象的时候来指定的数据类型
*/
public class Generic<T> {
private T key;
public Generic() {
}
@Override
public String toString() {
return "Generic{" +
"key=" + key +
'}';
}
public Generic(T key) {
this.key = key;
}
public T getKey() {
return key;
}
public void setKey(T key) {
this.key = key;
}
}
测试类定义
public class Demo {
public static void main(String[] args) {
//泛型类在创建对象时来制定具体的类型
Generic<String> strGeneric = new Generic<>("a");
String key1 = strGeneric.getKey();
System.out.println(key1);
Generic<Integer> intGeneric = new Generic<>(100);
Integer key2 = intGeneric.getKey();
System.out.println(key2);
//若没有指定类型,则按照Object类处理
Generic generic = new Generic("abc");
Object key3 = generic.getKey();
System.out.println(key3);
}
}
个人理解:可以把自定义的泛型类理解为集合(如ArrayList集合)。其方法都需要自定义.
1.2应用:实现一个抽奖器
泛型类
public class ProductGetter<T> {
private T product;
Random random = new Random();
//奖品池 集合
ArrayList<T> list = new ArrayList<>();
public void addProduct(T t){
list.add(t);
}
public T getProduct() {
product = list.get(random.nextInt(list.size()));
return product;
}
}
1.3泛型类派生子类
泛型父类
public class Parent<E> {
private E value;
public Parent() {
}
public Parent(E value) {
this.value = value;
}
public E getValue() {
return value;
}
public void setValue(E value) {
this.value = value;
}
}
泛型子类1
public class ChildFirst<T> extends Parent<T>{
@Override
public T getValue() {
return super.getValue();
}
}
这里泛型子类1也是泛型,所以其泛型标识必须一致,都为T或者E
泛型子类2
public class ChildSecond extends Parent<Integer>{
@Override
public Integer getValue() {
return super.getValue();
}
@Override
public void setValue(Integer value) {
super.setValue(value);
}
}
这里泛型子类2就不是泛型类,就要明确派生类型。
测试类
public class Demo {
public static void main(String[] args) {
//使用时再确定泛型类型
ChildFirst<String> childFirst = new ChildFirst<>();
childFirst.setValue("abc");
String value = childFirst.getValue();
System.out.println(value);
//子类已经是确定的类
ChildSecond childSecond = new ChildSecond();
childSecond.setValue(45);
Integer value1 = childSecond.getValue();
System.out.println(value1);
}
}
2.泛型接口
public interface Generator<T> {
T getKey();
}
泛型实现类1,其不是泛型类,所以需要明确泛型接口的数据类型
public class Apple implements Generator<String> {
@Override
public String getKey() {
return "hello generator";
}
}
泛型实现类2,其是泛型类,所以泛型的标识要包含泛型接口额标识符
public class Pair<T,E> implements Generator<T>{
private T key;
private E value;
public Pair(T key, E value) {
this.key = key;
this.value = value;
}
public Pair() {
}
@Override
public T getKey() {
return key;
}
public E getValue() {
return value;
}
}
测试类
public class Demo5 {
public static void main(String[] args) {
Apple apple = new Apple();
String key = apple.getKey();
System.out.println(key);
System.out.println("====================");
Pair<String,Integer> pair = new Pair<String, Integer>("James",23);
//类似于Map
String key1 = pair.getKey();
Integer value = pair.getValue();
System.out.println(key1+value);
}
}
3.泛型方法
以前面的抽奖器为例
public class ProductGetter<T> {
private T product;
Random random = new Random();
//奖品池 集合
ArrayList<T> list = new ArrayList<>();
public void addProduct(T t){
list.add(t);
}
public T getProduct() {
product = list.get(random.nextInt(list.size()));
return product;
}
/*
定义了一个泛型方法
<E>泛型列表 这是泛型方法的标志 具体类型 ,由调用方法时指定
*/
public <E> E getProduct(ArrayList<E> list){
return list.get(random.nextInt(list.size()));
}
/*
泛型可变参数的定义
*/
public static <E> void print(E... e){
for (int i = 0; i < e.length; i++) {
System.out.println(e[i]);
}
}
}
测试类
public class Demo6 {
public static void main(String[] args) {
ProductGetter<Integer> productGetter = new ProductGetter<>();
ArrayList<String> stringArrayList = new ArrayList<>();
stringArrayList.add("苹果手机");
stringArrayList.add("华为手机");
stringArrayList.add("笔记本电脑");
stringArrayList.add("扫地机器人");
//对泛型方法的调用,类型是通过调用方法的时候指定 泛型方法独立于泛型类
//Demo3里的是泛型类的成员方法 注意泛型方法和成员方法的区别
String product = productGetter.getProduct(stringArrayList);
System.out.println(product+product.getClass().getSimpleName());
ArrayList<Integer> integers = new ArrayList<>();
integers.add(1000);
integers.add(200);
integers.add(2000);
//成员方法
Integer product1 = productGetter.getProduct(integers);
System.out.println(product1+product1.getClass().getSimpleName());
productGetter.print(1,2,3,4,5);
}
}
4.类型通配符
首先定义一个泛型类
public class Box<T> {
private T first;
public T getFirst() {
return first;
}
public void setFirst(T first) {
this.first = first;
}
}
测试类
public class Demo7 {
public static void main(String[] args) {
Box<Number> box1 = new Box<Number>();
box1.setFirst(100);
showBox(box1);
Box<Integer> box2 = new Box<Integer>();
box2.setFirst(200);
showBox(box2);
}
//?就是类型通配符 类型通配符代表的就是类型实参,而不是类型形参
//? extends Number 类型通配符的上限 只能传Number或者其子类
public static void showBox(Box<? extends Number> box) {
Number first = box.getFirst();
System.out.println(first);
}
}
?就是类型通配符。其代表的就是类型实参,而不是类型形参;
? extends Number 类型通配符的上限,参数只能传Number或者其子类。
还有类型通配符的下限
? super Number 类型通配符的下限,参数只能传Number或者其父类;
5.类型擦除
List<String> l1 = new ArrayList<String>();
List<Integer> l2 = new ArrayList<Integer>();
System.out.println(l1.getClass() == l2.getClass());
输出结果为true。这是因为类型擦除的缘故
通俗地将,泛型类和普通类在JVM里是没有什么差别的。
其实,
在泛型类被类型擦除的时候,之前泛型类中的类型参数部分如果没有指定上限,则会被转译成普通的 Object 类型,如果指定了上限则类型参数就被替换成类型上限。下限也是。