整型坐标,小数坐标,字符串坐标。如果要同时接受三种类型需要Object类型,都会发生向上转型操作。
int -> (自动装箱)Integer -> 向上转型使用Object接收。
在泛型的指定中无法指定基本数据类型的,必须设置成一个类,在设置一个数字时就必须使用包装类。
如果set设置的类型和<T>中指定的类型不一致,则会在编译时出错。
在设置泛型为java.lang.Integer的时候,实际上setVar的方法就变成public void setVar(Integer var){}
其中能接收的只能是整型数字,如果是一个整型常量,则会用自动装箱的机制完成。
构造方法可以为类初始化,如果类中的属性通过泛型指定。可以通过构造方法设置属性内容,
泛型构造方法并不需要像声明类那样指定泛型。
而且一个类中有多个属性需要不同泛型来声明,则可以在声明类时指定多个泛型类型。
public class TestJava{
}
class Point<T>{
private T x;
private T y;
public Point(T x,T y){
this.x = x;
this.y = y;
}
public void setX(T x){
this.x = x;
}
public void setY(T y){
this.y = y;
}
public T getX(){
return this.x;
}
public T getY(){
return this.y;
}
}
class Name<T>{
private T name;
public Name(T name){
this.name = name;
}
public void setName(T name){
this.name = name;
}
public T getName(){
return this.name;
}
}
class UserPassword<U,P>{
private U user;
private P password;
public UserPassword(U user,P password){
this.user = user;
this.password = password;
}
public U getUser(){
return this.user;
}
public P getPassword(){
return this.password;
}
}
class Demo{
public static void main(String[] args){
Point<Integer> po = new Point<Integer>(50,40);
System.out.println("x in the Int Case:"+po.getX());
System.out.println("y in Int Case:"+po.getY());
Name<String> name = new Name<String>("FangXy");
System.out.println("The name is:"+name.getName());
UserPassword<String,String> up = new UserPassword<String,String>("FuXs","bdrw2013");
System.out.print("User:"+up.getUser());
System.out.println(" Password:"+up.getPassword());
}
}//Demo
输出:
x in the Int Case:50
y in Int Case:40
The name is:FangXy
User:FuXs Password:bdrw2013
在泛型应用中最好在声明类对象时,指定好其内部的数据类型如Info<String>
public class TestJava{
}
class Info<T>{
private T var;
public void setVar(T var){
this.var = var;
}
public T getVar(){
return this.var;
}
}
class Demo{
public static void main(String[] args){
Info<Object> i = new Info<Object>();
i.setVar("FangXy");
System.out.println("Content:"+i.getVar());
}
}//Demo
输出:Content:FangXy
如果Info<Object> i = new Info<Object>()更改为 Info i = new Info()就会弹出警告
注: TestJava.java使用了未经检查或不安全的操作。
注: 有关详细信息, 请使用 -Xlint:unchecked 重新编译。
在<>中加入Object实际上没有任何意义,因为不设置泛型它本身也是Object类型。不过加上Object之后,编译警告消失了。
以上程序在操作时都设置了一个固定的类型,在泛型操作中也可以通过通配符 接收 任意 指定泛型类型 的对象。
对象的引用传递是最常见的。如果在泛型类的操作中,进行引用传递时,泛型类型必须匹配才可以传递,否则是无法传递的。
public class TestJava{
}
class Info<T>{
private T var;
public void setVar(T var){
this.var = var;
}
public T getVar(){
return this.var;
}
}
class Demo{
public static void main(String[] args){
Info<String> info = new Info<String>();
info.setVar("FangXy");transmit(info);
}
public static void transmit(Info<Object> temp){
System.out.println("Content:"+temp);
}
}//Demo
Compile error: main里面Info<String>,transmit传递的方法是Info<Object>。因为String和Object不同,尽管String是Object的子类,但是在进行引用传递时也同样无法进行操作。
如果想让程序正确执行,可以将fun的参数从Info<String>修改为Info,即不指定泛型。
虽然不指定泛型不会出现编译错误。不过Info没指定泛型还是不妥。可以引入通配符?,表示可以接收此类型的任意泛型对象。
public class TestJava{
}
class Info<T>{
private T var;
public void setVar(T var){
this.var = var;
}
public T getVar(){
return this.var;
}
}
class Demo{
public static void main(String[] args){
Info<String> info = new Info<String>();
info.setVar("FangXy");
transmit(info);
}
public static void transmit(Info<?> temp){
System.out.println("Content:"+temp);
}
}//Demo
输出:Content:Info@15db9742
如果使用"?"接收泛型对象,则不能设置被泛型指定的内容
比如:Info<?> info = new Info<String>();//使用泛型接收对象
info.setVar("FangXy"); //compile error 无法设置。
将一个字符串设置给泛型所声明的属性,因为使用Info<?>,所以无法将内容设置给var属性,但此时可以设置null值。
info.setVar(null); //success null可以设置。
受限泛型,设定上下限
假设一个方法能够接收的对象只能是数字,上限就可以设定为Number
function(Info<? extends Number> temp)
public class TestJava{
}
class Info<T>{
private T var;
public void setVar(T var){
this.var = var;
}
public T getVar(){
return this.var;
}
public String toString(){
return this.var.toString();
}
}
class Demo{
public static void main(String[] args){
Info<Integer> info01 = new Info<Integer>();
Info<Float> info02 = new Info<Float>();
info01.setVar(30);
info02.setVar(30.1f);
transmit(info01);
System.out.println(info01.getVar());
transmit(info02);
System.out.println(info02.getVar());
}
public static void transmit(Info<? extends Number> temp){
System.out.println(temp+" ");
}
}//Demo
输出:
3030
30.1
30.1
info01 是Info<XX>泛型类型的实例化对象,print(info01)直接打印对象就是调用对象的toString方法。
等同于print(info01.toString())
Object类中的toString方法,直接输出对象的哈希值。可以覆写toString()方法,输出想要输出的东西。
上例中,transmit(info01)就是调用transmit(info01.toString()),
toString调用this.var.toString(),因为想要返回this.var,不过this.var不是数组类型,所以要用toString转换一下数组类型
当使用的泛型只能在本类及其父类类型上应用时,就必须使用泛型下限。
比如要求传递参数的类型范围为String - Object
public class TestJava{
}
class Info<T>{
private T var;
public void setVar(T var){
this.var = var;
}
public T getVar(){
return this.var;
}
public String toString(){
return this.var.toString();
}
}
class Demo{
public static void main(String[] args){
Info<Object> info01 = new Info<Object>();
Info<String> info02 = new Info<String>();
info01.setVar(new Object());
info02.setVar("FangXy");
transmitXiaxian(info01);
System.out.println(info01.getVar());
transmitXiaxian(info02);
System.out.println(info02.getVar());
}
//this function can only receive parameter from String to Object
public static void transmitXiaxian(Info<? super String> temp){
System.out.println(temp+" ");//means invoke temp.toString()
}
}//Demo
Output:
java.lang.Object@15db9742
java.lang.Object@15db9742
FangXy
FangXy
因为设置了范围下限。若有Info<Integer> info03 = new Info<Integer>(); info03.setVar(20);
transmitXiaxian(info03)则会报错。因为transmitXiaxian的下限是String类型。即只能接收Object和String类型的方法。
泛型与子类继承的限制:一个类的子类可以通过对象多态性为父类初始化,不过在泛型操作中,
子类的泛型是无法使用父类泛型接收(Info<String> 不能赋值给Info<Object>->编译错误)
Info<?> = Info<String> 是可以的。
为什么不能用向上转型?
如果将子类泛型赋值给父类泛型,则扩大了子类泛型的内容。
Info<All>如果被Info<Person>赋值。则表示一个人的信息代表了所有人的信息。
很显然是不合理的,所以编译错误。