标题:通配符
package conll;
class Message<T>{
private T msg;
public T getMsg() {
return msg;
}
public void setMsg(T msg) {
this.msg = msg;
}
}
public class TestDemo {
public static void main(String[] args) {
Message<String> m = new Message<String>();
m.setMsg("Hello World!");
fun(m); //引用传递
}
public static void fun(Message<String> temp){
System.out.println(temp.getMsg());
}
}
以上的代码为Message设置的是一个String类型的泛型对象。
但是当设置的其他类型的类型呢?
代码:
public class TestDemo {
public static void main(String[] args) {
Message<Integer> m = new Message<Integer>();
m.setMsg(100);
fun(m); //引用传递
}
public static void fun(Message<String> temp){
System.out.println(temp.getMsg());
}
}
代码1
public static void fun(Message<String> temp){
System.out.println(temp.getMsg());
}
代码2
public static void main(String[] args) {
Message<Integer> m = new Message<Integer>();
m.setMsg(100);
fun(m); //引用传递
}
代码1和代码2在标注颜色的地方不统一。
fun()方法里面接受的“Message<String>”那么就不能够使用了,并且fun()方法不能够针对于不同的泛类进行重载,因为方法地方重载认的只是参数的类型与泛型无关。
解决方法一:不设置参数方法的泛型
package conll;
class Message<T>{
private T msg;
public T getMsg() {
return msg;
}
public void setMsg(T msg) {
this.msg = msg;
}
}
public class TestDemo {
public static void main(String[] args) {
Message<Integer> m1 = new Message<Integer>();
Message<String> m2 = new Message<String>();
m1.setMsg(100);
m2.setMsg("Hello World");
fun(m1); //引用传递
fun(m2);
}
public static void fun(Message temp){
System.out.println(temp.getMsg());
}
}
问题:
public static void fun(Message temp){
System.out.println(temp.getMsg());
}
Message会出现警告信息,因为不设置泛型就会出现警告信息。这里再fun里面设置了String类型的数据,但是泛型本身设置的Integer方法。
package conll;
class Message<T>{
private T msg;
public T getMsg() {
return msg;
}
public void setMsg(T msg) {
this.msg = msg;
}
}
public class TestDemo {
public static void main(String[] args) {
Message<Integer> m1 = new Message<Integer>();
m1.setMsg(100);
fun(m1); //引用传递
}
public static void fun(Message temp){
temp.setMsg("Hello");
System.out.println(temp.getMsg());
}
}
所以现在需要解决的是,需要又一种方式可以接受一个类的任意的泛型类型,但是不能够修改只能取出,那么就可以使用?来描述。
package conll;
class Message<T>{
private T msg;
public T getMsg() {
return msg;
}
public void setMsg(T msg) {
this.msg = msg;
}
}
public class TestDemo {
public static void main(String[] args) {
Message<Integer> m1 = new Message<Integer>();
m1.setMsg(100);
fun(m1); //引用传递
}
public static void fun(Message<?> temp){ //不能够设置但是能够取出。
System.out.println(temp.getMsg());
}
}
在“?”通配符里面基础上还会有两个子通配符。
1.? extends类:设置泛型上限,可以在声明上和方法的参数上使用;
-?extends Number:意味着可以设置Number或则是Number的子类(Integer、Double....)
2.?super类:设置泛型下限,方法参数上使用;
-? super String :意味着只能够设置String或则它的父类Object
范例:
package conll;
class Message<T extends Number>{
private T msg;
public T getMsg() {
return msg;
}
public void setMsg(T msg) {
this.msg = msg;
}
}
public class TestDemo {
public static void main(String[] args) {
Message<Integer> m1 = new Message<Integer>();
m1.setMsg(100);
fun(m1); //引用传递
}
public static void fun(Message<? extends Number> temp){ //不能够设置但是能够取出。
System.out.println(temp.getMsg());
}
}
如果设置了非Number或则子类的化,那么将出现语法错误。
范例:设置下限
package conll;
class Message<T >{
private T msg;
public T getMsg() {
return msg;
}
public void setMsg(T msg) {
this.msg = msg;
}
}
public class TestDemo {
public static void main(String[] args) {
Message<String> m1 = new Message<String>();
m1.setMsg("hello world");
fun(m1); //引用传递
}
public static void fun(Message<? super String> temp){ //不能够设置但是能够取出。
System.out.println(temp.getMsg());
}
}
看懂就好。
标题:泛型接口
泛型不仅可以定义在一个类里面,那么泛型也可以在接口上声明,称为泛型接口。
范例:定义泛型接口
//如果是接口在前面加上字母I,例如:IMessage
//如果是抽象类就在前面加上Abstract,例如:AbstractMessage
//如果是普通类直接缩写,例如:Message
interface IMessage<T>{ //设置泛型接口
public void print(T t);
}
在接口上必须要定义相应的子类,所以来讲如果要定义子类有两种形式。
形式一:在子类继续设置泛型
package conll;
//如果是接口在前面加上字母I,例如:IMessage
//如果是抽象类就在前面加上Abstract,例如:AbstractMessage
//如果是普通类直接缩写,例如:Message
interface IMessage<T>{ //设置泛型接口
public void print(T t);
}
//子类也继续使用泛类,并且父接口使用和子类同样的泛型标记
class MessageImpl<T> implements IMessage<T>{
public void print(T t){
System.out.println(t);
}
}
public class TestDemo {
public static void main(String[] args) {
IMessage<String> msg = new MessageImpl();
msg.print("hello world!");
}
}
形式二:在子类不设置泛型,而为父接口明确的定义一个泛型类型
package conll;
//如果是接口在前面加上字母I,例如:IMessage
//如果是抽象类就在前面加上Abstract,例如:AbstractMessage
//如果是普通类直接缩写,例如:Message
interface IMessage<T>{ //设置泛型接口
public void print(T t);
}
//子类也继续使用泛类,并且父接口使用和子类同样的泛型标记
class MessageImpl implements IMessage<String>{
public void print(String t){
System.out.println(t);
}
}
public class TestDemo {
public static void main(String[] args) {
IMessage<String> msg = new MessageImpl();
msg.print("hello world!");
}
}
标记:泛型方法
泛型方法不一定非要定义在支持泛型的类里面。在之前所编写的所有存在有泛型的方法都是在泛型支持类里面定义。
范例:泛型方法
package conll;
public class TestDemo {
public static void main(String[] args) {
String str = fun("hello");
System.out.println(str.length());
}
public static <T> T fun(T t){
return t;
}
}
能看懂泛型方法的标记就可以了。
总结:1.泛型解决的是向下转型所带来的安全隐患,其核心的组成就是在声明类或接口的时候不设置参数或属性的类型。
2.“?”可以接收任意的泛型类型,只能够取出,但是不能修改。