1.概述
1.泛型,即“参数化类型”。就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定 义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
通俗来说:有时候需要传递的参数类型程序员也不知道传什么样的类型合适,这时候就是通过定义类型为泛型,当接受后参数类型变为传递的具体类型。
2.使用
-
泛型在类中的使用
定义一个泛型类:
public class ClassName<T>{
private T data;
public T getData() { return data; }
public void setData(T data) { this.data = data; }
}
下面举例子说明:
1.设置一个person类,定义一个<T>--泛型属性,这时创建person对象需要将泛型转换成一个具体类型,也就是创建引用时传递的具体类型。
public class Person<T> {
private int age;
private T data;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", data=" + data +
'}';
}
}
2.创建test类提供main方法。
public class PersonTest {
public static void main(String[] args) {
Person<String> person1 =new Person<>();
person1.setData("hahaha");
System.out.println("传递的参数为string类型"+person1);
Person<Integer> person2= new Person<>();
person2.setData(100);
System.out.println("传递的类型为integer类型"+person2);
}
}
我们分别创建两个person对象,一个传递给string类型,一个传递给integer类型。并分别设置他们的属性。
输出结果
这里没有设置age的值,默认输出为0.
注意:在编译之后程序会采取去泛型化的措施。 也就是说Java中的泛型,只在编译阶段有效。 在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加 类型检查和类型转换的方法。也就是说,泛型信息不会进入到运行时阶段。
-
泛型在接口中的使用
定义一个泛型接口:
public interface IntercaceName<T>{
T getData();
}
1.实现接口时,可以选择指定泛型类型,也可以选择不指定, 如下:
public class InterFaceTest implements InterFaceName<String> {
private String test;
@Override
public String getData() {
return test;
}
2.不指定类型:泛型类实现泛型接口,里面的泛型并没有赋值。如下:
public class InterFaceT<T> implements InterFaceName<T>{
private T test;//定义的泛型属性
private int a;//定义int类型的属性
@Override
public T getData() {
return null;
}
}
-
泛型在方法中的使用
private static <T> T 方法名(T a, T b) {}//传递的类型为T类型,在返回类型前面声明,返回的类型也为T,这里的为特殊情况,下面声明一个返回值为void的方法做为例子。
public class Demo {
public static void main(String[] args) {
print(123);
print("hahaha");
}
public static <A> void print(A a){
System.out.println(a);
}
}
输出结果:
-
泛型中的一些特殊规则
泛型限制类型
1. 在使用泛型时, 可以指定泛型的限定区域 , - 例如: 必须是某某类的子类或 某某接口的实现类,格式:
<T extends 类或者接口1 & 接口2>
public class Demo {
public static void main(String[] args) {
Plate<Apple> plate = new Plate<>();
}
}
interface Fruit{}
class Apple implements Fruit{}
class Plate<T extends Fruit>{
T data;
}
这时创建的对象传递的类型只能为Fruit接口的实现类或者继承接口或者Fruit接口
泛型中的通配符 ?
类型通配符是使用?代替方法具体的类型实参。
1 <? extends Parent> 指定了泛型类型的上届
2<? extends Child> 指定了泛型类型的下届
3<?> 指定了没有限制的泛型类型 (可以当作Object看待但是不完全相同,Object可以传递任意参数,"?"这个一旦接受了参数,之后就会只接受最初的类型)
我们通过上面的代码想实现这样的内容,将一个装着苹果的盘子声明为一个装着水果的盘子。我们发现这样的操作是无法实现的。
这时候通过这样的操作实现:
Plate<? extends Fruit> plate1 = new Plate<Apple>();// 指定了泛型类型的下届为Fruit的子类
Plate<? super Apple> plate2 = new Plate<Fruit>();//指定了泛型类型的上届为Apple的父类
-
作用