泛型是什么
- 泛型(generics)是编程语言中的一种类型参数化机制,它允许在定义类、接口或方法时使用类型参数。这些类型参数可以在实际使用时被具体的类型所替换,从而实现代码的复用性和灵活性。通过泛型,可以编写更加通用的组件,同时保持类型安全。
引入
- 在实际的需求中,我们可能会遇见需要接收一个参数但是参数的类型不能确定,最简单的方法就是定义多个类型成员变量, 但随着接收参数的类型增加,去类中创建多个成员变量就会显得很麻烦,比如:当data变量可能为整型、浮点型、布尔型、字符型、字符串型的任何一种,总不能都去创建一个该类型的data成员变量吧,这时候就需要使用泛型了
泛型的应用
泛型在类中的应用
- 如下方代码所示,我们使用了
<t>给该类指定了一个需要接收的参数,这个参数实际上要接收的是一个类型值。这就是泛型参数,而后面的属性的类型,方法参数的类型就是由参数t来决定的:
package com.generic;
//public class box{
public class box<t>{
// private int data;
private t data;
// private string data;
//public void setdata(int data) {
// this.data = data; }
public void setdata(t data) {
this.data = data;
}
//public int getdata() {
// return data;
//}
public t getdata() {
system.out.println("data类型是:" + this.data.getclass());
return data;
}
}- 我们在genericmain类中使用box类,我们先指定box的类型,在创建box的对象,如下方代码所示:
public class genericmain {
public static void main(string[] args){
box <boxinter> = new box<>();
boxinter.setdata(9);
box<string> boxstring = new box<>();
boxstring.setdata("hello world");
//测试用例:
int data = boxinter.getdata();
system.out.println("data的值是:" + data);
string datastr = boxstring.getdata();
system.out.println("data的值是" + datastr);
//输出案例:
//data类型是:class java.lang.integer
//data的值是:9
//data类型是:class java.lang.string
//data的值是hello world
}
}- 拓展:实际上我们平时使用的arraylist容器就是利用率泛型来成为不同类型的容器,即为先指定类型后创建与类型匹配的对象,可以按住
ctrl+右击查看arraylist的源码,会发现实际上arraylist的源码中也有一个泛型参数<e>
//arraylist的源码开头
public class arraylist<e> extends abstractlist<e>{ ... 泛型在接口的应用(多态--类型校验)
- 可以创建一个接口,该接口用于实现,根据不同的类型,进行不同的输出,如下方代码所示:
- 创建一个拥有泛型参数的接口,在接口中创建一个抽象方法
- 抽象方法中指定传入参数的类型由泛型决定
public interface printtable<t> {
void print(t data);
}- 创建实现接口的类
- 先创建一个指定类型为integer的类
package com.generic; //定义类来实现接口 //public class integerprinttable implements printtable{ //我们还需要指定处理泛型中的哪种类型,这样写的好处是java会帮我们做类型检查, //使用接口的对象的泛型该实现类的泛型是否匹配 public class integerprinttable implements printtable<integer>{ // @override // public void print(object data) { } @override public void print(integer data) { system.out.println("我被用于指定输出interger类型的参数" + data); // 提供接口中的抽象方法的具体实现 } }- 创建一个类来实现接口,指定类型为string
package com.generic; //定义类来实现接口 public class stringprinttable implements printtable<string>{ // 提供接口中的抽象方法的具体实现 @override public void print(string data) { system.out.println("我被用于指定输出string类型的参数" + data); } } - 在box类中使用接口
- 为了使用接口,可以先创建一个接口的引用
private printtable<t> printtable; - 创建一个使用该接口的方法printdata(直接调用接口的引用拿到的对象中的print方法);
- 最后我们写一个box的构造方法,形式参数为
printtable<t> printtable,即为接口的引用,但需注意的是,这里的目的不是传入接口对象(接口本身也不能实例化为对象),而是利用向上转型(父类持有子类对象)持有实现类的对象,利用向上转型的特性,实现多态
public class box<t>{ private t data; private printtable<t> printtable; //在类中将接口声明,可以看为,我们需要在这个类中使用该接口的实现 public box(printtable<t> printtable) { this.printtable = printtable; //这里传入实现了printtable接口类的对象,这里实际上是向上转型 //这里的目的实际上就是在使用print方法时通过接口选择那种print方法 } public void setdata(t data) { this.data = data; } public t getdata() { system.out.println("data类型是:" + this.data.getclass()); system.out.println(this.data); return data; } public void printdata() { printtable.print(this.data); //这里我们使用实现了接口的类的对象中的方法 } } - 为了使用接口,可以先创建一个接口的引用
- 在主类genericmain中进行测试
- 在box类中我们写了构造方法要求像传入一个接口实现类的对象,至于具体传入哪个则是根据box对象选择了泛型的哪一种来决定的
- 之后就可以调用box中的方法了
- 我们分别调用
boxinter.printdata(); boxstring.printdata();,printdata会根据父类接口持有的类对象,匹配实现接口的子类的对象中的方法
public class genericmain { public static void main(string[] args){ //创建容器容器中添加元素 box<integer> boxinter = new box<>(new integerprinttable()); boxinter.setdata(9); //创建容器容器中添加元素 box<string> boxstring = new box<>(new stringprinttable()); boxstring.setdata("hello world"); //测试用例: boxinter.printdata(); boxstring.printdata(); //输出案例: /* 我被用于指定输出interger类型的参数9 我被用于指定输出string类型的参数hello world */ } } - 泛型在接口中的应用的例子中,即体现了面向对象的多态特性,又体现了泛型能够进行类型校验的功能,在创建box对象的时候,使用的先指定类型,后创建与指定类型匹配的对象
- 在上面的例子中,我们可以试着创建不匹配指定泛型的接口实现类对象,可以发现因为类型不匹配ide给我们标红报错了

- 因为我们本应给
printtable<string> printtable赋值public class stringprinttable implements printtable<string>,即为父类接口未持有匹配的子实现类
- 在上面的例子中,我们可以试着创建不匹配指定泛型的接口实现类对象,可以发现因为类型不匹配ide给我们标红报错了
泛型在方法中的应用
- 创建一个方法,如下方代码所示
public static<t> void printlist(arraylist<t> list){
for(t data:list){
system.out.println(data);
}
}- 调用方法,如下方代码所示
- 在这里不需要给
public static<t> void printlist(arraylist<t> list)传单独的类型给泛型,因为在printlist方法的原型中只要求传入arraylist的对象,而对象中就已经指定了泛型的类型了
- 在这里不需要给
public static void main(string[] args){
//列表泛型方法测试用例是
arraylist<integer> list = new arraylist<>();
list.add(9);
list.add(8);
list.add(7);
printlist(list);
//这里string会被当作泛型t的值直接传入
}到此这篇关于java泛型及类型校验的文章就介绍到这了,更多相关java类型校验内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论