前言

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));

    }
}

ContactAuthor