Java泛型
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java泛型,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4236字,纯文字阅读大概需要7分钟。
内容图文
![Java泛型](/upload/InfoBanner/zyjiaocheng/646/a8721c5c979745cdb191554bba500a02.jpg)
一.泛型的概述
? 泛型是java 1.5的新特性,本质是参数化类型,就是将要操作的数据类型指定为一个参数。泛型可以使用在类,接口,方法中,分别叫做泛型类,泛型接口以及泛型方法。
? 比如ArrayList<String> list = new ArrayList<>()
就是一个泛型类。
? 为什么要使用泛型?
? 在没有泛型之前,将数据存入集合,是这样子操作的:
public class GenericTest {
public static void main(String[] args) {
ArrayList array = new ArrayList();
array.add("Hello");
array.add(123);
String str = (String)array.get(0);
int num = (int)array.get(1);
System.out.println(str);
System.out.println(num);
}
}
? 存入数据的时候是可以任意类型,取出来时需要做一个类型转换,这样子操作就存在一个问题,过了许久后可能会忘记了集合的第几个数据是什么类型,一旦搞错,就会产生一个异常java.lang.ClassCastException
? 引入泛型之后,代码就变成了这样子的:
public class GenericTest {
public static void main(String[] args) {
ArrayList<String> array = new ArrayList();
array.add("Hello");
// array.add(123);
String str = array.get(0);
// int num = (int)array.get(1);
System.out.println(str);
// System.out.println(num);
}
}
? 在编译时就已经确定了参数类型为String,如果存入集合的数据不是String,在编译时就会报错,在取出数据时也不需要进行类型转换了,这样一来,使得在运行时可能发生的java.lang.ClassCastException异常在编译时期就能被编译器发现,从而从运行时错误变成了编译时期的错误,并且在使用的时候避免了类型转换的麻烦。
二.泛型的定义
定义泛型类的格式
修饰符 class 类名<代表泛型的变量> { ... }
比如源码中的ArrayList的定义是这样的:
public class ArrayList<E> extends AbstractList<E> ? implements List<E>, RandomAccess, Cloneable, java.io.Serializable { .... }
泛型类的编写比普通类要稍微复杂一些,我们可以根据普通类的编写来进行改造从而完成泛型类的编写。
比如先创建一个普通类Person
public class Person { private String name; public Person(String name) { this.name = name; } public String getName() { return this.name; } }
然后使用T来标记需要指定的类型,这里是String,改写后的Person类如下:
public class Person<T> { private T name; public Person(T name) { this.name = name; } public T getName() { return this.name; } }
定义泛型方法的格式
修饰符 <代表泛型的变量> 返回值类型 方法名(参数) { ... }
比如可以在普通类中定义泛型方法:
public class Person { private String name; public Person(String name) { this.name = name; } public String getName() { return this.name; } public <T> void print (T msg) { System.out.println(msg.getClass()); } }
定义泛型接口的格式
修饰符 interface 接口名<代表泛型的变量> { ... }
比如:
public interface List<E> { .... }
泛型类、泛型方法和泛型接口的确定时间
上面介绍了如何定义泛型,但是这个泛型在什么时候确定泛型类型呢?
对于泛型类,是在创建对象时候确定泛型类型的,比如:`
ArrayList<String> list = new ArrayList<>()
对于泛型方法,是在方法被调用的时候确定泛型类型的,比如
Person p = new Person(); p.print("hello java");
对于泛型接口,是有两种情况存在的:
第一种:在实现接口时候指定泛型类型。
第二种:如果实现接口的时候仍旧使用了泛型,则在创建接口实现类对象时候指定泛型类型。
泛型的定义需要注意的几点
泛型的类型只能是引用类型,不可以是基本类型
<代表泛型的变量> 尖括号里可以使用任意的字母,对编译器来说都是一样的,但是习惯上使用T,E,K,V等字母来表示(完全是因为程序员习惯)
其中主要是因为这些字母都代表了一个含义:
- T :Type(类型)
- E:Element(元素)
- K:Key(键)
- V:Value(值)
三.泛型的通配符
? 泛型有三种类型的通配符:
<? extends T>
:上边界通配符意义:表示只能接受T类型或者T类型的子类型
缺陷:只能读取对象,不能添加任何对象(null除外)
<? super T>
:下边界通配符意义:表示只能接受T类型或者T类型的父类型
缺陷:只能添加对象,不能读取对象(Object除外)
<?>
:无界通配符等同于:<? extends Object>
比如有Object类,String类,Number类,Integer类,其中Number类是Integer类的父类
// 泛型的上边界,此时泛型?,必须是Number或者其子类
public static void getElement1(Collection<? extends Number> c) {}
// 泛型的下边界,此时泛型?,必须是Number或者其父类
public static void getElement2(Collection<? super Number> c) {}
public static void main(String[] args) {
Collection<Integer> list1 = new ArrayList<Integer>();
Collection<String> list2 = new ArrayList<String>();
Collection<Number> list3 = new ArrayList<Number>();
Collection<Object> list4 = new ArrayList<Object>();
getElement1(list1);
getElement1(list2); // error
getElement1(list3);
getElement1(list4); // error
getElement2(list1); // error
getElement2(list2); // error
getElement2(list3);
getElement2(list4);
}
内容总结
以上是互联网集市为您收集整理的Java泛型全部内容,希望文章能够帮你解决Java泛型所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。