泛型

来源:互联网 发布:java的编程工具 编辑:程序博客网 时间:2024/06/08 20:08

   ## generic 一般的;广泛类型的;

   ##输出字符串的长度功能

import java.util.*;class GenericDemo { public static void main(String[] args)  {  ArrayList al = new ArrayList();  al.add("java01");  al.add("java002");  al.add("java0003");  al.add("java00004");  Iterator it = al.iterator();  while(it.hasNext())//输出字符串的长度,要用到自付出的特有方法  {   String s =(String)it.next();//由于多态,Object obj = it.next();父类中没有字符串长度特有方法,必须向下转型   System.out.println(s+"长度:"+s.length());  } }}


   (1)集合中只能添加对象,但是1.6以后集合有了新特性,可以添加基本数据类型:

      添加基本数据类型的原理:

      基本数据类型包装类:自动装箱、自动拆箱

     

    ArrayList al = new ArrayList();      al.add(4);//Integer i = 4;//这里4是一个对象,i是类类型引用指向这个常量对象

ArrayList al = new ArrayList();
      al.add(4);//Integer i = 4;//这里4是一个对象,i是类类型引用指向这个常量对象

   (2)发现问题,集合中传入字符串以后就不能传入其他类型的数据,会提示ClassCastException 类型转换异常

    ##这种问题在编译时期不会提示,在运行时期会提示异常,使用户无法解决

   (3)为了避免这一安全问题,1.5增加了集合的新特性-“泛型”

      泛型的概述:规定集合接收数据的数据类型,规定迭代器的接收类型

    ##切记:泛型的作用:“指定具体类型”

    

ArrayList<String> al = new ArrayList<String>();      Iterator<String> it = al.iterator();  ArrayList<String> al = new ArrayList<String>();      Iterator<String> it = al.iterator();    ##规定了泛型,如果输入其他类型数

据,在编译时就会提示报错

      <>就是用来约束类型的,泛型<>中接收的一定是“引用数据类型”

   (4)泛型的好处:

      1.将运行时期的类型转换异常转移到了编译时期:

        方便程序员解决问题,让运行时期问题减少,安全

      2.避免了强制转换的麻烦(给迭代器规定泛型不用再强制转换)

7、泛型小练习:

//按照长度对字符串进行排序

import java.util.*;class LenComparator implements Comparator<String>{ public int compare(String o1,String o2) {  int num = new Integer(o1.length()).compareTo(new Integer(o2.length()));//长度倒叙排列将对象互换  if(num==0)   return o1.compareTo(o2);//长度倒叙排列将对象互换  return num; }}class GenericDemo2 { public static void main(String[] args)  {  TreeSet<String> ts = new TreeSet<String>(new LenComparator());  ts.add("java01");  ts.add("java02");  ts.add("java03");  ts.add("java004");  ts.add("java0005");  Iterator<String> it = ts.iterator();  while(it.hasNext())  {   String s = it.next();   System.out.println(s);  } }}

   (1)集合可以定义泛型,迭代器可以定义泛型,比较器接口也可以定义泛型:

    TreeSet<String> ts = new TreeSet<String>();//集合泛型      Iterator<String> it = ts.iterator();//迭代器泛型      class C implements Comparator<String>//实现比较器接口泛型      public int compare(String o1,String o2)//实现了接口泛型,复写的方法参数也必须是泛型数据类型

    (2)基本数据包装类有compareTo()比较,用来比较两个数值的大小

      o1.length()//得到的字符串长度是一个整数

      new Integer()用来接收这个长度,这个整数对象就具有了compareTo()这个比较方法,可以比较两个数值的大小

      o1.compareTo()//字符串的比较方法是用来比较两个字符串的自然顺序

    ##若想按长度从大到小输出,只需要把o1和o2两个比较对象兑换位置即可,因为二叉树>1的往右放,<1的往左放
     

8、泛型类:

class Student{ private String name; private int age; Student(String name,int age) {  this.name = name;  this.age = age; } public String getName() {  return name;  } public int getAge() {     return age; }}class Utils<QQ>//这个就是反省类{ private QQ q; public void setObject(QQ q) {  this.q=q; } public QQ getObject() {  return q; }}class GenericClassDemo { public static void main(String[] args)  {  Utils<Student> u = new Utils<Student>();//新建一个反省类对象,指定类型为Student类型  u.setObject(new Student("lisi",20));//设置对象方法  Student stu = u.getObject();//用Student类型引用接收一个设置好的了Student对象  System.out.println(stu.getName()+"......"+stu.getAge());//输出这个对象的名字和年龄 }}


9、泛型方法:

   泛型类:将泛型定义在类上 class A<E>

   泛型方法:public <T> void show(T t)

   (1)当定义一个泛型类时,泛型类中的方法所操作的类型就都是泛型类型了:

     例: class Demo<T> 
          void show(T t){}
          void print(T t){}

          Demo<String> d = new Demo<String>();

          这时d对象在调用show()和print方法时传入的对象只能是String类型的,出现了操作的局限性

        ##如果想操作其他数据类型,就只能再new一个新的对象

   (2)解决这个问题,可以不定义泛型类 而定义泛型方法:

      class Demo
      public <T> void show(T t){}
      public <T> void print(T t){}

      Demo d = new Demo();

      d.show(String);
      d.print(new Integer(3));
      
    ## 此时就可以用一个对象操作不用类型的数据了,解决了数据类型操作的局限性

    ## 切记:泛型中操作的数据类型只能是“引用数据类型”

10、泛型类中一样可以定义泛型方法:

   class Demo<T>
   {
 public void show(T t)
 {}
 public <Q> void print(Q q)
 {}
   }
   主函数中:
   Demo<String> d = new Demo<String>();
   d.show(String);//可以通过编译
   d.show(4);//编译失败,show()方法是String类型操作方法,

   d.print(3.14);编译成功:泛型方法

   ## 泛型方法的书写格式:
      public <Q> void pritn(Q q)
      泛型定义在方法上,将泛型置于返回值类型前面

11、静态泛型方法:

   (1)class Demo<T>
      public static void method(T t)

    ##此方法在调用时会提示:静态访问非静态内容
      因为要调用类中的方法就要建立对象,静态随着类先加载在内存中,对象后加载,而且对象在堆中,是非静态内容,不能将数据传入静态方法中  
 
   (2)静态泛型方法:

      class Demo<T>
      public static <Q> void method(Q q)

    ##此方法是静态泛型方法,调用时只传入数据,不是类对象的特有数据,所以可以编译通过

    ##总结:
           静态方法不可以访问类上定义的泛型
           静态泛型方法可以操作不确定的引用数据类型

12、泛型接口:

   ## 泛型接口的两种格式:

  (1)第一种格式:在子类继承接口时就明确泛型类型:

interface Inter<T>{ public void show(T t);}class SubInter implements Inter<String>//实现接口时就已经明确了泛型类型{ public void show(String s) {  System.out.println("show..."+s); }}class GenericInterfaceDemo{ public static void main(String[] args) {  SubInter s = new SubInter();  s.show("haha"); }}


   (2)第二种格式:在子类实现接口时不明确泛型类型,让用户自己定义数据类型

interface Inter<T>{ public void show(T t);}class SubInter<T> implements Inter<T>//实现接口时不明确泛型类型,由用户自定义数据类型{ public void show(T t) {  System.out.println("show..."+t); }}class GenericInterfaceDemo{ public static void main(String[] args) {  //不是泛型方法就要实例两个对象操作不同的数据类型  SubInter<String> s = new SubInter<String>();  s.show("hehe");  SubInter<Integer> s1 = new SubInter<Integer>();  s1.show(5); }}

13、集合中的泛型--通配符:

   (1)当在类中定义一个方法(普通方法或静态方法),要接收一个集合,但不明确传入集合的类型时,可以用“通配符?”来代替:

public static void show(ArrayList<?> al)//静态函数方便内部调用,ArrayList<?> 传入的集合类型可以是任意类型
{
 Iterator<?> it = al.iterator();//传入集合是不明确类型,迭代器也要接收不明确类型
 while(it.hasNext())
 {
  System.out.println(it.next());
 }
}

   ##迭代器的类型随着函数传入的集合类型而变化

   (2)第二种方式:静态泛型方法

public static <C> void show(ArrayList<C> al)//静态函数方便内部调用,ArrayList<C> 传入的集合类型可以是任意类型
{
 Iterator<C> it = al.iterator();//传入集合是不明确类型,迭代器也要接收不明确类型
 while(it.hasNext())
 {
  System.out.println(it.next());
 }
}

14、泛型的高级应用:泛型限定

    ## GenericLimit 泛型限定 ;

   (1)泛型限定:

      上限:? extends E ,E这个类型和它的子类型都可以接收

      下限:? super E ,E这个类型和它的父类型都可以接收

   例:

/*
定义一个泛型上限:
person父类
Student子类
定义一个ArrayList接口,分别添加父类对象,子类对象
调用方法,方法中用迭代器遍历元素,要求可以访问父类和子类对象,获取对象的名字
*/

import java.util.*;class Person{ private String name;        Person(String name) {  this.name = name; } public String getName() {  return name; }}class Student extends Person{ Student(String name) {  super(name); }}class GenericLimitDemo { public static void main(String[] args)  {  ArrayList<Person> al = new ArrayList<Person>();//定义一个接收Person类型的泛型集合  al.add(new Person("java01"));  al.add(new Person("java02"));  al.add(new Person("java03"));  ArrayList<Student> al1 = new ArrayList<Student>();//定义一个接收Student类型的泛型集合  al1.add(new Student("java--01"));  al1.add(new Student("java--02"));  al1.add(new Student("java--03"));  showName(al);  showName(al1); } public static void showName(ArrayList<? extends Person> al)//泛型上限:限制了父类是Person,只要是它的子类即可 {  Iterator<? extends Person> it = al.iterator();  while(it.hasNext())  {   System.out.println(it.next().getName());  } }}

      ##public static void showName(ArrayList<? super Student> al)//泛型下限:限制了子类Student,只要是它的父类即可

   (2)Comparable和Comparator(比较器)的泛型限定:

       Comparable(集合<? super E>)泛型下限:
       Comparator(集合<? super E>)泛型下限:只要是E的父类对象都可以

     ##Comparable和Comparator的泛型限定都是下限,只要是E的父类都可以传入:

       例:

     1.class Student implements Comparable<Student>:此类是Student,它继承了Person,那只要是Student的父类就可以作为泛型
       {
    public int comparable(Student s){}
       }
     ##传入的是Person也可以:
       class Student implements Comparable<Person>
       {
    public int comparable(Person s){}//如果传入Student Person s = new Student();这是多态
       }
       
     2.class MyComp implements Comparator<Student>:比较器的操作泛型是Student,是它的父类就可以作为泛型,因为下限
       {
    public int compare(Student s1,Student s2){}
       }
     ##传入父类的泛型:
       class MyComp implements Comparator<Person>
       {
    public int compare(Person p1,Person p2){}//传入Student一样是多态
       }

   (3)Collection中的方法:

      containsAll(Collection<?> c) :此集合包含另一个结合的所有元素,返回true
      removeAll(Collection<?> c):移除与指定集合的交集元素,移除成功返回true,否则返回false  
      retainAll(Collection<?> c):保留与指定集合的交集元素

   (4)泛型限定提高了扩展性:

    ##规定类型限定以后,以后的新类只要继承父类就可以传入泛型类中


0 0
原创粉丝点击