前言

Github:https://github.com/HealerJean

博客:http://blog.healerjean.com

1、泛型标识

E - Element (在集合中使用,因为集合中存放的是元素) 以下都是表示泛型名称。换成其他字母都没关系

标识 代表 说明
T Type Java 类,T 的使用,可以直接当做方法使用哦,函数里面可以对T进行操作
Type 表示不确定的java类型
     
K Key
V Value
N Number 数值类型

1.1、泛型中<?><T>有什么区别

<T>:的使用,可以直接当做方法使用哦,函数里面可以对T进行操作

<?>:表示不确定的java类型

/**
 * T 的使用,可以直接当做方法使用哦,函数里面可以对T进行操作
 */
public static <T> void printT(ArrayList<T> al){
  Iterator<T> it = al.iterator();
  while(it.hasNext())
  {
    T it1 = it.next();
    System.out.println(it1.toString());
  }
}
/**
 *  ? 的使用
 */
public static void printColl(ArrayList<?> al){
  Iterator<?> it = al.iterator();
  while(it.hasNext())
  {
    System.out.println(it.next().toString());
  }
}

2、泛型的使用以及存在时期

2.1、泛型的简单使用ListArrayList

//1、可以打印
List list = new ArrayList();
list.add(1);
list.add("String");
Iterator iterator = list.iterator();
while (iterator.hasNext()){
  System.out.println(iterator.next());//正常打印
}

2.2、泛型存在于编译时期

Java中编译后的class不会包含泛型信息,泛型只在编译阶段有效,成功编译过后的class文件中是不包含任何泛型信息的。泛型信息不会进入到运行时阶段

private static void testEquals() {
		ArrayList<String> a = new ArrayList<String>();  
		ArrayList b = new ArrayList();  
  
		Class c1 = a.getClass();  
		Class c2 = b.getClass();  
		
		System.out.println(c1 == c2); //true   表示已经经过编译了,没有任何泛型信息
		System.out.println(a == b); //false  
	}

2.3、利用反射调用arrylist

private static void invokeMethod() {
  ArrayList<String> a = new ArrayList<String>();  
  Class c = a.getClass();  

  a.add("CSDN_SEU_Cavin");  
  try{  
    Method method = c.getMethod("add",Object.class);  
    method.invoke(a,100);  
    System.out.println(a);  //[CSDN_SEU_Cavin, 100]  
  }catch(Exception e){  
    e.printStackTrace();  
  }  
}

3、自建反射对象的使用

3.1、具有泛型,T


public static class FX<T> {  
  private T ob; // 定义泛型成员变量  

  public FX(T ob) {  
    this.ob = ob;  
  }  

  public T getOb() {  
    return ob;  
  }  

  public void showTyep() {  
    System.out.println("T的实际类型是: " + ob.getClass().getName());  
  }  
}  

public static void main(String[] args) {  
  FX<Integer> intOb = new FX(100);
  intOb.showTyep();  
  System.out.println("value = " + intOb.getOb());  
  System.out.println("----------------------------------");  

  FX<String> strOb = new FX("CSDN_SEU_Calvin");
  strOb.showTyep();  
  System.out.println("value = " + strOb.getOb());  
}



T : java.lang.Integer
value = 100
----------------------------------
T : java.lang.String
value = CSDN_SEU_Calvin

3.2new 的实现,没有泛型


public static class FX {  
  private Object ob; // 定义泛型成员变量  

  public FX(Object ob) {  
    this.ob = ob;  
  }  

  public Object getOb() {  
    return ob;  
  }  

  public void showTyep() {  
    System.out.println("T的实际类型是: " + ob.getClass().getName());  
  }  
}  


object =: java.lang.Integer
value = 100
----------------------------------
object =: java.lang.String
value = CSDN_SEU_Calvin

public static void main(String[] args) {  
  FX intOb = new FX(new Integer(100));  
  intOb.showTyep();  
  System.out.println("value= " + intOb.getOb());  
  System.out.println("----------------------------------");  

  FX strOb = new FX("CSDN_SEU_Calvin");  
  strOb.showTyep();  
  System.out.println("value= " + strOb.getOb());  
}  

4、注意事项:

4.1、确定的泛型类型,传参必须确定类型才能成功

public class ThreeMain {
  public static void main(String[] args) {  
    FX<Number> ex_num = new FX<Number>(100);  
    getData(ex_num);  

    FX<Integer> ex_int = new FX<Integer>(200);  
    // getData(ex_int);//编译错误  
  }  

