package cooom;

import org.junit.Test;

import java.util.*;

/**
 *
 * 泛型的使用
 * 1.jdk 5.0新增的特性
 * 2.在集合中使用泛型:
 *  总结:
 *   a.集合接口或集合类在jdk5.0是都修改为带泛型的结构
 *   b.在实例化集合类是,可以指明举例的泛型类型
 *   c.指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法,构造器属性等)使用到类的泛型的位置,
 *   都指定为实例化时泛型的类型 比如add(E e)----- >实例化以后add(Integer e)
 *   d.注意点:泛型的类型必须是一个类,不能是基本数据类型,需要用到基本数据类型的时候用包装类替换
 *   e.如果实例化时没有指明泛型的类型,默认泛型为java.lang.Object类型
 * 3.自定义泛型结构:泛型类丶泛型接口;泛型方法 。见:GenericTest.java
 * @author 冀帅
 * @date 2020/8/13-12:06
 */
public class GenericTest {
    //在集合中使用泛型之前的情况:
    @Test
    public  void  test1(){
        ArrayList list = new ArrayList();
        //需求:存放学生的成绩
        list.add(78);
        list.add(76);
        list.add(89);
        list.add(88);
        //问题一:类型不安全(没有限制存放数据的类型)
        list.add("Tom");

        for (Object score : list) {//取出来放到score里面
            //问题二:强转时,可能出现类型转换异常(ClassCastException)。
            int stuScore = (Integer) score;//Object转成Integer ,在自动拆箱
            System.out.println(stuScore);//ClassCastException
        }

    }       
    //在集合中使用泛型的情况:以ArrayList为例
    @Test
    public  void  test2(){
        //不能用int, 因为add()里是Object类型,int不属于。int默认值为0,Integer的默认值为NULL
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(78);
        list.add(87);
        list.add(99);
        list.add(65);
//        在编译时就进行类型检查,保证数据安全
//        list.add("Tom"); 编译错误
//        方式一遍历
//        for (Integer score : list) {
//            int stuScore = score;//不用再强转了
//            System.out.println(stuScore);
//
//        }


//        方式二遍历
        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

    }
    //在集合中使用泛型的情况:以HashMap为例
    @Test
    public  void  test3(){
        Map<String,Integer> map = new HashMap<String,Integer>();
        map.put("Tom",87);
        map.put("Jerry",87);
        map.put("Jack",67);
//        遍历方式一:遍历键
//        Set<String> set = map.keySet();
//        Iterator<String> iterator = set.iterator();
//        while (iterator.hasNext()){
//            System.out.println(iterator.next());
//        }
        //        遍历方式二:遍历键和值
//        Set<Map.Entry<String, Integer>> set = map.entrySet();
//        Iterator<Map.Entry<String, Integer>> iterator = set.iterator();
//        while (iterator.hasNext()){
//            System.out.println(iterator.next());
//        }
        //        遍历方式三:遍历键和值
        Set<String> set = map.keySet();
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()){
            String key = iterator.next();//拿到键
            Integer value = map.get(key);
            System.out.println(key+"---"+value);
        }

    }
}
package cooom;

import com.sun.org.apache.bcel.internal.generic.NEW;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/** 自定义泛型结构:泛型类丶泛型接口;泛型方法 。
 *
 * 1.关于自定义反省类,泛型接口:
 *
 *
 *
 * @author 冀帅
 * @date 2020/8/13-22:41
 */
