泛型即“参数化类型”,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型参数),然后在使用时传入具体的类型(类型实参)。
一、泛型在类中的使用
写一个Person类(用泛型)
public class Person<T,M> {
private int age;
private String name;
private T haha; //T 类型的haha
private M xixi; //M 类型的xixi
//加上getset访问器(源码不赘述)
注:<>中的泛型可以为一个也可以为多个(实现类时必须去泛型)
测试时:传入String 与 integer(int的包装类),于是T 为String类,M为integer类
public static void main(String[] args) {
Person<String, Integer> p = new Person<>();
p.setHaha("哈哈"); //存入string类型
System.out.println(p.getHaha());
p.setXixi(3); //存入int类型
System.out.println(p.getXixi());
}
运行结果:
二、泛型在接口中的使用
与在类中的使用相似,只不过在实现接口时可以选择去泛型,也可以选择继续使用泛型。
1.实现接口时去泛型:
先写一个用泛型的接口:
public interface Person2 <T> {
T print();
}
实现接口:
public class Student implements Person2<String>{ //传入字符类型
private String text = "我是字符串";
@Override
public String print() { //print方法返回类型自动变为String类型
return text;
}
测试及结果:
public static void main(String[] args) {
Student s = new Student();
System.out.println(s.print());
}
2、实现接口时继续用泛型:
public class Student<T> implements Person2<T>{
private T text; //依旧为T型变量
@Override
public T print() {
return text;
}
}
三、泛型在方法中的使用
方法传入的参数为泛型,后面在实现时,传入什么类型,便会将泛型匹配为什么类型!
注:泛型的范围就只是此方法的范围
public class Student{
public static <T> void print(T t){ //泛型方法
System.out.println(t);
}
public static void main(String[] args) {
print(3); //传入3,自动将T匹配为integer类型
}
四、泛型限制类型(如何限制泛型有多泛~)
我们写泛型,通常是什么类型都可以,但是如果我们想要限制泛型的范围,应该如何限制呢?
用一个例子来讲:先写一个水果接口,我们下面写了一个盘子类,泛型想要限制为水果接口的所有子类,而不能传入其他的类(string \ int 等类)
解决方法:将泛型 extends 类(接口)1 & 接口2
interface Fruit{}
class Apple implements Fruit{} //apple为Friut的一个实现类
class plate<T extends Fruit>{ //泛型T 限定为Fruit接口的所有实现类(eg:apple)
T date;
}
这样子plate传入的类型只能是Fruit接口的实现类Apple
public class Demo3 {
plate<Apple> p = new plate<>();
}
五、 泛型中的通配符
如果我想在泛型中用多态 eg: 用水果盘子new一个苹果盘子对象,会报错。
解决方法:使用泛型的通配符 ?
1、指定泛型类型的上届
此行代码的意思为plate传入的泛型可以为水果接口的任何实现(子)类,于是后面的苹果类不再报错
public class Demo3 {
plate<? extends Fruit> p = new plate<Apple>();
}
2、指定泛型类型的下届
此行代码的意思为plate传入的泛型可以为苹果类的任何父类,于是后面的苹果类不再报错
public class Demo3 {
plate<? super Apple> p = new plate<Fruit>();
}
3、没有限制的泛型类型
传入任何类型都可以接收。约等于object类,但是不同的在于,object在后来调用时,传string就是string类型,传int就是int类型。但是?如果调用的时候写成了string类型,那么以后调用的时候就只能传string。
public class Demo3 {
plate<?> p = new plate<Fruit>();
plate<?> p2 = new plate<Apple>();
}