Java中的泛型基础 |
您所在的位置:网站首页 › java中super指什么 › Java中的泛型基础 |
1、为什么要使用泛型?
适用于多种数据类型执行相同的代码,利于封装(如,封装Base类、统一的适用于RecyclerView的Adapter等)
泛型中的类型在使用的时候,直接指定即可,不需要进行强制转换。数据转换是很容易带来数据异常的,尤其是当服务端传过来的数据与我们接收的数据类型不同的时候。
2、泛型类、泛型接口、泛型方法
2.1、泛型方法
引入一个类型变量T(其他大写字母都可以,不过常用的就是T,E,K,V等等),并且用括起来,并放在类名的后面。泛型类是允许有多个类型变量的。例如: 一个类型变量 publie class NormalGeneric { private T data; public NormalGeneric() { } public NormalGeneric(T data) { this(); this.data = data; } } 复制代码两个类型变量 public class NormalGeneric2{ private T data; private K result; public NormalGeneric2(){ } } 复制代码 2.2、泛型接口/泛型类 public interface Generator{ public T next(); } 复制代码实现泛型接口的类有两种实现方法: (1)未传入泛型参数时,那么该类也属于泛型类,那么在new出该实例对象时,需要指定具体类型。 // 定义类 public class ImpIGenerator implement Generator{ private T data; } // 实现 注意 STring就是具体类型 ImpIGenerator impIGenerator = new ImpIGenerator(); 复制代码(2)在实现泛型接口时,传入泛型参数,那么在new出该类的实例时,与普通的类就没区别了。 // 类定义 public class ImpIGenerator2 implement Generator{ @Override public String next(){ return "OK"; } } // 实现 ImpIGenerator2 impIGenerator2 = new ImpIGenerator2(); 复制代码 2.3、泛型方法 public class GenericMethod { // public:代表修饰符 :表示泛型方法 T:表示返回值 public T genericMethod(T...a){ return a[a.length/2]; } public void test(int x, int y){ System.out.println(x+y); } } 复制代码泛型方法是在调用方法的时候指明泛型的具体参数类型,泛型方法可以在任何场景中使用,包括普通类和泛型类。但是在泛型类中定义普通方法和泛型方法是有区别的: 普通方法: public class Generic{ private T key; public Generic(T key){ this.key = key; } // 虽然在该方法中使用了泛型,但是这并不是一个泛型方法。 // 这只是类中一个普通的成员方法,只不过他的返回值是在声明泛型类已经声明过的泛型。 // 所以在这个方法中才可以继续使用 T 这个泛型。 public T getKey(){ return key; } } 复制代码泛型方法: // 这才是一个真正的泛型方法。 // 首先在public与返回值之间的必不可少,这表明这是一个泛型方法,并且声名了一个泛型T // 这个T可以出现在这个泛型方法的任意位置 // 泛型的数量也可以是任意多个 // 如:public ... public T showKeyName(Generic generic){ System.out.println("generic key:" + generic.getKey()); T test = generic.getKey(); return test; } 复制代码关键点: 3、限定类型变量有时候我们需要对变量类型进行约束。比如我们定义一个泛型方法: public static T min(T a, T b){ if(a.comapareTo(b) > 0){ return a; } else { return b; } } 复制代码如何才能够保证传进来的a、b两个参数一定有compareTo方法呢?那么我们就要对T进行约束,保证传进来的T参数的类型实现了Comparable类 public static T min(T a, T b){ if(a.comapareTo(b) > 0){ return a; } else { return b; } } 复制代码T extends Comparable 表示,传进来的实例对象必须实现了Comparable类,否则将发生编译错误 extends左右都允许有多个,如**T,V extends Comparable & Serializable** 注意限定类型的时候,只允许有一个类,允许多个接口,如果所限定的类型包含类和接口,那么类要放在最前面,也就是紧跟extends之后的第一个要放类。 类型限定既可以放在泛型方法上,也可以用在泛型类上 T super XXX跟 extends用法一样,只不过super表示传入的类型T只能是XXX或XXX的父类,最高为object类 4、泛型中的约束和局限性现在有一个Restrict泛型类 public class Restrict{} 4.1、不能用基本类型实例化 // Restrict 这种不允许 要使用 Double Restrict restrict = new Restrict(); 复制代码 4.2、运行时,类型查询只适用于原始类型因为类型擦除,Java虚拟机中的对象并没有泛型类这一说,instanceof 和 getClass() 只能查询到原始类型, 具体的泛型类型时无从得知的。 // if(restrict instanceof Restrict){} 这种不允许 // if(restrict instanceof Restrict){} 这种不允许 Restrict restrictString = new Restrict(); System.out.println(restrict.getclass == restrictString.getclass()); System.out.println(restrict.getclass.getName); 复制代码 4.3、泛型类的静态上下文中类型变量失效不能在静态域或静态方法中使用泛型。因为泛型是需要我们在创建对象的时候才知道是什么类型,而对象创建过程中,代码的执行先后顺序是最先执行static部分,然后才是构造函数等。 因此,在对象初始化之前static部分的代码已经执行,而此时的static块并不知道到底是什么类型,因为这个时候我们的对象还没初始化。 // 静态域或者方法里不能引用类型变量 // private static T instance; // 静态方法本身是泛型方法就可以 private static T getInstance(){} 复制代码 4.4、不能创建参数化类型的数组例如 Restrict array = new Restrict[10] 是错误的, 我们只能声明 Restrict[] array; 4.5、不能实例化类型变量 // 不能实例化类型变量 //public Restrict(){ // this.data = new T(); //} 复制代码 4.6、不能捕获泛型类的实例 // 泛型类不能 extends Exception/Throwable //private class Problem extends Exception{} //public void doWork(T) t{ // try{ // ... // } catch (T e){ // ... // } //} 复制代码但可以这样 public void doWork(T t) throws T{ try{ ... } catch (Throwable e){ ... } } 复制代码 5、泛型类型的继承规则现在我们有一个类、子类和一个泛型类 public class Employee{} public class Worker extends Employee{} public class Pair{} 复制代码Pair 和 Pair之间没有任何关系 Employee employee = new Worker(); //Pair employeePair2 = new Pair(); 这行报错 复制代码但是泛型类之间可以继承和扩展其他泛型类(看2.2、泛型接口/泛型类),例如:List和ArrayList Pair pair = new ExtendPair(); private static class ExtendPair extends Pair{} 复制代码 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |