java泛型参数传递_详细讲解Java的泛型
我们知道,使⽤变量之前要定义,定义⼀个变量时必须要指明它的数据类型,什么样的数据类型赋给什么样的值。
假如我们现在要定义⼀个类来表⽰坐标,要求坐标的数据类型可以是整数、⼩数和字符串,例如:
x = 10、y = 10
x = 12.88、y = 129.65
x = "东京180度"、y = "北纬210度"
针对不同的数据类型,除了借助⽅法重载,还可以借助⾃动装箱和向上转型。我们知道,基本数据类型可以⾃动装箱,被转换成对应的包装类;Object 是所有类的祖先类,任何⼀个类的实例都可以向上转型为 Object 类型,例如:
int --> Integer --> Object
double -->Double --> Object
String --> Object
这样,只需要定义⼀个⽅法,就可以接收所有类型的数据。请看下⾯的代码:
public class Demo {
public static void main(String[] args){
Point p = new Point();
p.tX(10); // int -> Integer -> Object
p.tY(20);
int x = (X(); // 必须向下转型
int y = (Y();
System.out.println("This point is:" + x + ", " + y);
牛蒡泡水喝的功效p.tX(25.4); // double -> Integer -> Object
p.tY("东京180度");
double m = (X(); // 必须向下转型党员转正介绍人发言
double n = (Y(); // 运⾏期间抛出异常
System.out.println("This point is:" + m + ", " + n);
}
}
class Point{
Object x = 0;
Object y = 0;
public Object getX() {
return x;
}
public void tX(Object x) {
this.x = x;
}
public Object getY() {
return y;
}
public void tY(Object y) {
this.y = y;
}
}
下运河风情上⾯的代码中,⽣成坐标时不会有任何问题,但是取出坐标时,要向下转型,在 Java多态对象的类型转换 ⼀⽂中我们讲到,向下转型存在着风险,⽽且编译期间不容易发现,只有在运⾏期间才会抛出异常,所以要尽量避免使⽤向下转型。运⾏上⾯的代码,第12⾏会抛出java.lang.ClassCastException 异常。
那么,有没有更好的办法,既可以不使⽤重载(有重复代码),⼜能把风险降到最低呢?
有,可以使⽤泛型类(Java Class),它可以接受任意类型的数据。所谓“泛型”,就是“宽泛的数据类型”,任意的数据类型。
更改上⾯的代码,使⽤泛型类:
public class Demo {
public static void main(String[] args){
// 实例化泛型类
Point p1 = new Point();
p1.tX(10);
p1.tY(20);
int x = p1.getX();
int y = p1.getY();
System.out.println("This point is:" + x + ", " + y);
Point p2 = new Point();
p2.tX(25.4);
p2.tY("东京180度");
double m = p2.getX();
String n = p2.getY();
System.out.println("This point is:" + m + ", " + n);
}
}
// 定义泛型类
class Point{
T1 x;
T2 y;
public T1 getX() {
return x;
}
public void tX(T1 x) {
this.x = x;
}
public T2 getY() {
return y;
}
public void tY(T2 y) {
this.y = y;
}
}
运⾏结果:
This point is:10, 20
This point is:25.4, 东京180度
与普通类的定义相⽐,上⾯的代码在类名后⾯多出了 ,T1, T2 是⾃定义的标识符,也是参数,⽤来传
递数据的类型,⽽不是数据的值,我们称之为类型参数。在泛型中,不但数据的值可以通过参数传递,数据的类型也可以通过参数传递。T1, T2 只是数据类型的占位符,运⾏时会被替换为真正的数据类型。
传值参数(我们通常所说的参数)由⼩括号包围,如 (int x, double y),类型参数(泛型参数)由尖括号包围,多个参数由逗号分隔,如 或 。
类型参数需要在类名后⾯给出。⼀旦给出了类型参数,就可以在类中使⽤了。类型参数必须是⼀个合法的标识符,习惯上使⽤单个⼤写字母,通常情况下,K 表⽰键,V 表⽰值,E 表⽰异常或错误,T 表⽰⼀般意义上的数据类型。
泛型类在实例化时必须指出具体的类型,也就是向类型参数传值,格式为:
className variable = new className();
也可以省略等号右边的数据类型,但是会产⽣警告,即:
className variable = new className();
因为在使⽤泛型类时指明了数据类型,赋给其他类型的值会抛出异常,既不需要向下转型,也没有潜在的风险,⽐本⽂⼀开始介绍的⾃动装箱和向上转型要更加实⽤。
注意:
泛型是 Java 1.5 的新增特性,它以C++模板为参照,本质是参数化类型(Parameterized Type)的应⽤。
类型参数只能⽤来表⽰引⽤类型,不能⽤来表⽰基本类型,如 int、double、char 等。但是传递基本类型不会报错,因为它们会⾃动装箱成对应的包装类。
泛型⽅法
除了定义泛型类,还可以定义泛型⽅法,例如,定义⼀个打印坐标的泛型⽅法:
public class Demo {
public static void main(String[] args){
// 实例化泛型类
Point p1 = new Point();
p1.tX(10);
p1.tY(20);
p1.X(), p1.getY());
Point p2 = new Point();
p2.tX(25.4);
p2.tY("东京180度");
p2.X(), p2.getY());
}
}
上海公积金热线
// 定义泛型类
class Point{
T1 x;
快点的英语怎么读
T2 y;
描写害怕的句子public T1 getX() {
return x;
}
public void tX(T1 x) {
this.x = x;
}
public T2 getY() {
return y;
}
public void tY(T2 y) {
元宵节的习俗作文
this.y = y;
}
// 定义泛型⽅法
public void printPoint(T1 x, T2 y){
T1 m = x;
四种基本反应类型T2 n = y;
System.out.println("This point is:" + m + ", " + n); }
}
运⾏结果:
This point is:10, 20
This point is:25.4, 东京180度
上⾯的代码中定义了⼀个泛型⽅法 printPoint(),既有普通参数,也有类型参数,类型参数需要放在修饰符后⾯、返回值类型前⾯。⼀旦定义了类型参数,就可以在参数列表、⽅法体和返回值类型中使⽤了。
与使⽤泛型类不同,使⽤泛型⽅法时不必指明参数类型,编译器会根据传递的参数⾃动查找出具体的类型。泛型⽅法除了定义不同,调⽤就像普通⽅法⼀样。
注意:泛型⽅法与泛型类没有必然的联系,泛型⽅法有⾃⼰的类型参数,在普通类中也可以定义泛型⽅法。泛型⽅法 printPoint() 中的类型参数 T1, T2 与泛型类 Point 中的 T1, T2 没有必然的联系,也可以使⽤其他的标识符代替:
public static void printPoint(V1 x, V2 y){
V1 m = x;
V2 n = y;
System.out.println("This point is:" + m + ", " + n);
}
泛型接⼝
在Java中也可以定义泛型接⼝,这⾥不再赘述,仅仅给出⽰例代码:
public class Demo {
public static void main(String arsg[]) {
Info obj = new InfoImp("www.weixueyuan");
System.out.println("Length Of String: " + Var().length());
}
}
//定义泛型接⼝
interface Info {
public T getVar();
}
//实现接⼝
class InfoImp implements Info {
private T var;
// 定义泛型构造⽅法
public InfoImp(T var) {
this.tVar(var);
}
public void tVar(T var) {