现在的位置: 首页 > 综合 > 正文

黑马程序员_<<基础加强--1.5新特性(泛型)(下)>>

2018年09月16日 ⁄ 综合 ⁄ 共 4745字 ⁄ 字号 评论关闭
文章目录

--------------------ASP.Net+Android+IOS开发.Net培训、期待与您交流! --------------------

1. 泛型

      1.概述

         泛型就是为了提高安全性,接口,类和方法上都可以使用泛型,特别是集合中常用到,对于泛型,是在编译器起到作用,当你存到了与指定的泛型类型不相同的对象,那么编译器会提示错误,但是在运行期,泛型是起不到作用的,下面我们就利用反射存储和指定泛型类型不一样的对象,来验证泛型是在编译器其作用。

 

import java.util.ArrayList;
public class FanXing {
  public static void main(String[] args) throws Exception {
    ArrayList list = new ArrayList();// 这里编译器会给警告,不安全的警告
    ArrayList<Integer> list1 = new ArrayList<Integer>();// 这里编译器就不会提示警告了
    list1.add(new Integer(12));
    list1.add(new Integer(34));
    System.out.println("list1=" + list1);
    /**
     * 利用反射向集合中存储和类型不一样的对象先利用反射获得方法,然后调用方法来进行存储
     */
    ArrayList.class.getMethod("add", Object.class).invoke(list1, "abc");// true,插入成功
    System.out.println("list1=" + list1);
  }
}
结果:
list1=[12, 34]
list1=[12, 34, abc]

 

从结果可以看出,已经把”abc”存储进去了,所以我们只要跳过了编译器,那么我们就会存储任何对象了。

     2.泛型术语

                  例如:    

                    ArrayList<E>:E称为类型变量或类型参数

         ArrayList<Integer>:整个称为参数化的类型

         ArrayList<Integer>:其中Integer称为类型参数的实例或实际类型参数

         ArrayList<Integer>:中的<>念着typeof

         ArrayList:称为原始类型

 

     3.泛型声明格式

 

          
/*
前后指定的泛型类型不一样,泛型类型参数不存在继承关系*/

    Collection<Object> con=new ArrayList<String>();//编译失败

    Collection<String> con1=new ArrayList<Object>();//编译失败

   
/*
可以一遍声明参数类型,一遍不声明*/

    Collection<Object> con2=new ArrayList();//编译成功,有警告

    Collectioncon3=new ArrayList<Object>();//编译成功,有警告

 

 

        泛型集合没有数组类型

          List<String> [] list=newArrayList<String>[10];//编译失败

   

     4.通配符

              4.1通配的使用

                通配符用?表示,表示任意类型

 

        

 import java.util.ArrayList;
import java.util.List;
public class FanXing {
  public static void main(String[] args) throws Exception {
 
    ArrayList<String> list = new ArrayList<String>();// 这里编译器就不会提示警告了
    list.add("abc");
    list.add("hello");
    show(list);
    ArrayList<Integer> list1 = new ArrayList<Integer>();// 这里编译器就不会提示警告了
    list1.add(new Integer(12));
    list1.add(new Integer(34));
    show(list1);
 
  }
 
  public static void show(List<?> list) {// ?表示可以接收任何类型的List集合
    System.out.println(list);
  }
}
结果:
[abc, hello]
[12, 34]

            4.2上下限

            

        类<?extends  类(A)> :设置上限,?可以是A类对象或者是A的子类对象。

       类<? Super  类(B)> :设置上限,?可以是B类对象或者是A的父类对象。

       例如:

