泛型的本质就是“数据类型的参数化”,因为有时候处理的数据类型不是固定的,所有我们就可以把它看作为形式参数传入进来。告诉编译器,在调用泛型的时候必须传入实际类型,这种参数类型可以用在类、接口、方法中。泛型只是方便了程序员的代码编写,以及更好的安全性检测。
泛型的使用场景
- 不使用泛型的情景:因为Java中所有的类都可以看作Object的子类,所以说我们可以用Object实现任意的参数类型,但是在使用过程中需要进行强制转化,这就需要程序员需要了解具体的类型,可能会产生类型转化异常。但是我们在编译的时候是发现不了这种错误的。只有运行的时候才会发现这种错误。
- 使用泛型:而使用泛型就是可以在编译阶段识别出来这种错误,所有的类型转化由编译器完成,程序员看来都是自动转化的,但是jvm虚拟机和不适用泛型执行的情况是一样的。编译器编译完了是不会生成泛型中的信息的,运行的时候虚拟机并不知道有泛型这个东西,这个也叫类型擦除。
泛型的使用(定义和使用)
1、泛型的定义:泛型的字符可以是任意字符,一般采用一下几个标记
2、泛型类:只有用户使用的时候,才能把类型却确定下来
/**
* 定义泛型的类
*/
public class Generic<T>{
private T flag;
public void setFlag(T flag){
this.flag=flag;
}
public T getFlag(){
return this.flag;
}
}
/**
* 使用定义好泛型类的测试类
*/
public class Test {
public static void main(String[] args) {
Generic<String> generic=new Generic<>();
generic.setFlag("hello world");
System.out.println(generic.getFlag());
Generic<Integer> generic1=new Generic<>();
generic1.setFlag(90);
System.out.println(generic1.getFlag());
}
}
3、泛型接口:和泛型类的声明方式一样,泛型接口的具体类型需要在实现类中进行声明
/**
* 定义泛型接口
* @param <T>
*/
public interface Igeneric <T>{
T getName(T name);
}
/**
* 定义好泛型接口的实现类
*/
public class IgenericImpl implements Igeneric<String>{
@Override
public String getName(String name) {
return name;
}
}
4、泛型方法:泛型方法是指将方法的参数类型定义成泛型,方便再调用的时候接收不同类型的参数。类型的参数有多个,可以用逗号隔开,类型参数一般放到返回值前面,调用方法的时候,不需要告诉编译器是啥类型,编译器可以直接识别出来
静态泛型方法:静态方法无法访问类上定义的泛型,如果静态方法操作的引用数据类型不确定时,必须要将泛型定义在方法上
/**
* 泛型方法的定义
*/
public class MethodGeneric {
//非静态方法
public <T> void getName(T name){
System.out.println(name);
}
public <T> T setName(T name){
return name;
}
//静态方法
public static <T> void setFlag(T flag){
System.out.println(flag);
}
public static <T> T getFlag(T flag){
return flag;
}
//方法中参数可变的类型方法
public <T> void method(T...arr){
for(T t:arr){
System.out.println(t);
}
}
}
/**
* 泛型方法的实现
*/
public class Test3 {
public static void main(String[] args) {
MethodGeneric methodGeneric=new MethodGeneric();
methodGeneric.getName("bjsxt");
methodGeneric.getName(890);
MethodGeneric methodGeneric1=new MethodGeneric();
String name=methodGeneric1.setName("b");
Integer name1=methodGeneric1.setName(80);
System.out.println(name+name1);
}
}
总结:
- 基本数据类型不能用于泛型,可以使用基本数据类型的包装类
- 不能通过类型参数创建对象