泛类
泛型类
public class Container<K, V> {
private K key;
private V value;
public Container(K k, V v) {
key = k;
value = v;
}
public K getKey() {
return key;
}
public void setKey(K key) {
this.key = key;
}
public V getValue() {
return value;
}
public void setValue(V value) {
this.value = value;
}
}
public class Main {
public static void main(String[] args) {
Container<String, String> c1 = new Container<String, String>("name", "findingsea");
Container<String, Integer> c2 = new Container<String, Integer>("age", 24);
Container<Double, Double> c3 = new Container<Double, Double>(1.1, 2.2);
System.out.println(c1.getKey() + " : " + c1.getValue()); // name : findingsea
System.out.println(c2.getKey() + " : " + c2.getValue()); // age : 24
System.out.println(c3.getKey() + " : " + c3.getValue()); // 1.1 : 2.2
}
}
泛型接口
Generator规定了需要有一个next方法,这个方法的返回类也是根据传入的类型而定的
public interface Generator<T> {
public T next();
}
FruitGenerator实现了Generator接口
public class FruitGenerator implements Generator<String> {
private String[] fruits = new String[]{"Apple", "Banana", "Pear"};
@Override
public String next() {
Random rand = new Random();
return fruits[rand.nextInt(3)];
}
}
调用
public class Main {
public static void main(String[] args) {
FruitGenerator generator = new FruitGenerator();
System.out.println(generator.next());
System.out.println(generator.next());
System.out.println(generator.next());
System.out.println(generator.next());
}
}
输出每次都随机打印Apple、Banana、Pear中的一个
泛型方法
泛型方法
public class Main {
public static <T> void out(T t) {
System.out.println(t);
}
public static void main(String[] args) {
out("findingsea");
out(123);
out(11.11);
out(true);
}
}
输出
findingsea
123
11.11
true
这里用到了可变参数
public class Main {
public static <T> void out(T... args) {
for (T t : args) {
System.out.println(t);
}
}
public static void main(String[] args) {
out("findingsea", 123, 11.11, true);
}
}
泛型参数的界限
通过方式规定泛型的界限
public class NumberTest<T extends Integer> {
private T num;
public NumberTest(T num) {
this.num = num;
}
public boolean isOdd() {
return num.intValue() % 2 == 1;
}
}
调用
public class Main {
public static void main(String[] args) {
NumberTest<Integer> nt = new NumberTest<>(123);
}
}
接着引入下一个问题,如何为泛型参数添加多个限制范围,多重限制范围格式如下:
<T extends A & B & C>
一个泛型参数可以有多重限制范围,使用“&”分隔。且限制范围中之多有一个类。如果用一个类作为限定,它必须是限定列表中的第一个。举例如下:
Class A { /* ... */ }
interface B { /* ... */ }
interface C { /* ... */ }
class D <T extends A & B & C> { /* ... */ }
注意A,B,C要放在D前面,否则无法通过编译
泛型方法与泛参界限的组合
如果说泛型方法是一个有用的工具,那泛参的界限就应该这个工具的灵魂,为这个工具添加了一些“行为准则”。如下:设计一个方法,统计在一个数组里比指定元素大的个数,
public class Main {
public static <T> int countGreater(T[] array,T elem) {
int count = 0;
for (T t : array) {
if (t > elem) {// Error, Operator can not applied to 'T', 'T'
++count;
}
}
return count;
}
}
发现上面这个方法无法通过编译,为什么呢??因为操作符“>”只可以用在基本数据类型(byte,char,short,int,float,long,double,boolean),却不可以用来比较类对象之间的大小(除非实现了Comparable接口)。想要解决这个矛盾,就需要为添加一个界限Comparable:
public interface Comparable<T> {
public int compareTo(T o);
}
然后将Comparable定为泛型的界限,再用compareTo替代">"运算符
public class Main {
public static <T extends Comparable<T>> int countGreater(T[] array,T elem) {
int count = 0;
for (T t : array) {
if (t.compareTo(elem) > 0) {//无编译错误
++count;
}
}
return count;
}
}
泛型、继承与子类型
这种“is-a”关系,同样也是用泛型。如果你将泛参设置Number,那么在随后的调用里,只需要传入一个数据对象就行了,如下:
Box<Number> box = new Box<>();
box.add(new Integer(1));
box.add(new Double(1.0));
但是方法中的Number泛型类却不能接受Integer和Double的参数
public void someMethod(Box<Number> n) { /*.....*/}
因为Box与Box都不是Box的子类。
泛型类与子类型
泛型的“extends”与继承的“extends”并不一样,泛型的“extends”其后可以是一个类(如T extends Number),同样也可以是一个接口(如T extends List)。泛型的”extends“代表子类型,而不是子类。
在泛型里,也存在子类型,前提是其泛型参数的限制并没有改变,可以认为泛参没有改变,其实就是从原来的类或接口来判断泛型的子类型。为了形象理解,我们已collection类来作个例子,如:ArrayList implement List,而List extends Collection,那么ArrayList就是List的子类型,而List则是Collection,其关系图如下:
深入一点来谈,现在假设需要定义自己的List接口 — PayLoadList,其定义如下:
interface PayloadList<E,P> extends List<E> {
void setPayload(int index, P val);
//...
}
如上,则下面的样例都是List子类型,:
PayloadList<String,String>
PayloadList<String,Integer>
PayloadList<String,Exception>
参考资源:
https://juejin.cn/post/6844903456621199367
https://blog.51cto.com/peiquan/1302898