泛型作用:
安全:在编译的时候检查类型安全;
省心:所有的强制转换都是自动和隐式的,提高代码的重用率;
1.格式:
class 类型<字母列表>{
修饰符 构造器(字母);
修饰符 返回类型 方法(字母)
}
泛型常见字母:
T Type 表示类型
K V 分别代表键值中的Key和Value
E 代表Element
? 表示不确定的类型
注:泛型声明时,字母不能使用在静态属性、静态方法上;
因为泛型是在使用的时候确定的,静态属性、静态方法编译的时候就确定;
2.使用
使用时指定具体的类型,(不能指定基本类型,而是用引用类型)
1)编译时会进行类型检查;
2)获取数据时不需要进行类型转换
例子1:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.cy.gen; /** * 泛型类:声明时使用泛型 * */ public class Student<T1, T2> { private T1 javaScore; private T2 oracleScore; //private static T1 phpScore; public T1 getJavaScore() { return javaScore; } public void setJavaScore(T1 javaScore) { this.javaScore = javaScore; } public T2 getOracleScore() { return oracleScore; } public void setOracleScore(T2 oracleScore) { this.oracleScore = oracleScore; } public static void main(String[] args) { Student<String, Integer> stu = new Student<String, Integer>(); //使用时指定类型,引用类型 stu.setJavaScore("优秀"); //类型检查 int oracleScore = stu.getOracleScore(); //自动类型转换 } }
例子2,泛型接口:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.cy.gen; public interface Comparator<T> { void compare(T t); }
例子3:泛型方法:
修饰符 <字母> 返回类型 方法名(字母){
}
要定义泛型方法,只需将泛型参数列表置返回值前;
注:泛型还可以定义在方法中,是否拥有泛型方法,与其所在的类是否泛型没有关系。
package com.cy.gen; import java.io.Closeable; import java.io.IOException; /** * 泛型方法 <> 返回类型前面 * 只能访问对象的信息,不能修改信息 */ public class TestMethod { public static void main(String[] args) { test("b"); //T --> String test(1); } //泛型方法 public static<T> void test(T t){ //t.setXXX(); System.out.println(t); } //extends <= //T是Closeable接口的实现类 ...代表可变参数 public static<T extends Closeable> void test(T... a){ for(T temp: a){ try { if(temp!=null) temp.close(); } catch (IOException e) { e.printStackTrace(); } } } }
3.派生子类
属性类型
方法重写
泛型擦除
例子1:父类为泛型:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.cy.gen02; /** * 父类为泛型类 * 1.属性 * 2.方法 * * 要么同时擦除,要么子类大于等于父类的类型 */ public abstract class Father<T, T1> { T name; public abstract void test(T t); } /** * 子类声明时指定具体类型 */ class Child1 extends Father<String, Integer>{ @Override public void test(String t) { } } /** * 子类为泛型类,类型在使用时确定 */ class Child2<T, T1> extends Father<T, T1>{ @Override public void test(T t) { } } /** * 子类为泛型类,父类不指定类型,泛型的擦除,使用Object替换 */ class Child3<T1, T2> extends Father{ @Override public void test(Object t) { } }
例子2:泛型接口:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.cy.gen02; /** * 泛型接口: 与继承同理 * 重写方法随父类而定 * @author CY * * @param <T> */ public interface Comparable<T> { void compare(T t); } //声明子类指定具体类型 class Comp implements Comparable<String>{ @Override public void compare(String t) { } } //擦除 class Comp1 implements Comparable{ @Override public void compare(Object t) { } } //父类擦除,子类泛型 class Comp2<T> implements Comparable{ @Override public void compare(Object t) { } } //子类泛型>=父类泛型 class Comp3<T, T1> implements Comparable<T>{ @Override public void compare(T t) { } }
4.通配符
? extends super
1.可以用在声明类型、声明方法参数上,不能用在声明类上
2.?可以接受泛型的任意类型,只能接收和输出,不能修改。(方法声明时参数无法正确知道具体的类型,因此不能修改)
3.?extends 泛型上限 <= (指定类型为子类或自身)
4. ? super 泛型下限 >= (指定类型为自身或父类)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.cy.gen03; /**通配符 * ? 类型不定,使用时确定类型 * ?使用: 声明类型|声明方法上,不能声明类或使用时用? * * */ public class Student<T> { T score; public static void main(String[] args) { Student<?> stu = new Student<String>(); test(new Student<Integer>()); test2(new Student<Apple>()); test3(new Student<Fruit>()); } public static void test(Student<?> stu){ } // <= public static void test2(Student<? extends Fruit> stu){ } // >= public static void test3(Student<? super Apple> stu){ } } class Fruit{ } class Apple extends Fruit{ }