泛型,可以理解为就是标签
集合容器类在设计声明阶段,不能明确其具体存储的类型,
JDK5之前元素类型只能设置成Object
JDK5之后引入泛型,此时在容器上使用
如Collection
这样等真正使用时再给E赋值(传入参数)
不用泛型
ArrayList list = new ArrayList(); list.add(1); list.add(3); list.add(5); list.add("sdf");//全完正确,编译不会出问题,但是类型不安全,如果list用来存放成绩数据,则运行时可能异常 for(Object score:list){ int stuScore = (Integer)score;//必须强转,因为score是Object类型的 }
使用泛型
泛型是个类型,不能是基本数据类型
ArrayList<Integer> list = new ArrayList<Integer>();//不能是int list.add(1); list.add("dsf");//报错了,编译时进行类型检查,保证了数据安全 //方式一 for(Integer score:list){ int stuScore=score;//这里就不用强转了 } //方式二 Iterator<Integer> iter = list.iterator(); while(iter.hasNext()){ sout(iter.next()); }
HashMap
Map<String,Integer> amp = new HashMap<>();//JDK7之后new后面的<>就可以省略了:类型推断 map.put("sd",1); map.put("sdf",2); Set<Map.Entry<String,Integer>> entry = map.entrySet(); for(Entry en: entry){ en.getkey(); en.getValue();W } //or Iterator<Map.Entry<String,Integer>> iter =entry.iterator(); while(iter.hasNext()){ Map.Entry<String,Integer> e = iter.next(); e.getKey; e.getValue; }
通常泛型字母的设置
K V 键值 T 类 E 方法
public class Order<T>{ String orderName; int orderId; T orderT; public Order(){} public Order(... , T orderT){ this. .... this.orderT=orderT; } public T getOrderT(){ return orderT; } } //实例化的时候如果没有指明泛型得类型,则默认为Object类型 Order o = new Order<String>();//刚开始写不习惯,前面的<>特别容易忘记 Order<String> o =new Order<>();
继承:
//继承时指明泛型 public class SubOrder extends Order<String>{ .... } SubOrder sub = new SubOrder("aa",1,"OrderT"); //继承时没有指明 public class SubOrder<E,T> extends Order<T>{ E subOrderE; ... } SubOrder<int,String> subOrder = new SubOrder<>();
class Fu<T1,T2>{ } class Z1 extends Fu{} // 相当于class Z1 extends Fu<Object,Object> class Z2 extends Fu<String,Integer>{ } //指明了具体类型 class Z3<T1,T2> extends Fu<T1,T2>{ }//全部保留 class Z4<T2> extends Fu<Integer,T2>{ }//部分保留
一个类,实例化成了两种不同泛型的对象,彼此就没啥关系啦,不能相互赋值 (编译就过不了)
异常类不可以有泛型
静态成员方法的里不可以有泛型。简单的说就是从第一个p开始到最后一个}结束,就别有泛型的字母
普通成员方法的trycatch里面,也不行。
T[] arr =new T[10 ]; 不行!
T[] arr = (T[ ]) new Object[10];
啥事泛型方法嘞?
不是说泛型里使用了类的泛型就叫泛型方法,
//这不是泛型方法 int add(E e); public List<E> copyXxxx(E[] arr){//编译器会把E[]认为是个某个声明的类型的数组 //这才是 <T> T[ ] toArray(T[ ] a); public <E> List<E> copyXxxx(E[] arr){ } //方法使用 List<Integer> list = Order.copyXxxx(new Integer(){1,2,3});//传入的参数决定了E的类型
泛型方法可以使静态的!!!!
因为泛型参数是在调用时确定的,而不需要类的初始化
但是要区分泛型方法的泛型 和 方法里类的泛型
data(base) access object
问题,表很多,各种类型的,每个类型每个数据都写增删改查太麻烦了。所以用泛型
做法:让数据库中的每个表对应java中的一个类,操作每个表对应操作类的对象,到底对应的那个类呢?? 对应T
public class DAO<T>{ //增 public void add(T t){ ... } //删 public boolean remove(int index){...} //改 public void update(int index,T t){...} //查 public T getIndex(int index){return null} pubcli List<T> getFullIndex(int begin,int end){return null} //泛型方法 public <E> E getValue(){ //举例:获取表中一共有多少条记录:E赋值为整型Long //又举例:获取全部员工工资,E赋值为浮点型 return null; } } //顾客表 public class Customer{ String name; ... } public class customerDAO extens DAO<Customer >{ //空的,啥也不写 } //学生表 public class Student{ ... } public class StudentDAO extends DAO<Student>{//每个XxxxDAO只能操作对应的表 } //测试 public class DAOTest{ @Test public void test1(){ CustomerDAO dao1 =new CustomerDAO(); dao.add(new Customer()); List<Customer> list = dao.getFullIndex(10,13); } @Test public void test2(){ StudentDAO dao =new STudentDAO(); dao.add(...); } }
List<Object> list=null; List<String> list3=null; list=list3;//报错的,泛型不能多态 //G<Fu>和G<Zi>完全是俩不挨边的类型,没有父子关系 ,但是他俩有个公共的爹,G<?>详见下面
如果想写一个通用的List遍历函数,Int型的,String型的,Person型的
但是<>没有多态了,
通配符:?
List<Object> list1 = null; List<String> list3 = null; LIst<?> list= null; list = list1;//可以了 list = list3;//可以了 public void show(List<?> list){ Iterator<?> iter = list.iterator(); while(iter.hasNext()){ Object o = iter.next(); sout(obj) } }
使用通配符之后就不能像普通的那种添加add了
除了添加null之外
10.4.2 有限制的通配符
//只允许Person及其父类使用 super限制下的泛型,可以add操作