引入泛型的原因
泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
引入泛型的意义
适用于多种数据类型执行相同的代码(代码复用)
public class FloatTest01 {static abstract class Animal {public abstract void eat();}static class Cat extends Animal {@Overridepublic void eat() {System.out.println("猫吃鱼");}}static class Dog extends Animal {@Overridepublic void eat() {System.out.println("小狗吃骨头");}}public static void animalEat(Cat cat) {cat.eat();}public static void animalEat(Dog dog) {dog.eat();}public static <T extends Animal> void animalEatUp(T t){t.eat();}public static void main(String[] args) {Cat cat = new Cat();animalEat(cat);Dog dog = new Dog();animalEat(dog);System.out.println("------------------------");animalEatUp(cat);animalEatUp(dog);}}
通过看这个例子就可以看出来,实现了代码的复用.(多多少少也有一点多态的影子)
泛型的使用
泛型类
public class Float<T> { //泛型标识,符号不做限制.T是类型的简称.//value的类型由T指定.private T value; //返回值的类型也由T指定.public T getValue() {return value;}//设置值的类型也由T指定.public void setValue(T value) {this.value = value;}public static void main(String[] args) {Float<String> strFloat = new Float<>();strFloat.setValue("我是string");System.out.println(strFloat.getValue());System.out.println("=======================");Float<Integer> intFloat = new Float<>();intFloat.setValue(1);System.out.println(intFloat.getValue());}
}
多元泛型
public class ManyFloat<K,V> { //指定了两个泛型类型 private K key;private V value;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 static void main(String[] args) {ManyFloat<String, String> strManyFloat = new ManyFloat<>();strManyFloat.setKey("字符串key");strManyFloat.setValue("字符串value");System.out.println(strManyFloat.getKey() + strManyFloat.getValue());System.out.println("===================");ManyFloat<Integer, Integer> intManyFloat = new ManyFloat<>();intManyFloat.setKey(1);intManyFloat.setValue(2);System.out.println(intManyFloat.getKey()+ "--" + intManyFloat.getValue());}
}
泛型接口
public interface FloatInterface<T> { //接口上定义泛型.//定义抽象方法,返回值为泛型类型.public T getValue();
}class FloatInterfaceImpl<T> implements FloatInterface<T> {private T value;//构造方法设置属性内容public FloatInterfaceImpl(T value) {this.value = value;}@Overridepublic T getValue() {return value;}public static void main(String[] args) {FloatInterfaceImpl<String> strImpl = new FloatInterfaceImpl<>("我是string参数");System.out.println("值为" + strImpl.getValue());System.out.println("====================");FloatInterfaceImpl<Integer> intImpl = new FloatInterfaceImpl<>(11);System.out.println("值为" + intImpl.getValue());}
}
泛型方法
public class FloatMethod {//第一个<T>声明此方法有一个泛型T.也可以理解为此方法为泛型方法.//第二个T是返回值类型.//第三个<T>代表T的具体类型.public <T> T getObject(Class<T> c) throws Exception {T t = c.newInstance();return t;}public static void main(String[] args) throws Exception {FloatMethod floatMethod = new FloatMethod();ManyFloat object = (ManyFloat) floatMethod.getObject(Class.forName("com.itbo.Genericity.ManyFloat"));object.setValue("泛型方法");System.out.println(object.getValue());}
}
为什么要用泛型方法
因为泛型类要在实例化的时候就指明类型,如果想换一种类型,不得不重新new一次,可能不够灵活;而泛型方法可以在调用的时候指明类型,更加灵活.
泛型上下限
public class FloatUpAndLow {class A {}class B extends A{}public static void testFloatUpAndLowA(A a){}public static void testFloatUpAndLowB(B b){testFloatUpAndLowA(b);}public static void testFloatUpAndLowC(List<A> listA) {}//这里会有异常public static void testFloatUpAndLowD(List<B> listB) {testFloatUpAndLowC(listB); }
}
解决方式
为了解决泛型中隐含的转换问题,Java泛型加入了类型参数的上下边界机制。<? extends A>表示该类型参数可以是A(上边界)或者A的子类类型。
public static void testFloatUpAndLowC(List<? extends A> listA) {}public static void testFloatUpAndLowD(List<B> listB) {testFloatUpAndLowC(listB); }
泛型上下限的引入
在使用泛型的时候,我们可以为传入的泛型类型实参进行上下边界的限制,如:类型实参只准传入某种类型的父类或某种类型的子类。
上限
public class FloatUpAndLow {@Dataclass Up {private String value;public Up(String value) {this.value = value;}}class UpSon extends Up {public UpSon(String value) {super(value);}}@Datastatic class UpTest<T extends Up> { // 此处泛型只能是Up类型和Up的子类.private T value; // 定义泛型变量public void setValue(T var) {this.value = var;}public T getVar() {return this.value;}@Overridepublic String toString() { // 直接打印return this.value.toString();}}public static void main(String[] args) {UpTest<Up> upUpTest = new UpTest<>();UpTest<UpSon> upSonUpTest = new UpTest<>();}
}
下限
public class FloatUpAndLow2 {public static void main(String[] args) {Low<String> stringLow = new Low<>();Low<Object> objectLow = new Low<>();stringLow.setVar("我是字符串.");objectLow.setVar(new Object());test(stringLow);test(objectLow);}public static void test(Low<? super String> arg) {System.out.println(arg + ",");}}class Low<T> {private T value; // 定义泛型变量public void setVar(T var) {this.value = var;}public T getVar() {return this.value;}@Overridepublic String toString() { // 直接打印return this.value.toString();}
}
总结
1:<?> 无限制通配符.
2:<? extends E> extends 关键字声明了类型的上界,表示参数化的类型可能是所指定的类型,或者是此类型的子类.
3:<? super E> super 关键字声明了类型的下界,表示参数化的类型可能是指定的类型,或者是此类型的父类.
有了方向,还会怕走错路嘛.
如果大家喜欢我的分享的话,可以关注我的微信公众号
心有九月星辰
