这一篇将系统的回忆起泛型的知识
在做Android的时候用到泛型的类有很多,很多时候会遇到将数据保存到一个List集合,Map等等,他们之间使用<>来填写数据类型,说一个我现在想到的就是Android中异步加载这个类AsyncTask《Params, Progress, Result》,第一个参数是在execute()中写入的参数,然后在doInBackgound中中传入了这个参数,最后返回了Result这个类型值。说了有点多,下面就说一下泛型的知识。
首先来一段简单的泛型代码
格式 :
- <数据类型>
- 此处的数据类型只能是引用类型。
ArrayList<String> array = new ArrayList();
array.add("fat");
array.add("one");
Iterator<String> it = array.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
把泛型定义在类上
格式:public class 类名<泛型类型1,…>
注意:泛型类型必须是引用类型—引用类型就是一个对象类型
泛型类
就是把泛型定义在类上,类中的参数是泛型
public class Test {
//泛型类 --类中使用的参数是泛型
public static class Fat<T>{
private T obj;
public T getObj(){
return obj;
}
public void setObj(T obj){
this.obj = obj;
}
}
public static void main(String[] args) {
Fat<String> fat = new Fat<String>();
fat.setObj("一个胖儿");
System.out.println( fat.getObj());
Fat<Integer> age = new Fat();
age.setObj(22);
System.out.println(age.getObj());
}
}
泛型方法
就是将泛型定义在方法上,此方法就可以传任意类型的参数,定义泛型方法的格式是
public <T> 方法名 (T t){}
//注意 泛型方法所在的类是个泛型类,因为前面生命的<T>就是泛型类中的泛型
看代码
public class Test {
public static class Fat<T>{
private T obj;
public T getObj(){
return obj;
}
public void setObj(T obj){
this.obj = obj;
}
public <T> void show(T obj){
System.out.println(obj);
}
}
public static void main(String[] args) {
Fat<String> fat = new Fat<String>();
fat.setObj("一个胖儿");
// System.out.println( fat.getObj());
fat.show(fat.getObj());
Fat<Integer> age = new Fat();
age.setObj(22);
// System.out.println(age.getObj());
fat.show(age.getObj());
}
}
泛型接口
格式:public interface 接口名<泛型>
看代码
//定一个父接口
public interface Finterface <T>{
public void show(T t);
}
//然后定义一个子类来实现这个父类接口
public class Zinterfaceimpl<T> implements Finterface<T>{
@Override
public void show(T t) {
System.out.println(t);
}
//测试
public class Test {
public static void main(String[] args) {
Finterface<Integer> one = new Zinterfaceimpl();
one.show(123);
}
}
//当然实现接口的时候可以确定类型
public class Zinterfaceimpl implements Finterface<String>{
@Override
public void show(String t) {
System.out.println(t);
}
通配符–?
- 类< ?>
表示任意类型,如果没有明确,就是Object以及任意的java类 - ? extends E
向下限定,E及其子类,就是所有继承了E的类才可以传入 - ? super E
向上限定,E及其父类,就是所有E的类或者E的父类。
看代码好理解一点:
//首先定义了一个A类
public class A<T> {
private T t;
A(){}
A(T t){
this.t = t;
}
public void show(){
System.out.println(t);
}
}
//定一个Fat类
public class Fat {
public void show(){
System.out.println("一个胖儿");
}
}
//测试
public class D {
public static void main(String[] args) {
A<Object> a = new A<Object>();
// A<Object> b = new A<Fat>();报错 ,必须前后一致
//为了解决这个问题使用通配符 ?
A<?> b = new A<Fat>();
//? extends E
A<? extends Fat> c = new A<>();//这个的意思就是限定了传入继承Fat或者Fat类的类类型
c.show(); //这里会输出一个null 注意这里调用的是A中的show方法
//如果我非要调用Fat中的show方法呢?这就要改一下A中的show代码
}
}
//修改后的A类show方法 还是得定义一个类的引用,其实这样我感觉根本就没体现向下限定
public void show(){
Fat f = (Fat) t;
f.show();
}
关于向上限定和向下限定有什么用呢?在Android中目前我还没用过,不过可以限定你传入对象的类型,必须是你想要对象的子类,或者必须是实现了这个接口的类。比如说
//将Fat定义成接口
public interface Fat {
public void show();
}
//B类
public class B implements Fat{
@Override
public void show() {
}
}
//测试
public class D {
public static void main(String[] args) {
B ccc =new B();
A<? extends Fat> d = new A<B>(ccc);
d.show();
//结果为 one fat
}
}
//注意A类,没有任何改动,使用Fat接口引用
ublic class A<T> {
private T t;
A(){}
A(T t){
this.t = t;
}
public void show(){
Fat f = (Fat) t;
f.show();
}
}
接口作为引用类型来使用,任何实现该接口的类的实例都可以存储在该接口类型的变量中,通过这些变量可以访问类中所实现的接口中的方法,Java 运行时系统会动态地确定应该使用哪个类中的方法,实际上是调用相应的实现类的方法。
================================================================================