Java中的泛型

今天来学习一下泛型,为了后面找工作做准备:
泛型的出现真的是非常方便,它增加了通用性,自然也省去了很多重复工作。我主要是用到泛型类,在MVC设计模式下,使用框架开发web工程,经常要和数据库交互,而且是对多张表或几张表在联合操作,同时也想操作的时候框架自动或者稍微手动一下使操作的都是bean对象。而对于数据库常用操作增删改查,这四种操作都是相同的,所以希望能把这四种操作抽象出来,操作各种表(对象),而如果不用泛型,则操作不同表则需要传入和返回不同对像,那么就需要对每种对象操作都要重复上述四种操作。但是有了泛型就不一样了,它可以指任何一种具体的java类型。
**

Java泛型中的标记符:

**
T –Type(Java 类型)ps:这里的T是指具体的某一种类型,其实在编译结束后,类型就会被擦除,变为真正的Java类型。
K –Key(键)一般用于Java中的Map等集合中。
V–Value(值)一般用于Java中的Map等集合中。
?–不确定的Java类型,一般用在通配符或者class类型不确定。

Java泛型应用主要有:泛型类、泛型方法、泛型接口、边界符、通配符

泛型类其实即使我上面提到增删改查用到的

public class BaseDao<T>{
 public void save(T o){...}
 public void delete(T o){...}
 public List<T> findStudents(String hql,Object param[]){...}
 //注意这些方法并不是泛型方法
 ......
}

这个定义就可以操作很多对象表。

泛型方法
泛型方法定义也很简单,需要在方法返回类型前加上泛型标识,

public class Utils{
 public <T> void compare(List<T> list){...}
 //在返回值前加<T> 、<K,v>等才是泛型方法,当然如果类为泛型类Utils<T>,方法返回类型前<T>也包含类型T
}

注意:如果泛型类中有静态方法,则静态方法不能引用类中的泛型,需要引用则需要把静态方法定义为泛型方法。

泛型接口

public interface BaseDaoInterface<T>{
 public void save(T o);
 public void delete(T o);
 .....................
}

接口使用

public class BaseDao<T> implements BaseDaoInterface<T>{
 public void save(T o){...}
 public void delete(T o){...}
 //public List<T> findStudents(String hql,Object param[]){...}
 ......
}

边界符

public void getValue(ShuZhi<? extends Number> value){....}
public void fn(Fruit<? super Apple>){...}
//ShuZhi、Fruit为泛型类,这里使用?与T区别不是很明显,但是可以理解为编译后,?可以是符合多种要求的数据类型,而?只能是确切的某一种。

通配符

public void boxTest(Box<Number> n) {...}

上面这个方法是不允许传入参数Box,虽然Integer属于Number子类,但Box与Box并没有这中关系,

class Parent{}
class Son1 extends Parent{}
class Son2 extends Parent{}

这个需要我们使用通配符来解决这个问题

public class Family<T>{
T fn1(List<? extends T> list){}
String fn2(){
Family<Parent> p=new Family<Parent>();
Parent p1=p.fn1(parent);
Parent p2=p.fn1(son1);
}
public static void main(String[] args) {
    f2();
}
}

PECS原则
Producer Extends, Consumer Super
具体理解可以往下看:

import java.util.Arrays;
import java.util.List;

public class GenericReading {
static List<Apple> apples=Arrays.asList(new Apple()); 
static List<Fruit> fruit= Arrays.asList(new Fruit());
static class Reader<T>{
    T readExact(List<T> list){
        return list.get(0);
    }
}
static void f1(){
    Reader<Fruit> fruitReader =new Reader<Fruit>();
    //Fruit f = fruitReader.readExact(apples);//出错
}

static class CovariantReader<T>{
    T readCovariant(List<? extends T> list) {
        return list.get(0);
    }
}
static void f2(){
        CovariantReader<Fruit> cList=new CovariantReader<Fruit>();
        Fruit f=cList.readCovariant(apples);
}
public static void main(String[] args) {
    f2();
}
}

在方法f1()中,我们发现在fruitReader.readExact(List list)中不能传入参数List apples,虽然Apple是Fruit子类,但编辑器认为List apples与List list是没有关系的。所以在f2中,使用通配符readCovariant(List


import java.util.ArrayList;
import java.util.List;

public class GenericWriting {
    static List<Apple> apples = new ArrayList<Apple>();
    static List<Fruit> fruit = new ArrayList<Fruit>();
    static <T> void writeExact(List<T> list, T item) {
        list.add(item);
    }
    static void f1() {
        writeExact(apples, new Apple());
        writeExact(fruit, new Apple());
    }
    static <T> void writeWithWildcard(List<? super T> list, T item) {
        list.add(item);
    }
    static void f2() {
        writeWithWildcard(apples, new Apple());
        writeWithWildcard(fruit, new Apple());
    }
    public static void main(String[] args) {
        f1(); f2();
    }
}

我们可以从思想或方法参数上理解:
writeWithWildcard(List

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值