Java基础突击第七天0014(泛型)

整型坐标,小数坐标,字符串坐标。如果要同时接受三种类型需要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

输出:

30
30
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>赋值。则表示一个人的信息代表了所有人的信息。

很显然是不合理的,所以编译错误。



猜你喜欢

转载自blog.csdn.net/u012144068/article/details/80950283