泛型
来源:互联网 发布:淘宝网卫生间用品 编辑:程序博客网 时间:2024/06/06 00:25
转自 http://peiquan.blog.51cto.com/7518552/1302898
一、java 泛型引入
List list = new ArrayList();list.add("abc");list.add(new Integer(1));//可以通过编译for (Object object : list) {System.out.println((String)object);//抛出ClassCastException异常}
List<String> list = new ArrayList<>();list.add("abc");//list.add(new Integer(1));//编译错误for (String string : list) {System.out.println(string);//无需任何强制类型转换}
二、泛型的类与接口
public class Gen {private Object obj;public Object getObj() {return obj;}public void setObj(Object obj) {this.obj = obj;}public static void main(String[] args) {Gen gen = new Gen();gen.setObj("abc");String str = (String) gen.getObj();//类型转换,可能会引起运行时ClassCastException}}
public class Gen<T> {T obj;public T getObj() {return obj;}public void setObj(T obj) {this.obj = obj;}public static void main(String[] args) {Gen<String> gen = new Gen<>();gen.setObj("abc");//gen.setObj(10);//无法通过编译String str = gen.getObj();//无需类型转换//-----------------------------Gen gen2 = new Gen();//raw type原始类型gen2.setObj("abc");gen2.setObj(10);//可以通过编译,自动装箱将10转化为Integer对象Integer num = (Integer) gen2.getObj();//使用了强制类型转换}}
细心的你会发现在main()方法里是使用泛型类型Gen<String>,便不再需要强制类型转换,也就移除了运行时的ClassCastException。同时为了区别,在此也定义了一个没有使用泛型类型的gen2,这时,编译器会弹出一个警告“Gen is a raw type,References to generic type Gen<T> should be parameterized”。当我们不提供泛型类型时,会默认使用Object会代替,也是因此这样,gen2可以设置String和Integer类型,不过,我们应尽量去避免这种这种情况的出现,如此,便又需要用到强制类型转换,也伴随着运行时的ClassCastException异常。
public interface List <E> { void add(E x); Iterator<E> iterator();}public interface Iterator<E> { E next(); boolean hasNext();}
三、泛型的命名规范
- E — Element,常用在java Collection里,如:List<E>,Iterator<E>,Set<E>
- K,V — Key,Value,代表Map的键值对
- N — Number,数字
- T — Type,类型,如String,Integer等等
- S,U,V etc. - 2nd, 3rd, 4th 类型,和T的用法一样
四、泛型的方法与构造函数
public class GenMethod {public static <T> void fromArrayToCollection(T[] a,Collection<T> c){for (T t : a) { c.add(t);}}public static void main(String[] args) {Object[] oa = new Object[100];Collection<Object> co = new ArrayList<>();GenMethod.<Object>fromArrayToCollection(oa, co);}}
public static <T> void fromArrayToCollection(T[] a,Collection<T> c){for (T t : a) {c.add(t);c.add(new Object());}}
String[] sa = new String[100];Collection<String> cs = new ArrayList<String>();// T 推断为StringfromArrayToCollection(sa, cs);// T 推断为ObjectfromArrayToCollection(sa, co);Integer[] ia = new Integer[100];Float[] fa = new Float[100];Number[] na = new Number[100];Collection<Number> cn = new ArrayList<Number>();//T 推断为NumberfromArrayToCollection(ia, cn);//T 推断为NumberfromArrayToCollection(fa, cn);//T 推断为NumberfromArrayToCollection(na, cn);//T 推断为ObjectfromArrayToCollection(na, co);//编译错误,Number与String不能兼容fromArrayToCollection(na, cs);
四、泛型参数的界限
public class Box<T> {private T t;public void set(T t) {this.t = t;}public T get() {return t;}public <U extends Number> void inspect(U u) {System.out.println("T: " + t.getClass().getName());System.out.println("U: " + u.getClass().getName());}public static void main(String[] args) {Box<String> integerBox = new Box<>();integerBox.set("abc");//能通过编译,因为T指定为String类型//integerBox.inspect("abc");//不能通过编译,因为U必须是Number类型或其子类integerBox.inspect(new Integer(10));}}
public class NumberTest<T extends Integer> {private T num;public NumberTest(T num) { this.num = num;}public boolean isOdd(){return num.intValue()%2 == 1;}//....}
Class A { /* ... */ }interface B { /* ... */ }interface C { /* ... */ }class D <T extends A & B & C> { /* ... */ }
class D <T extends B & A & C> { /* ... */ } // 无法通过编译
五、泛型方法与泛参界限的综合
public static <T> int countGreater(T[] array,T elem) {int count = 0;for (T t : array) {if (t > elem) {//编译错误++count;}}return count;}
public interface Comparable<T> { public int compareTo(T o);}
public static <T extends Comparable<T>> int countGreater(T[] array,T elem) {int count = 0;for (T t : array) {if (t.compareTo(elem) > 0) {//无编译错误++count;}}return count;}
六、泛型、继承与子类型
String someString = new String();Object someObject = new Object();someObject = someString;
public void someMethod(Number n) { /* ... */ }someMethod(new Integer(10)); // OKsomeMethod(new Double(10.1); // OK
Box<Number> box = new Box<>();box.add(new Integer(1)); box.add(new Double(1.0));
public void someMethod(Box<Number> n) { /*.....*/}
这个方法可以接受什么类型的参数呢??显然,这个方法接受Box<Number>类型的参数??那又是否可以接受Box<Integer>或者Box<Double>类型的参数的??答案是否定的,因为Box<Integer>与Box<Double>都不是Box<Number>的子类。在泛型编程里,这是一个容易混淆的概念,但又必须要懂的原理。如下图:
从图可以看到,即使Integer是Number的子类,但Box<Integer>并不是Box<Number>的子类。Box<Integer>与Box<Number>的共同父类是Object。换言之,无论类A与类B是否存在关联,MyClass<A>与MyClass<B>都没有任何关联,其共同的父类的是Object。那是否说,泛型就不存在子类呢??这个留待解决,看完本文便可以知晓。
七、泛型类与子类型
interface PayloadList<E,P> extends List<E> { void setPayload(int index, P val); //...}
PayloadList<String,String>PayloadList<String,Integer>PayloadList<String,Exception>
如图
0 0
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- 泛型
- C++ 成员函数作为回调函数
- leetcode Jump Game & Jump Game II
- 不可不知的c++易犯错误。
- Consecutive sum II 1977
- Java - 线程安全
- 泛型
- 自然连接(NATURAL JOIN)
- YouCompleteMe插件在linux x64 redhat 下的编译和初步使用
- UML_交互图
- memcached-session-manager 教程实现session共享
- hdu 1686 Oulipo (KMP模板)
- 5月,献给程序员们的经典巨著——APUE .(转载)
- Fileupload控件点击“浏览”按钮,选择图片后需要立即显示所选择的图片
- disk