「本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!」前端
虽然写了一段时间的 Java 代码,可是一直以来只要看到泛型,仍是会摸不着头脑选择性放弃。可是今天在看公司大佬的代码发现不少地方会用到泛型,因此今天就整理一下我理解的泛型。java
泛型程序设计(generic programming)是程序设计语言的一种风格或范式。泛型容许程序员在强类型程序设计语言中编写代码时使用一些之后才指定的类型,在实例化时做为参数指明这些类型。 泛型的定义主要有如下两种: 1⃣️ 在程序编码中一些包含类型参数的类型,也就是说泛型的参数只能够表明类,不能表明个别对象。 2⃣️ 在程序编码中一些包含参数的类。其参数能够表明类或对象等等。程序员
👆上面的解释来自百度百科,简单的说 泛型是一种代码范式。后端
Java 泛型的参数只能够表明类,不能表明个别对象。因为 Java 泛型的类型参数之实际类型在编译时会被消除,因此没法在运行时得知其类型参数的类型,并且没法直接使用基本值类型做为泛型类型参数。markdown
Java 泛型设计原则:ide
把类型明确的工做推迟到建立对象或调用方法的时候才去明确的特殊的类型。只要在编译时期没有出现警告,那么运行时期就不会出现 ClassCastException
异常。post
下面是简单的泛型的例子:this
public class Generic {
public static void main(String[] args) {
// C 能够接受 String
C<String> stringC = new C<>("Hello world");
System.out.println(stringC);
// C 能够接受 Integer
C<Integer> integerC = new C<>(100);
System.out.println(integerC);
}
}
// C 能够接受任意类型数据的初始化
class C<T> {
private T item;
public C(T t){
item = t;
}
@Override
public String toString() {
return item + "";
}
}
复制代码
T、E、K、V 本质上都是通配符。编码有时候讲究约定俗成。好比咱们能够用 A-Z 之间的任何一个字母均可以表示通配符,并不会影响程序的正常运行。一般状况下 T、E、K、V 是这样约定的:编码
?
表示不肯定的 Java 类型T ( type )
表示具体的一个 Java 类型K V ( key value )
分别表明 Java 键值中的 Key ValueE ( element )
表明 Element上界通配符 ? extends T
spa
例如 List< ? extends Number>
目的是为了接受List<Integer> or List<Long>
的数据类型。
下界通配符 ? super T
例如 List<? super Number>
目的是为了弥补只能存放一种特定类型数据的不足。
public class Generic {
public static void main(String[] args) {
// 能够
List<? super Number> list = new ArrayList<>();
list.add(10);
list.add(20L);
list.add(20.2);
System.out.println(list);
List<Integer> list1 = new ArrayList<>();
List<Long> list2 = new ArrayList<>();
list1.add(10);
list1.add(20);
list2.add(10L);
list2.add(20L);
read(list1);
read(list2);
}
private static void read(List< ? extends Number> list) {
Number first = list.get(0);
Number last = list.get(list.size() - 1);
System.out.println("first = " + first.toString() + " last = " + last.toString());
}
}
复制代码
最后看一下 PECS(Producer Extends Consumer Super)原则:
// 多参数泛型
class Person<N, A, S> {
private N name;
private A age;
private S sex;
Person(N name, A age, S sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public N getName() {
return name;
}
public void setName(N name) {
this.name = name;
}
public A getAge() {
return age;
}
public void setAge(A age) {
this.age = age;
}
public S getSex() {
return sex;
}
public void setSex(S sex) {
this.sex = sex;
}
@Override
public String toString() {
return "姓名:" + name + ",年龄:" + age + ",性别:" + sex;
}
}
// 使用
public class Generic {
public static void main(String[] args) {
Person<String, Integer, Character> person = new Person<String, Integer, Character>("蛋炒饭", 28, '男');
printPerson(person);
// 姓名:蛋炒饭,年龄:28,性别:男
}
// 泛型方法
private static <T> void printPerson(T person){
if ( person != null) {
System.out.println(person);
}
}
}
复制代码