先看一个例子:
class Message<T>
{
private T message;
public T getMessage()
{
return message;
}
public void setMessage(T message)
{
this.message=message;
}
}
public class Tong
{
public static void main(String[] args)
{
Message<String> m1=new Message<>();
m1.setMessage("pick");
func(m1);
Message<Integer> m2=new Message<>();
m2.setMessage(10);
//func(m2); //这里会出错,如果func形参指定类型,就要重载一个形参为Integer的func
}
public static void func(Message<String> m)
{
System.out.println(m.getMessage());
}
}
为什么会有通配符?
上述例子需要写很多重载方法,但是写重载方法的本质上是为了func可以接受不同的泛型,而通配符就可以接受任意类型。
通配符-----?
- ?通配符:表示参数可以接收任意类型 ,只能用于方法。
- ? 通配符只能取得类中属性值,不能修改属性值,因为类型不确定,无法设置确定类型。
用通配符对上述例子进行修改:
public static void func(Message<?> m)
{
//此时使用通配符"?"描述的是它可以接收任意类型,但是由于不确定类型,所以无法修改
//m.setMessage("world"); //错误,不能修改数据
System.out.println(m.getMessage());
}
通配符----? extends 类
- ? extends 类 是设置泛型上限,表示泛型类是类或者类的子类;
- ? extends 类 可以用于类和方法
- ? extends 类用于方法时,不能修改属性值,只能取得属性值,因为发生了父类(如Number)到子类的向下转型,需要强转,由于子类不确定,无法强转。
如:? extends Number 表示只能设置Number及其子类如Integer 、Double等。
T extends 类 : 用在类上
表示T只能是类或类的子类。
?extends 类: 用在方法上
表示只能接受类及其子类的泛型类。
通配符----? extends 类
class Mess<T extends Number> //T只能是Number及其子类
{
private T mess;
public void setMess(T mess)
{
this.mess=mess;
}
public T getMess()
{
return this.mess;
}
}
public class Tong
{
public static void main(String[] args)
{
//Mess<String> m1=new Mess<String>(); //错误,因为String不是Number的子类
Mess<Integer> m2=new Mess<>();
m2.setMess(10); //自动装箱
func(m2);
Mess<Double> m3=new Mess<>();
m3.setMess(19.3);
func(m3);
}
public static void func(Mess<? extends Number> m)
{
//此时?继承了Number类,但依旧不知道具体类型,即无法修改数据
//m.setMess(10);//错误
System.out.println(m.getMess());
}
}
通配符----- ? super 类
- ? super 类: 表示取得泛型下限,表示泛型类只能是类和类的父类;
- ?super 类 :只能用于方法;
- ? super 类用在方法中可以设置属性值,也可以取得属性值,因为子类到父类是自动的向上转型。
如:? super String :表示此方法只能取得String及其父类Object类。
class Met<T>
{
private T met;
public void setMet(T met)
{
this.met=met;
}
public T getMet()
{
return this.met;
}
}
public class Tong
{
public static void main(String[] args)
{
Met<String> m1=new Met<>();
m1.setMet("pick");
func(m1); //接收String类
}
public static void func(Met<? super String> m)
{
m.setMet("world"); //可以设置属性:子类到父类是自动转型
System.out.println(m.getMet());
}
}