public class GenericTest1 {
    @Test
    public  void test1(){
        //如果定义了泛型类,实例化时没有指明类的泛型,则认为此泛型类型为Object类型
        //要求:如果定义了类带泛型的,建议在实例化时要指明泛型的类型
        Order order = new Order();
        order.setOrderT(123);
        order.setOrderT("ABC");
        //建议:实例化时指明类的泛型
        Order<String> order1 = new Order<String>("orderAA",1001,"order:AA");

        order1.setOrderT("AA:hello");

    }
    @Test
    public  void test2(){
        SubOrder sub1 = new SubOrder();//在定义SubOrder类时已经指定过泛型类型,不用在这里在指定了
        //由于子类在继承带泛型的父类时,指明了泛型类型,则实例化子类对象时,不用再指明泛型类型。
        sub1.setOrderT(1122);
        SubOrder1<String> sub2 = new SubOrder1<>();
        sub2.setOrderT("order2...");
    }
     @Test
    public  void  test3(){
        //泛型不同的引用不能相互赋值
         ArrayList<String> list1 = null;
         ArrayList<Integer> list2 = null;
//         list1 = list2; 编译错误
         Person p1 = null;
         Person p2 = null;
         p1=p2;

     }
     //测试泛型方法
     @Test
    public void test4(){
        Order<String> order = new Order<>();
        Integer[] arr = new Integer[]{1,2,3,4};
        //泛型方法在调用时指明泛型参数的类型,与类的泛型毫无关系。
         List<Integer> list = order.copyFromArryToList(arr);//由放进去的数组决定的是Integer
         System.out.println(list);
//         Iterator<Integer> iterator = list.iterator();
//         while (iterator.hasNext()){
//             System.out.println(iterator.next());
//         }

     }
}
package cooom;

/**
 * @author 冀帅
 * @date 2020/8/14-12:16
 */
//异常类不能声明泛型类
//public class MyException <T> extends Exception{
//}

package cooom;

import java.util.ArrayList;
import java.util.List;

/**
 * 自定义泛型类
 * @author 冀帅
 * @date 2020/8/13-22:26
 */
public class Order <T> {
    String orderName;
    int orderId;
    //类的内部结构就可以使用类的泛型
    T orderT;//定义一个不知道什么类型的变量orderT
    public  Order(){
//        编译不通过
//        T[] arr = new T[20]
        //编译通过
          T[] arr = (T[]) new Order[1];


    }
    public Order(String orderName,int orderId,T orderT){
        this.orderId = orderId;
        this.orderName = orderName;
        this.orderT = orderT;
    }
    //以下三个方法都不是泛型方法
    public  T getOrderT(){

        return orderT;
    }
    public  void setOrderT(T orderT){

        this.orderT = orderT;
    }

    @Override
    public String toString() {
        return "Order{" +
                "orderName='" + orderName + '\'' +
                ", orderId=" + orderId +
                ", orderT=" + orderT +
                '}';
    }
    //静态方法中不能使用类的泛型。
    //类的泛型在实例化(造对象)的时候指定,静态结构早于实例化,所以会错
//    public static void  show(T orderT){
//        System.out.println(orderT);
//    }
    public  void  show(){
//        编译不通过
    }
//        try {
//
//        }catch (T t){
//
//        }
//    }
    //泛型方法:在方法中出现了泛型的结构,泛型的参数与类的泛型没有 任何关系
    //泛型方法所属的类是不是泛型类都没有关系
    //public后的<E>是为了让编译器知道E[]是个泛型,不是个类
    //静态方法不能使用类的泛型(先加载静态方法,类型还没指定,所以错),但泛型方法可以是静态的(调用的时候就指定了)
    public  static   <E> List<E> copyFromArryToList(E[] arr){//参数设置为不确定类型的数组,然后把数组放到List中
        ArrayList<E> list = new ArrayList<>();
        for (E e : arr) {//把arr放到e中
            list.add(e);//把e放到list中
        }
        return list;

    }
}

package cooom;

/**
 * @author 冀帅
 * @date 2020/8/14-12:02
 */
public class Person {
}
package cooom;

/**
 * @author 冀帅
 * @date 2020/8/13-22:51
 */
public class SubOrder extends Order<Integer>{//SubOrder不再是泛型类
}

package cooom;

/**
 * @author 冀帅
 * @date 2020/8/13-22:55
 */
public class SubOrder1<T> extends Order<T>{//SubOrder1<T>仍然为泛型类
}