public class MyClass{ } 含义是要求传入T的类型必须是Number或者Number的子类型
在实际应用中可能会需要对传递给类型参数的类型加以限制。比如需要创建一个泛型类,它包含了一个求数组平均值的方法。这个数组的类型可以是整型、浮点型,但显然不能是字符串类型或是其他非数值类型。
Java提供了有界类型bounded types。在指定一个类型参数时,可以指定一个上界,声明所有的实际类型都必须是这个超类的直接或间接子类。
class classname
//要求传入的泛型类型必须是Number抽象类的子类
public class Generic{
public double sum(T... params) {
double res=0;
for(int i=0;i
调用方法:
Genericg=new Generic<>():
double sum=g.sum(1L,2L,3L,4L,5L,6L);
System.out.println(sum);因为Long是Number的子类,但是换一种类型String则会报错
Generic
g=new Generic<>(); //报错的原因是String不是Number的子类型 另外调用方式
Genericg=new Generic<>();
double sum=g.sum(1,2,3,4,5); //写法正确,因为Integer(1)也是Number类型的
接口和类都可以用来做上界。class Stats
。
这里需要注意:针对上界接口使用的关键字仍然是extends而非implements。一个类型参数
可以有多个限界,如class Stats。限界类型
用&分隔,因为逗号用来分隔类型参数。在多个限界中,可以有多个接口,但最多只能有一个类。如果用一个类作为限界,它必须是限界列表中的第一个。
import java.io.Serializable;
import java.util.Date;
public class Test2 {
public static void main(String[] args) {
// MyClass mc=null;
// MyClass mc2=null;
MyClass mc1=new MyClass<>();
MyClass mc2=new MyClass<>();
MyClass mc3=new MyClass<>();
mc3.add(123); //Integer是Number的子类型
mc3.add(12.345);
Number kk=mc3.get();
A2 aa=new A2<>();
D2 dd=new D2<>();
}
}
class MyClass{
private T id;
public void add(T t) {
this.id=t;
}
public T get() {
return id;
}
}
class A2&Serializable>{
}
class B2 implements Comparable,Serializable{
@Override
public int compareTo(B2 o) {
return 0;
}
}
//如果上限类型为类,不是接口,则只能有一个;如果有多个,则至少一个是接口
class C2 {
}
class E2 {
}
class F2 {
}
class G2 extends E2 {
}
class H2 extends F2 {
}
class T2{}
class D2 {
T id;
String name;
}
class Y2{
}
使用一般用于接收参数
void doSomething(Stats> ob) 表示这个参数ob可以是任意的Stats类型。
其中?表示一个不确定的类型,它的值会在调用时确定下来。List> list = new ArrayList
(); 注意不能写成 List
public class Test{
public void pp(List> list){
list.add("123"); //语法报错
}
public static void main(String[] args){
List list=new ArrayList<>();
list.add("bbbb");
Test t=new Test();
t.pp(list);
}
}
这里的List>中的?表示可以传人任意的类型参数,其中List> list可以匹配任意参数化的类型,但是到底匹配的是什么类型,只有以后才知道,所以cols=new ArrayList
和 cols = new ArrayList
都可以, 但是cols.add("abc")或cols.add(new Date())都不行
public static void printCollection(Collection> collection){
for(Object obj:collection)
System.out.println(obj);
//collection.add("abc");//报错,因为collection不知道未来匹配的一定是String类型
collection.size();//不报错,此方法与参数类型没有关系
collection=new HashSet();//这是可以的
}
public class A{
private ID id;
private T name;
}
public interface IA{
public T pp();
}
定义泛型类上给泛型添加约束
public class MyClass
{}
在泛型类或者泛型接口中不允许直接使用super
List super Integer> array = new ArrayList
(); Integer 可以认为是 Integer 的 "父类"
List super Integer> array = new ArrayList
(); Number 是 Integer 的 父类
List super Integer> array = new ArrayList
Object 是 Integer 的 父类
如果要求泛型实现两个或者两个以上的接口
public class MyClass
{}
要求传入的类型T必须同时实现了接口1和接口2如果要求泛型必须继承B类,同时实现IC接口
public class MyClass{}
如果要求泛型继承一个类并且实现接口
public class MyClass{}
extends T>只能用于方法返回,告诉编译器此返参的类型的最小继承边界为T,
T和T的父类都能接收,但是入参类型无法确定,只能接受null的传入
super T>只能用于限定方法入参,告诉编译器入参只能是T或其子类型,而返参只能用Object类接收- ' ? '既不能用于入参也不能用于返参
- 频繁往外读取内容的,适合用上界extends
- 经常往里插入的,适合用下界Super
import java.util.ArrayList;
import java.util.List;
public class Test1 {
public static void main(String[] args) {
List list=new ArrayList<>();
list.add("bbbb");
Test1 t1=new Test1();
t1.pp(list);
// t1.bb(list); //List和List