import java.util.ArrayList;
import java.util.List;
public class FanXing {
  public static void main(String[] args) throws Exception {
 
    ArrayList<Integer> list = new ArrayList<Integer>();// 这里编译器就不会提示警告了
    list.add(new Integer(12));
    list.add(new Integer(34));
    show(list);
    ArrayList<Object> list1 = new ArrayList<Object>();// 这里编译器就不会提示警告了
    list1.add(new Integer(12));
    list1.add("abc");
    show1(list1);
 
  }
  // ?表示可以接收Number的类型或者是NUmber子类的类型的List集合,其他的类型不可以
  public static void show(List<? extends Number> list) {
    System.out.println(list);
  }
  // ?表示可以接收Number的类型或者是NUmber父类的类型的List集合,其他的类型不可以
  //这里可以知道Number的父类只有Object,所以只能接受Number和Object类型
  public static void show1(List<? super Number> list) {
    System.out.println(list);
  }
}
结果:
[12, 34]
[12, abc]

 

     5.综合使用

       

   import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.Map;
import java.util.Map.Entry;
public class FanXing {
  public static void main(String[] args) throws Exception {
 
    HashMap<String,Integer> map=new HashMap<String,Integer>();
    map.put("java01", 20);
    map.put("java02", 22);
    map.put("java03", 23);
    /*
     * 读取HashMap集合,有三种方法,
     *  1.读取键集
     *  2.读取值集
     *  3.读取Map.Entry
     *  下面使用第三种读取集合*/
    Set<Map.Entry<String,Integer>> entry=map.entrySet();
      Iterator<Entry<String, Integer>> it=entry.iterator();
       while(it.hasNext()){
         Map.Entry<String,Integer> ks=it.next();
         System.out.println(ks.getKey()+"="+ks.getValue());
       }
  }
 
}
结果:
java02=22
java03=23
java01=20
 

     6.小知识点

          Java中的泛型是模仿的是C++的泛型

     java中的泛型是是在编译期,在运行期间就“擦除了”

     注意事项:

          只有引用类型的才能作为泛型的实际参数类型

           要是int类型会自动装箱成Integer

           但是int[]数组就不会自动装箱,因为本身就是引用类型, 但是其不能作为泛型的实际参数。

     异常泛型,你可以抛出泛型异常,但是获取的时候,catch()处理异常的时候不能是catch(T  e)必须是具体的异常,catch(Exceptione),可以抛出throw (T) e,和throws T

 

      

     7.自定义泛型类

         在方法中使用泛型的时候,定义的时候在方法的返回值前面声明其泛型,<T>为类定义泛型public class 类名<T>{}

       静态方法中不能使用和定义类的时候的泛型,因为对象没有创建的时候就调用了,所以静态方法调用的时候,可以没有对象,但是泛型不知道了,但是你要是使用泛型的话,那么就可定义类的泛型可以分开,不使用同一个泛型。


      详细的可以参考黑马程序员_<<泛型>>

         8.获得方法参数的类型

             通过泛型类型的方法获得方法参数的类型

 

       publicstaticvoidapplyVector(Vector<Date> v1) {}

       publicstaticvoidapplyVector(Vector<Integer>
v1)
{}

       首先说明;这样写编译器活报错,原因是这不是方法的重载,参数类型都是Vector类型,不能通过用泛型来区分这不是同一类型,这是同一个类型,都是Vector,同时早获取方法的时候,也不能获取Vector<Data>.class或者Vector<Integer>.class类型,只能是Vector.class.

 

import java.lang.reflect.*;
import java.util.Date;
import java.util.Vector;
 
public class FanXing {
  public static void main(String[] args) throws SecurityException,
      NoSuchMethodException {
    Method method = FanXing.class.getMethod("applyVector", Vector.class);//获得方法
    Type[] types = method.getGenericParameterTypes();//获得方法上的泛型类型
    ParameterizedType pType = (ParameterizedType) types[0];// 通过Type的子类获取对象,第一个类型
    System.out.println(pType.getRawType());// 获取对象的类型
    System.out.println(pType.getActualTypeArguments()[0]);
    // 获取的是对象中的所有参数,我们知道我们定义的方法只有一个泛型类型,所以取第一个就可以
  }
 
  public static void applyVector(Vector<Date> v1) {
 
  }
 
}
结果:
class java.util.Vector
class java.util.Date
 

--------------------ASP.Net+Android+IOS开发.Net培训、期待与您交流!
--------------------

抱歉!评论已关闭.