1、为何要有泛型(Generic)?
1. 解决元素存储的安全性问题
2. 解决获取数据元素时,须要类型强转的问题java
泛型,JDK1.5新加入的,解决数据类型的安全性问题,其主要原理是在类声明时经过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这样在类声明或实例化时只要指定好须要的具体的类型便可。Java泛型能够保证若是程序在编译时没有发出警告,运行时就不会产生ClassCastException异常。同时,代码更加简洁、健壮。git
2、使用泛型
github
3、在集合中使用泛型
1.对象实例化时不指定泛型,默认为:Object。
2.泛型不一样的引用不能相互赋值。
3.加入集合中的对象类型必须与指定的泛型类型一致。
安全
4.静态方法中不能使用类的泛型。ide
5.若是泛型类是一个接口或抽象类,则不可建立泛型类的对象。this
6.不能在catch中使用泛型编码
7.从泛型类派生子类,泛型类型需具体化设计
备注:把一个集合中的内容限制为一个特定的数据类型,这就是generics背后的核心思想。code
泛型方法对象
方法,也能够被泛型化,无论此时定义在其中的类是否是泛型化的。在泛型方法中能够定义泛型参数,此时,参数的类型就是传入数据的类型。
泛型方法的格式:
[访问权限] <泛型> 返回类型 方法名([泛型标识 参数名称]) 抛出的异常
public class DAO { public <E> E get(int id, E e){ E result = null; return result; } }
static <T> void fromArrayToCollection(T[] a, Collection<T> c) { for (T o : a) { c.add(o); } } public static void main(String[] args) { Object[] ao = new Object[100]; Collection<Object> co = new ArrayList<Object>(); fromArrayToCollection(ao, co); String[] sa = new String[20]; Collection<String> cs = new ArrayList<>(); fromArrayToCollection(sa, cs); Collection<Double> cd = new ArrayList<>(); // 下面代码中T是Double类,但sa是String类型,编译错误。 // fromArrayToCollection(sa, cd); // 下面代码中T是Object类型,sa是String类型,能够赋值成功。 fromArrayToCollection(sa, co); }
4、泛型和继承的关系
若是B是A的一个子类型(子类或者子接口),而G是具备泛型声明的类或接口,G<B>并非G<A>的子类型!好比:String是Object的子类,可是List<String >并非List<Object>的子类。
public void testGenericAndSubClass() { Person[] persons = null; Man[] mans = null; // 而 Person[] 是 Man[] 的父类. persons = mans; Person p = mans[0]; // 在泛型的集合上 List<Person> personList = null; List<Man> manList = null; // personList = manList;(报错) }
5、通配符
1.使用类型通配符:?
好比:List<?> ,Map<?,?>
List<?>是List<String>、List<Object>等各类泛型List的父类。
2.读取List<?>的对象list中的元素时,永远是安全的,由于无论list的真实类型是什么,它包含的都是Object。
3.写入list中的元素时,不行。由于咱们不知道c的元素类型,咱们不能向其中添加对象。
惟一的例外是null,它是全部类型的成员。
将任意元素加入到其中不是类型安全的:
Collection<?> c = new ArrayList<String>();
c.add(new Object()); // 编译时错误
由于咱们不知道c的元素类型,咱们不能向其中添加对象。
add方法有类型参数E做为集合的元素类型。咱们传给add的任何参数都必须是一个未知类型的子类。 由于咱们不知道那是什么类型,因此咱们没法传任何东西进去。惟一的例外的是null,它是全部类型的成员。另外一方面,咱们能够调用get()方法并使用其返回值。返回值是一个未知的类型,可是咱们知道,它老是一个Object。
public static void main(String[] args) { List<?> list = null; list = new ArrayList<String>(); list = new ArrayList<Double>(); //list.add(3); list.add(null); List<String> l1 = new ArrayList<String>(); List<Integer> l2 = new ArrayList<Integer>(); l1.add(“Python"); l2.add(15); read(l1); read(l2); } static void read(List<?> list){ for(Object o : list){ System.out.println(o); } }
4.有限制的通配符
<?>
容许全部泛型的引用调用
举例:
<? extends Number> (无穷小 , Number]
只容许泛型为Number及Number子类的引用调用
<? super Number> [Number , 无穷大)
只容许泛型为Number及Number父类的引用调用
<? extends Comparable>
只容许泛型为实现Comparable接口的实现类的引用调用
public static void printCollection3(Collection<? extends Person> coll){ Iterator<?> iterator = coll.iterator(); while(iterator.hasNext()){ System.out.println(iterator.next()); } } public static void printCollection4(Collection<? super Person> coll){ Iterator<?> iterator = coll.iterator(); while(iterator.hasNext()){ System.out.println(iterator.next()); } }
范例:泛型应用
用户在设计类的时候每每会使用类的关联关系,例如,一我的中能够定义一个信息的属性,可是一我的可能有各类各样的信息(如联系方式、基本信息等),因此此信息属性的类型就能够经过泛型进行声明,而后只要设计相应的信息类便可。
public interface Info{ // 只有此接口的子类才是表示人的信息 } public class Contact implements Info{ // 表示联系方式 private String address ; // 联系地址 private String telephone ; // 联系方式 private String zipcode ; // 邮政编码 public Contact(String address,String telephone,String zipcode){ this.address = address; this.telephone = telephone; this.zipcode = zipcode; } public void setAddress(String address){ this.address = address ; } public void setTelephone(String telephone){ this.telephone = telephone ; } public void setZipcode(String zipcode){ this.zipcode = zipcode; } public String getAddress(){ return this.address ; } public String getTelephone(){ return this.telephone ; } public String getZipcode(){ return this.zipcode; } @Override public String toString() { return "Contact [address=" + address + ", telephone=" + telephone + ", zipcode=" + zipcode + "]"; } } public class Introduction implements Info{ private String name ; // 姓名 private String sex ; // 性别 private int age ; // 年龄 public Introduction(String name,String sex,int age){ this.name = name; this.sex = sex; this.age = age; } public void setName(String name){ this.name = name ; } public void setSex(String sex){ this.sex = sex ; } public void setAge(int age){ this.age = age ; } public String getName(){ return this.name ; } public String getSex(){ return this.sex ; } public int getAge(){ return this.age ; } @Override public String toString() { return "Introduction [name=" + name + ", sex=" + sex + ", age=" + age + "]"; } } public class Person<T extends Info>{ private T info ; public Person(T info){ // 经过构造方法设置信息属性内容 this.info = info; } public void setInfo(T info){ this.info = info ; } public T getInfo(){ return info ; } @Override public String toString() { return "Person [info=" + info + "]"; } // public String toString(){ // 覆写Object类中的toString()方法 // return this.info.toString() ; // } } public class GenericPerson{ public static void main(String args[]){ Person<Contact> per = null ; // 声明Person对象 per = new Person<Contact>(new Contact("北京市","01088888888","666666")) ; System.out.println(per); Person<Introduction> per2 = null ; // 声明Person对象 per2 = new Person<Introduction>(new Introduction("王尼玛","男",27)); System.out.println(per2) ; } }
GitHub地址:https://github.com/leebingbin/