java泛型
T、E、?、K、V
Java源码中的Class代表这个类型所对应的类,而Class<?>表示类型不确定的类。
T
:表示确定的Java类型
E
:Element (在集合中使用,因为集合中存放的是元素,也表示Collection容器中的类型)
?
:是一种无限的符号,代表任何类型都可以
K、V
:java中的键值对key、value
泛型的好处
1、提供编译时的类型检查机制。
2、减少数据类型转换
泛型类中常用的泛型标识:T、E、K、V
K、V通常联合使用,用到hashmap中
泛型类
使用语法:类名<具体数据类型> 对象名 = new 类名<具体的数据类型>();jdk1.7后,后一个<>中的数据类型省略。
泛型类在创建对象的时候来指定类型
/**
* 泛型类定义
* @param <T>:T是创建对象的时候指定具体的数据类型
*/
public class MainClass2<T> {
// 是由外部使用类的时候指定
private T key;
public MainClass2(T key) {
this.key = key;
}
public T getKey() {
return key;
}
public void setKey(T key) {
this.key = key;
}
@Override
public String toString() {
return "MainClass2{" +
"key=" + key +
'}';
}
}
//------------------使用--------------------
public class MainClass3 {
public static void main(String[] args) {
// 指定String类型
MainClass2<String> strmain = new MainClass2<>("StringType");
String str = strmain.getKey();
System.out.println(str);
// 指定Integer类型
MainClass2<Integer> intmain = new MainClass2<>(100);
Integer ints = intmain.getKey();
System.out.println(ints);
// 泛型类在创建对象的时候,没有指定类型,将按照Object类型来操作
MainClass2 objmain = new MainClass2(true);
Object boolObj = objmain.getKey();
System.out.println(boolObj);
}
}
1、泛型没有指定具体类型,则默认是Object。
2、泛型不支持基本数据类型,只能是类类型。
3、同一个泛型类创建的对象本质上是同一个类型。
泛型类继承
从泛型类派生子类
1、子类也是泛型类,父类的泛型表示要和子类的相同
class ChildGeneric<T> extends Generic<T>
。
class ChildGeneric<T,E> extends Generic<T>
。
2、子类不是泛型类,父类要明确泛型的数据类型
class ChildGeneric extends Generic<String>
。
子类是泛型类:
/**
* 如果父类不声明类型,父类默认是Object
* @param <T>
*/
public class ChildGeneric<T> extends Parent<T>{
@Override
public T getValue() {
return super.getValue();
}
}
子类不是泛型类
/**
* 没有指定父类的类型
*/
public class ChildGenerics extends Parent{
@Override
public Object getValue() {
return super.getValue();
}
}
/**
* 指定父类的类型
*/
public class ChildGenerics extends Parent<Integer>{
@Override
public Integer getValue() {
return super.getValue();
}
}
泛型接口
接口语法:
public interface 接口名称<泛型标识>{
泛型标识 方法名();
}
实现类:
实现类不是泛型
1、接口要制定类型
public class ProductImpl implements Produces<String>{
@Override
public String findall() {
return null;
}
}
实现类是泛型
1、实现类和接口的泛型类型要一致
/**
* 如果父类不声明类型,父类默认是Object
* @param <T>
*/
public class ChildGeneric<T> extends Parent<T>{
@Override
public T getValue() {
return super.getValue();
}
}
泛型方法
语法:
修饰符 <T、E、…> 返回值类型 方法名(形参列表){ 方法体 }
1、public 与返回值中间非常重要,可以理解为声明此方法为泛型方法
2、只有声明了泛型方法才是泛型方法,泛型类中使用了泛型的成员方法斌不是泛型方法
3、表名该方法将使用泛型类型T
4、与泛型类一样,T可以随便写成任意标识,常用的有T、E、K、V等形式的参数。
public <E> E getProductid(ArrayList<E> list){
return list.get(random.nextInt(list.size()));
}
在测试中调用方法
ProductGetter<Integer> productGetter1 = new ProductGetter<>();
ArrayList<String> strList = new ArrayList<>();
strList.add("drfgd");
strList.add("segfs");
strList.add("shrd");
strList.add("seh");
String product = productGetter1.getProduct(strList);
System.out.println(product+"\t"+product.getClass().getSimpleName());
通配符
?代替的是实参
,可以是代替具体实参,所以?
是类型实参,不是类型形参。
public class test {
public static void main(String[] args) {
Box<Number> box1 = new Box<>();
box1.setFirst(100);
showBox(box1);
System.out.println("---------------------------------");
Box<Integer> box2 = new Box<>();
box2.setFirst(200);
showBox(box2);
System.out.println("---------------------------------");
Box<String> box3 = new Box<>();
box3.setFirst("ajsyg");
showBox(box3);
}
// 接收返回值的时候只能用`Object`类型接收
public static void showBox(Box<?> box){
Object first = box.getFirst();
System.out.println(first);
}
}
通配符的上限
语法:
类/接口<? extends 实参类型>
要求:
该泛型的类型,只能是实参类型,或实参类型的子类类型。
<? extends 类型>
:
表示?的上限最大只能到达Number
,可以是他的子类。
接收返回值时可以使用Number
。
public static void showBox(Box<? extends Number> box){
Object first = box.getFirst();
System.out.println(first);
}
通配符的下限
语法:
类/接口<? super 实参类型>
要求:
要求该泛型的类型,只能是实参类型,或者实参类型的父类类型。
public static void lowBox(Box<? super Integer> box){
Object first = box.getFirst();
System.out.println(first);
}
// 在主方法中
Box<Number> box4 = new Box<>();
box4.setFirst(100);
lowBox(box4);