  //此行若把Number换为“?”或者“T” getData(ex_int);编译通过  
  public static void getData(FX<Number> temp) { 
    //do something...  
  }  

  public static class FX<T> { 
    private T ob;   
    public FX(T ob) {  
      this.ob = ob;  
    }  
  }  
}

4.2、<? extends Number><? supers Number>

<? extends Number> :表示继承 Number 的都能够使用

<? supers Number> :表示父类以上都能够使用

public class ThreeMain {
  public static void main(String[] args) {  
    FX<Number> ex_num = new FX<Number>(100);  
    getUpperNumberData(ex_num);

    FX<Integer> ex_int = new FX<Integer>(200);  
    getUpperNumberData(ex_int);

  }  

  public static void getUpperNumberData(FX<? extends Number> temp){  
    System.out.println("class type :" + temp.getClass());  
  }       
  
  public static class FX<T> {  
    private T ob;   
    public FX(T ob) {  
      this.ob = ob;  
    }  
  }  

4.3、不能对确切的泛型类型使用instanceof操作

public class FourMain {

  public static void main(String[] args) {
    FX<Number> ex_num = new FX<Number>(100);  
    FX<Integer> ex_int = new FX<Integer>(200);  

    // 报错,不能对确切的泛型类型使用instanceof操作。如下面的操作是非法的,编译时会出错。不确定的应该使用 ?
	 	if(ex_num instanceof FX<Number>){ 
      
		} 
	 
    if(ex_num instanceof FX<?>){    //使用T也是错误的,以为T也是已知的java类型
      
    } 
  }

  public static class FX<T> {  
    private T ob;   
    public FX(T ob) {  
      this.ob = ob;  
    }  
  }  
}

5、泛型的使用

5.1、DTO

@Data
@Accessors(chain = true)
public class Bean03DTO<A, N> {

    private A age;
    private N name;
}


@Data
@Accessors(chain = true)
public class Bean03OtherDTO<F> {

    private F friend;
}



public class Bean31ParentDTO<P> {

    private P parent;
}


@Data
public class Bean31SonDTO<S extends Bean31ParentDTO>{

    private S son;

}

5.2、泛型使用

public class GenericService {


    /**
     * 1、有多少泛型,前面放多少个
     */
    public static <A, N> A invokeOne(Bean03DTO<A, N> bean03DTO) {
        return bean03DTO.getAge();
    }

    /**
     * 2、有多少泛型,前面放多少个
     */
    public static <A, N, F>  Pair<Bean03DTO<A, N>, Bean03OtherDTO<F>> invokeTwo(Bean03DTO<A, N> dto, 
                                                                                Bean03OtherDTO<F> other) {
        Pair<Bean03DTO<A, N>, Bean03OtherDTO<F>> pair = new Pair<>(dto, other);
        return pair;
    }


    /**
     * 3、继承中的泛型引用
     */
    public static <S extends Bean31ParentDTO<String>>  S invokeThree(Bean31SonDTO<S> bean31SonDTO){
        return bean31SonDTO.getSon();
    }

    /**
     * 3、继承中的泛型引用,前面放多少个
     */
    public static <S extends Bean31ParentDTO<String>, A, N>  S invokeThree(Bean31SonDTO<S> bean31SonDTO, 
                                                                           Bean03DTO<A, N> bean03DTO){
        return bean31SonDTO.getSon();
    }

}
@Slf4j
public class TestMain {

