java学习笔记——泛型Generic

------- android培训java培训、期待与您交流! ----------


泛型用于解决安全问题

一、泛型的使用:

LinkedList <String> al = new LinkedList<String>(); //LinkedList 相当容器 String 说明元素的类型

类似数组的声明:

int [ ]  ary = new int[ 4]; // [ ] 代表容器 ,int代表元素的类型


如果没有使用泛型

LinkedList al = new LinkedList();

al.offerLast("aa");

al.offerLast("bb");

将会报警告:Type Safety : The method offerLast(Object) belongs to the raw type LinkedList . Reference to generic type LinkedList<E >should be parametrized.(意思是为了类型的安全性,推荐使用泛型 LinkedList<E >,应该对LinkedList参数化。而不推荐使用未加工的LinkedList类型 )。

二、泛型使用的好处

1.可以将运行时出现的ClassCastException 提前的编译期间。

    如果没使用泛型,从集合里取出一个元素需要对它进行强制类型转换。而如果强制的类型不是元素的实际类型,在编译时可以通过,在运行时才能发现错误。

2.集合没使用泛型前,用Object类型接收具体类型对象,会失去具体类型的特征。

3.省去强制类型转换的操作。

   由于使用泛型时集合对同一类对象进行操作,保证了存入的都是同一类对象。而且知道对象的类型。所以在取出元素时不必进行强转。

三、自定义泛型

为什么要自定义泛型?

当1.5 之前没有泛型时,要对不知道操作的(对象的)类型是什么时,使用Object接受所有对象。

class Tools {

  private Object obj;

  public void setObject(Object obj) {

      this.obj = obj;

  }

 public Object getObject() {

       return obj;

 }

class Test

 {

     public static void main(String[ ] args) {

       Tools t = new Tools();

        t.setObj(new Worker());//传入Worker对象,变成Object对象

        Worker  er = (Worker) t.getObj();//取出的是Object对象,需要强转成实际对象才能使用。

   }

}// 1.5之前的集合操作就是采取这种思想。

class Worker {

 }

理由:当类中要操作的引用数据类型不确定时,早期定义Object 来完成扩展,1.5通过泛型来完成扩展。

定义泛型:

     class Tools <QQ > {// 泛型类定义的泛型在整个类中有效

             private QQ q;

             public void setObject(QQ q) {//在整个类中有效

                      this.q = q;

             }

             public QQ getObject ( ) {//在整个类中有效

                        return q;

              }

 泛型使用:

        class Test {

               public static void main(String [] args) {

               Tools<Worker> tool = new Tools<Worker>();

               tool.setObject(new Worker());

                Worker er = tool.getObject();//不要进行强转。


                 }

          }

 问题:泛型类定义的泛型,在整个类中有效。使用方法时,泛型类对象在明确要操作的具体类型后,所有要操作的类型已经固定了。

        为了让不同方法可以操作不同方法可以操作不同类型,而且类型还不确定,可以将泛型定义在方法上。

  解决: 泛型方法

四、自定义泛型方法

    class Demo {

     public <T>  display(T t) {//<T>写在返回类型之前。

     System.out.println("display ::"+ t);

    }

    class Test {

    pubic static void main(String[] args) {

            Demo d = new Demo();

            d.display("1234");

            d.display(12);

   }

   }

1.可以在泛型类中定义泛型方法吗?

 可以。而且这样做不是没有意义的。他的意义是:使得该方法能操作不对的对象。而不是泛型类确定的统一类型。

2.静态方法不可以使用类上的泛型。

   如在泛型类中有方法

     public static void method(T t){

                  System.out.println("method()");

     }

  编译会报 无法从静态上下文(ps:方法)引用非静态  类 T;

  原因我想是:静态方法是在泛型类字节码加载时就被加载的,但是T 是在泛型类创建对象时Demo<String> demo = new Demo<String>;才确定的 。

 解决办法:定义泛型方法在静态方法上。

    public static  <T>  void method(T t){

                  System.out.println("method()");

     }


五 、泛型定义在接口上

    在java API中可以看到很多容器接口都定义了泛型。

    Interface Itr<T> {

             void show(T t);

    }

   可以有两种方式使用泛型接口

1.实现类操作明确类型,例String

   class ItrImpl implements Itr<String> {

          void show(String t){

              System.out.println(t);

          }

     }

2.实现类操作泛型

   class  ItrImpl2 implements Itr<T>  {

          void show(T t){

            System.out.println(t);

          }

     }

六 、泛型限定

