java泛型的使用
2014-03-30 02:37
399 查看
一、概述
1、概念:泛型就是参数化的类型,使用广泛的类型。2、作用:
*安全:指定容器要持有什么类型的对象,而且由编译器来保证类型的正确性。
*省心:所有的类型转换都是自动的和隐式的,提高代码的重用率
二、泛型类
1、格式:< 字母列表>class类名 <字母列表>{
修饰符 字母 属性;
修饰符 构造器 (字母){
}
修饰符 返回类型 方法名(字母){
}
字母列表中的每个字母都代表一种还未确定的引用类型(泛型是在使用时确定具体类型),可以使用任何字母表示,但为了规范使用,一般使用以下常见字母
T 表示Type即类型;
K 和V
分别表示键值中的key和Value
E 表示Element
? 表示不确定的类型(通配符)
2、泛型类在声明时使用泛型,不能将泛型字母使用在静态方法和静态属性上,因为泛型是在使用时确定具体类型,而static是在编译时确定。
3、泛型不能使用基本数据类型,必须使用引用类型,否则编译出错。
下面举一个泛型类的例子说明
public class Student<T1,T2> { private T1 javaScore; private T2 oracleScore; //泛型声明时不能使用 静态属性|静态方法上 //private static T1 test; 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> (); //1、安全:类型检查 stu.setJavaScore("优秀"); //2、省心:类型转换 int it =stu.getOracleScore(); //自动拆箱 } }
三、泛型接口
泛型在接口中的使用与泛型类基本一致,需要注意的是在接口中泛型字母只能使用在方法中,不能使用在全局常量中(接口中的成员变量均为全局常量)。四、泛型方法
泛型方法就是为方法的返回类型签名,< >位于返回类型前面,泛型方法因为类型还未确定,所以只能访问对象信息,不能修改信息。五、泛型的擦除
1.擦除:*在使用时没有指定具体类型
*子类继承|实现时没有指定具体类型
2.后果:
*擦除后不类型检查
*擦除后按Object接收,以Object对待
*存在编译警告,加上Object可以去除,但显得有些画蛇添足
/** * 父类为泛型类 * 1、属性 * 2、方法 * * 要么同时擦除,要么子类大于等于父类的类型, * 不能子类擦除,父类泛型 * 1、属性类型 * 父类中,随父类而定 * 子类中,随子类而定 * 2、方法重写: * 随父类而定 */ public abstract class Father<T,T1> { T name; public abstract void test(T t); } /** * 子类声明时指定具体类型 * 属性类型为具体类型 * 方法同理 */ class Child1 extends Father<String,Integer>{ String t2; @Override public void test(String t) { } } /** * 子类为泛型类 ,类型在使用时确定,大于等于父类的类型 * @author Administrator * */ class Child2<T1,T,T3> extends Father<T,T1>{ T1 t2; @Override public void test(T t) { } } /** * 子类为泛型类,父类不指定类型 ,泛型的擦除,使用Object替换 */ class Child3<T1,T2> extends Father{ T1 name2; @Override public void test(Object t) { // TODO Auto-generated method stub } } /** * 子类与父类同时擦除 */ class Child4 extends Father{ String name; @Override public void test(Object t) { } } /** *错误:子类擦除,父类使用泛型 class Child5 extends Father<T,T1>{ String name; @Override public void test(T t) { } */
/** *泛型的擦除 *1、继承|实现声明 不指定类型 *2、使用时 不指定类型 *统一Object 对待 *1、编译器警告 消除使用Object *2、不完全等同于Object ,编译不会类型检查 */ public class Student<T> { private T javaScore; private T oracleScore; //泛型声明时不能使用 静态属性|静态方法上 //private static T1 test; public T getJavaScore() { return javaScore; } public void setJavaScore(T javaScore) { this.javaScore = javaScore; } public T getOracleScore() { return oracleScore; } public void setOracleScore(T oracleScore) { this.oracleScore = oracleScore; } public static void main(String[] args) { Student stu1 = new Student(); //消除警告 使用 Object Student<Object> stu = new Student<Object>(); //stu.setJavaScore("af"); //以Object对待 test(stu1); //stu1 相当于Object 但是不完全等同Object //擦除,不会类型检查 //test(stu); test1(stu1); test1(stu); } public static void test(Student<Integer> a){ } public static void test1(Student<?> a){ } }
六、泛型没有多态
public class Fruit { } class Apple extends Fruit{ } public class App { public static void main(String[] args) { //A<Fruit> f = new A<Apple>();错误,泛型没有多态 A<Fruit> f =new A<Fruit>(); //test(new A<Apple>());错误 } //形参使用多态 public static void test(A<Fruit> f){ } //返回类型使用多态 public static A<Fruit> test2(){ //return (A<Fruit>)(new A<Apple>());错误 return null; } }
七、通配符?、extends和super在泛型中的使用
1.通配符的作用:虽然泛型没有多态,但通过通配符的使用,我们可以实现类似多态的功能。2.通配符的使用:通配符使用在声明类型|方法上,不能用在声明类或使用时(使用时必须确定类型)。
3.? :表示类型不定,使用时确定类型。
4.? extends classA :表示小于等于,也称作上限,即该类型只能是classA的子类或自身。
5.? super classA :表示大于等于,也称作下限,即该类型只能是classA的父类或自身。
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<Apple>()); //泛型没有多态 //test4(new Student<Apple>()); //< stu = new Student<Fruit>(); //test4(stu); //使用时确定类型 test4(new Student<Object>()); test4(new Student<Fruit>()); } public static void test(Student<?> stu){ } public static void test3(Student<Fruit> stu){ } //extends <= public static void test2(Student<? extends Fruit> stu){ } //super >= public static void test4(Student<? super Fruit> stu){ } }
八、泛型的嵌套
1.声明:嵌套使用泛型A<B<C>> = new A<B<C>>();
2.使用:从外到内,层层拆分
public class Bjsxt <T>{ T stu ; public static void main(String[] args) { //泛型的嵌套 Bjsxt<Student<String>> room =new Bjsxt<Student<String>>(); //从外到内拆分 room.stu = new Student<String>(); Student<String> stu = room.stu; String score =stu.score; System.out.println(score); } }
九、没有泛型数组
可以声明泛型数组,但是不能创建泛型数组。虽然如此,但是我们可以通过使用Object接收,再将其强制转换为泛型数组。public static void main(String[] args) { Integer[] arr = new Integer[4]; //Student<String>[] arr2 = new Student<String>[10]; Student<?>[] arr2 = new Student[10]; MyArrayList<String> strList =new MyArrayList<String>(); strList.add(0, "a"); String elem =strList.getElem(0); System.out.println(elem);} class MyArrayList<E>{ //E[] cap =new E[10]; 没有泛型数组 Object[] cap = new Object[10]; public void add(int idx,E e){ cap[idx] =e; } @SuppressWarnings("unchecked") public E[] getAll(){ return (E[]) cap; } @SuppressWarnings("unchecked") public E getElem(int idx){ return (E) cap[idx]; } }
十、JDK7泛型使用的新特性
JDK1.7中使用泛型,声明一次类型即可,在使用|创建时不用指定类型。例如List<String> arrList2= new ArrayList<>();
终于写完了
第一次写博客,有写的不好的地方还望指教。
相关文章推荐
- java泛型的使用实例
- java泛型(三)、通配符的使用
- java泛型(三)、通配符的使用
- 菜鸟译文(二)——使用Java泛型构造模板方法模式
- java泛型的基本介绍和使用
- java泛型(三)、通配符的使用
- 使用Java泛型和反射机制编写Excel文件生成和解析的通用工具类
- java泛型的使用(四)设置泛型的时候,只能是Number或者Number的子类(int,float)等
- java泛型中通配符的使用
- Java泛型使用
- Java泛型使用小结
- 使用Java泛型应该注意的几个地方
- java泛型(三)、通配符的使用
- java泛型(一)、泛型的基本介绍和使用
- 为什么使用Java泛型 以及 Java泛型使用方法
- java泛型使用的简单规则和限制
- Java泛型在静态方法中的使用
- 使用Java泛型构造模板方法模式
- java泛型操作复习,以及讲解在android中使用的场景
- java泛型中T和?(通配符)的区别与使用声明