    @Test
    public void test(){
        Bean03DTO<Integer, String> bean03DTO = new Bean03DTO<>();
        bean03DTO.setAge(11);
        bean03DTO.setName("HealerJean");
        log.info("invoke:{}", GenericService.invokeOne(bean03DTO));

        Bean03OtherDTO<String> bean03OtherDTO = new Bean03OtherDTO();
        bean03OtherDTO.setFriend("friend");
        log.info("invoke:{}", GenericService.invokeTwo(bean03DTO,bean03OtherDTO));

    }
}

6、instanceof

instanceof 操作符用于判断一个引用类型所引用的对象是否是一个类的实例。

public  void instanceOf(Object object) {
      /**
       *  ==
       */
      if(Long.class == object.getClass()){
          System.out.println("Long.class == object.getClass()");
      }

      /**
       * equals
       */
      if(Long.class.equals(object.getClass()) ){
          System.out.println("Long.class.equals(object.getClass()) ");
      }

      /**
       * instance Of
       */
      if(object instanceof  Long){
          System.out.println("object instanceof  Long");
      }
  } 

==equals比较的实际的 Class类,没有考虑继承,instanceofisInstance考虑继承


class  Father{}
class  Son extends  Father{}


public void fatherAndSon(){
    Father son = new Son(); //和 Son son = new Son(); 一样
    Father father = new Father();

    //son.getClass() ==  father.getClass() :false
    System.out.println("son.getClass() ==  father.getClass() :" +
                       (son.getClass() == father.getClass()) );

    //son.getClass().equals(father.getClass()) :false
    System.out.println("son.getClass().equals(father.getClass()) :" +
                       (son.getClass().equals(father.getClass())) );

    //son  instanceof Father :true
    System.out.println("son  instanceof Father :" +(son  instanceof Father ));

    //father  instanceof Son :false   //父类不能  instanceof  子类
    System.out.println("father  instanceof Son :" +(father  instanceof Son ));

    //father  instanceof Father :true
    System.out.println("father  instanceof Father :" +(father  instanceof Father ));

    //son.getClass().isInstance(father):false  //子类不能 isInstance 父亲
  System.out.println("son.getClass().isInstance(father):"+son.getClass().isInstance(father));

    //father.getClass().isInstance(son):true
  System.out.println("father.getClass().isInstance(son):"+father.getClass().isInstance(son));

    //son.getClass().isInstance(son)true
  System.out.println("son.getClass().isInstance(son)"+son.getClass().isInstance(son));

}

@Test
public void testFatherAndSon(){
    fatherAndSon();
}


7、ResolvableType

7.1、JDK

@Test
public void test() throws NoSuchFieldException {
    Type genericType = D003ResolvableType.class.getDeclaredField("param").getGenericType();
    ParameterizedType type = (ParameterizedType) genericType;
    Type[] typeArguments = type.getActualTypeArguments();
  
    System.out.println("从 HashMap<String, List<Integer>> 中获取 String:" + 
                       typeArguments[0]);
    // 从 HashMap<String, List<Integer>> 中获取 String:class java.lang.String

    System.out.println("从 HashMap<String, List<Integer>> 中获取 List<Integer> :" + 
                       typeArguments[1]);
    // 从 HashMap<String, List<Integer>> 中获取 List<Integer> :java.util.List<java.lang.Integer>

    System.out.println("从 HashMap<String, List<Integer>> 中获取 List :" + 
                       ((ParameterizedType) typeArguments[1]).getRawType());
    // 从 HashMap<String, List<Integer>> 中获取 List :interface java.util.List

    System.out.println("从 HashMap<String, List<Integer>> 中获取 Integer:" + 
                       ((ParameterizedType) typeArguments[1]).getActualTypeArguments()[0]);
    // 从 HashMap<String, List<Integer>> 中获取 Integer:class java.lang.Integer


    Field param = D003ResolvableType.class.getDeclaredField("param");
    System.out.println("从 HashMap<String, List<Integer>> 中获取父类型:"+
                       param.getType().getGenericSuperclass());
    // 从 HashMap<String, List<Integer>> 中获取父类型:java.util.AbstractMap<K, V>
}

7.2、Spring


@Test
public void test2() throws NoSuchFieldException {
    ResolvableType param = ResolvableType.forField(D003ResolvableType.class.getDeclaredField("param"));
  
    System.out.println("从 HashMap<String, List<Integer>> 中获取 String:" + 
                       param.getGeneric(0).resolve());
    // 从 HashMap<String, List<Integer>> 中获取 String:class java.lang.String

    System.out.println("从 HashMap<String, List<Integer>> 中获取 List<Integer> :" + 
                       param.getGeneric(1));
    // 从 HashMap<String, List<Integer>> 中获取 List :interface java.util.List

    System.out.println("从 HashMap<String, List<Integer>> 中获取 List :" + 
                       param.getGeneric(1).resolve());
    // 从 HashMap<String, List<Integer>> 中获取 List :interface java.util.List

    System.out.println("从 HashMap<String, List<Integer>> 中获取 Integer:" + 
                       param.getGeneric(1,0));
    // 从 HashMap<String, List<Integer>> 中获取 Integer:java.lang.Integer

    System.out.println("从 HashMap<String, List<Integer>> 中获取父类型:" +
                       param.getSuperType());
    // 从 HashMap<String, List<Integer>> 中获取父类型:java.util.AbstractMap<java.lang.String, java.util.List<java.lang.Integer>>
}

ContactAuthor