  <?> :占位符 、通配符 表示被操作的具体类型不确定

             <?>只能定义在方法上,不能定义在类上。

      public static void main (String [] args) {

             ArrayList<String> al = new ArrayList<String>();

             al.add("aa");

             al.add("bb");

            al.add("cc");

            ArrayList<Integer> al2 = new ArrayList<Integer>();

             al2.add(11);

             al2.add(12);

             al2.add(13);

//要求:现在要遍历出al 、al2中的元素 ,该怎么做?

//al al2 使用各自的遍历器。

            showCon(al);

            showCon(al2);        

     }

也可以:

  方法一:   定义一个泛型方法。

<span style="font-size:14px;">static <T> void  showCon (ArrayList<T> al){
	  for(Iterator<T> it = al.iterator();it.hasNext();){
		  T t = it.next();
		  System.out.println(t);
	  }
	  
  }</span>
方法二:用占位符<?>表示具体类型不确定。

<span style="font-size:14px;">static void showCon(ArrayList<?> al) {
		for (Iterator<?> it = al.iterator(); it.hasNext();) {
			// T t = it.next(); 占位符与泛型方法的不同,泛型方法可以能接受具体类型对象并操作,而占位符不能。
			System.out.println(it.next());//it.next.length(),error.不能使用类型的特有方法。
		}
	}</span>

七、<?>的高级应用

  问题:不允许这样使用泛型

   ArrayList<Person> al = new ArrayList<Student>();//Student是Person的子类

   和 ArrayList<Student> al = new ArrayList<Person>();

  解决 <? extends E>

         <? super E>

TreeSet<E> API

addAll(Collection<? extends E> c) 操作某类及某类的子类   上限

TreeSet(Comparator<? super E> comparator) 操作某类及某类的父类   下限

使用举例

<span style="font-size:14px;"><? extends E>

/*<?>通配符的高级应用 、<? extends E>上限定。
   接收E及E的子类
 */
package java5new;

import java.util.*;
public class GenericDemo1 {
    public static void main(String[] args){
        ArrayList<Person> al = new ArrayList<Person>();
        al.add(new Person("001"));
        al.add(new Person("002"));
        al.add(new Person("003"));
        ArrayList<Student> al2 = new ArrayList<Student>();
        al2.add(new Student("01"));
        al2.add(new Student("02"));
        al2.add(new Student("03"));
        printAl(al);
        printAl(al2);
    }
    public static void printAl(ArrayList<? extends Person> al){//<span style="color:#FF0000;">接收Person及Person的子类</span>
       for(Iterator<? extends Person> it = al.iterator();it.hasNext();){//注意Iterator与AL类型一致
          System.out.println(it.next().getName());//可以使用特有方法
       }
       
    }
}
class Person {
    String name;
    Person(String name){
        this.name = name;
    }
    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return name;
    }
}
class Student extends Person{

    Student(String name){//继承中,子类要写明构造方法
        super(name);
    }
    
}</span>


  

<? super E >   

<span style="font-size:14px;">/*
 * TreeSet(Comparator<? super E> comparator) 
 * 可以传递E或E的父类
 */

import java.util.*;

public class XiaXianDemo {

	public static void main(String[] args) {
		TreeSet<Student> ts = new TreeSet<Student>(new Comp()); // E:Student
		ts.add(new Student("s001"));
		ts.add(new Student("s002"));
		ts.add(new Student("s003"));
		TreeSet<Worker> ts2 = new TreeSet<Worker>(new Comp()); // E:Worker
		ts2.add(new Worker("w001"));
		ts2.add(new Worker("w002"));
		ts2.add(new Worker("w003"));
		
		Iterator<Student> it = ts.iterator();//注意迭代器的定义
		while(it.hasNext()){
			System.out.println(it.next().getName());
		}
		Iterator<Worker> it2 = ts2.iterator();//注意迭代器的定义
		while(it2.hasNext()){
			System.out.println(it2.next().getName());
		}
	}

}

class Worker extends Person {
	Worker(String s) {
		super(s);

	}
}

class Comp implements Comparator<Person> {  //只定义接收父类的比较器,不分别定义Worker 、Student类的比较器,<span style="color:#FF0000;"><? super E> </span>
	public int compare(Person p1, Person p2) {
		return p1.getName().compareTo(p2.getName());
	}
}</span>

以下是自己的一点思考总结:

1.泛型定义时不能操作 T 泛型的具体方法。

2.泛型的使用时可以操作具体类型的具体方法

3.<?>不用于定义泛型类class Demo<?>{},error.



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值