第十二章 泛型

为什么要有泛型

泛型(Generic):标签
所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这个类型参数将在使用时(例如,继承或实现这个接口,用这个类型声明变量、创建对象时)确定(即传入实际的类型参数,也称类型实参)。

泛型的使用

package atgugui.java;

import org.junit.Test;

import java.util.*;

/**
 * 泛型的使用
 * 1.jdk5.0新增的特性
 *
 * 2.在集合中使用泛型:
 * 总结:
 * ①集合接口或集合类在jdk5.0时都修改为带泛型的结构
 * ②在实例化集合类时,可以指明具体的泛型类型
 * ③指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如,方法,构造器,属性)使用到类的泛型的位置,都指定为实例化时泛型的类型
 * 比如:add(E e) ----->实例化以后,add(Integer e)
 * ④注意点:泛型的类型必须是类,不能是基本数据类型,需要用到基本数据类型的位置,拿包装类代替
 * ⑤如果实例化时,没有指明泛型的类型。默认类型为java.lang.Object类型
 *
 * 3.如何自定义泛型结构:泛型类、泛型接口、泛型方法,见GenericTest1
 *
 *
 *
 * @author xq
 * @create 2020-12-30-9:47
 */
public class GenericTest {
    //在集合中使用泛型之前的情况:
    @Test
    public void test1() {
        ArrayList list = new ArrayList();
        //需求:存放学生的成绩
        list.add(78);
        list.add(68);
        list.add(38);
        list.add(48);
        list.add(58);
        //问题一:类型不安全
        // list.add("Tom");
        //问题二:强转时,可能出现ClassCastException
        for (Object score : list) {
            int stuScore = (int) score;
            System.out.println(stuScore);
        }
    }

        //在集合中使用泛型的情况:以ArrayList为例
        @Test
        public void test2(){
            ArrayList<Integer> list = new ArrayList<>();
            list.add(78);
            list.add(68);
            list.add(38);
            list.add(48);
            list.add(58);
            //编译时就会进行类型检查,保证数据的安全
            for(Integer score : list){
                //避免了强转操作
//                int stuScore = score;
//                System.out.println(stuScore);
                System.out.println(score);
            }
        }

        //HashMap
        @Test
        public void test3(){
           // Map<String,Integer> map = new HashMap<String,Integer>();
            //jdk7新特性,类型推断
            Map<String,Integer> map = new HashMap<>();
            map.put("Tom", 11);

            //泛型的嵌套
            Set<Map.Entry<String,Integer>> entry = map.entrySet();
            Iterator<Map.Entry<String, Integer>> iterator = entry.iterator();
            while (iterator.hasNext()){
                System.out.println(iterator.next());

            }
        }
}

自定义泛型

package atgugui.java;

/**
 * 自定义泛型类
 * @author xq
 * @create 2020-12-30-10:36
 */
public class Order<T> {

    String orderName;
    int orderId;

    //类的内部结构就可以使用类的泛型

    T orderT;
    public Order(){}
    public Order(String orderName,int orderId,T orderT){
        this.orderName = orderName;
        this.orderId = orderId;
        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 +
                '}';
    }
}

泛型继承,通配符

package atgugui.java;

import org.junit.Test;

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

/**
 * 1.泛型在继承方面的体现
 *
 * 类A是类B的父类,G<A>和G<B>不具备子父类关系,二者是并列关系
 *
 * 补充:类A是类B的父类,A<G> s是B<G>的父类
 *
 * 2.通配符的使用
 * @author xq
 * @create 2020-12-30-12:47
 */
public class GenericTest2 {


    /*
    1.泛型在继承方面的体现
     */
    @Test
    public void test1(){
        Object obj = null;
        String str = null;

        obj = str;

        Object[] arr1 = null;
        String[] arr2 = null;
        arr1 = arr2;

        List<Object> list1 = null;
        List<String> list2 = null;
        //此时的list1和list2的类型不具有子父类关系
        //编译不通过
//        list1 = list2;
//        Date date = new Date();
//        str = date;
    }

    /*
    2.通配符的使用
        通配符: ?
        类A是类B的父类,G<A>和G<B>是没有关系的,二者共同的父类是:G<?>
     */
    @Test
    public void test2(){
        List<Object> list1 = null;
        List<String> list2 = null;

        List<?> list = null;

        list = list1;
        list = list2;


        //
        List<String> list3 = new ArrayList<>();
        list3.add("A");
        list3.add("B");
        list3.add("C");
        list = list3;
        //添加:对于List<?>不能向其内部添加数据
        //除了添加null之外
        list.add(null);

        //获取:
        Object o = list.get(1);


    }
    public void print(List<?> list){
        Iterator<?> iterator = list.iterator();
        while (iterator.hasNext()){
            Object obj = iterator.next();
            System.out.println(obj);
        }

    }
    /*
    3.有限制条件的通配符的使用
        ?extends A:
            G<? extends A>可以作为G<A>和G<B>的父类的,其中B是A的子类
        ? super A:
            G<? super A>可以作为G<A>和G<B>的父类,其中B是A的父类
     */

}

关于自定义泛型类,泛型接口时

package atgugui.java;

import org.junit.Test;

/**
 *
 * 1.关于自定义泛型类,泛型接口时
 *
 *
 * @author xq
 * @create 2020-12-30-10:40
 */
public class GenericTest1 {
    @Test
    public void test1(){
        //如果定义了泛型类,实例化没有指明类的泛型,则认为此泛型类型为Object类型
        //要求:如果大家定义了类带泛型的,建议实例化时要指明类的泛型
        Order order = new Order();
        order.setOrderT(123);
        order.setOrderT("ABC");

        //建议:实例化时指明类的泛型
        Order<String> order1 = new Order<String>("Order",1001,"r");
        order1.setOrderT("AA");

    }
}

第十三章 IO流

13.1 File类的使用

package atgugui.java1;

import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.util.Date;

/**
 * File类的使用
 *
 * 1.File类的一个对象,代表一个文件或一个文件目录(俗称:文件夹)
 * 2.File类声明在java.io包下
 * 3.File类中涉及到关于文件或文件目录的创建、删除、重命名、修改时间、文件大小等方法,
 * 并未涉及到写入或读取文件内容的操作,如果需要读取或写入文件内容,必须使用IO流来完成
 * 4.后续File类的对象常会作为参数传递到流的构造器中,指明读取或写入的"终点"。
 *
 *
 * @author xq
 * @create 2020-12-30-14:55
 */
public class FileTest {
    /*
    1.如何创建File类的实例
        File(String filePath)
        File(String Path)
        File(File parentFile,String childPath0)
    2.
    相对路径:相较于某个路径下,指明的路径
    绝对路径:包含盘符在内的文件或文件目录的路径

    3.路径分隔符
    window:\\
    unix:/
     */
    @Test
    public void test(){
        //构造器1
        File file1 = new File("Hello,txt");//相对于当前module
        File file2 = new File("D\\workspace_idea1\\JavaSenior\\day08\\hi.txt");
        System.out.println(file1);

        //构造器2
        File file3 = new File("D\\workspace_idea1","JavaSenior");
        System.out.println(file3);
        //构造器3:
        File file4 = new File(file3,"hi.txt");
        System.out.println(file4);

    }

    @Test
    public void test2(){
        File file1 = new File("hello.txt");
        File file2 = new File("d:\\io\\hi.txt");

        System.out.println(file1.getAbsolutePath());
        System.out.println(file1.getPath());
        System.out.println(file1.getName());
        System.out.println(file1.getParent());
        System.out.println(file1.length());
        System.out.println(new Date(file1.lastModified()));
        System.out.println();
        System.out.println(file2.getAbsolutePath());
        System.out.println(file2.getPath());
        System.out.println(file2.getName());
        System.out.println(file2.getParent());
        System.out.println(file2.length());
        System.out.println(file2.lastModified());


    }

    @Test
    public void test3(){
        File file = new File("D:\\idea\\workspace");
        String[] list = file.list();
        for(String s : list){
            System.out.println(s);
        }

        File[] files = file.listFiles();
        for(File f : files){
            System.out.println(f);
        }
    }
    /*
    public boolean renameTo(File dest):把文件重命名为指定的文件路径
    比如:file1.renameTo(file2)为例:
        要想保证返回true,需要file1是在硬盘中存在的,且file2不能在硬盘中存在
     */
    @Test
    public void test4(){
        File file1 = new File("hello.txt");
        File file2 = new File("D:\\idea\\io\\hi.txt");

        boolean renameTo = file1.renameTo(file2);
        System.out.println(renameTo);

    }
    @Test
    public void test5(){
        File file1 = new File("hello.txt");
        file1 = new File("hello1.txt");

        System.out.println(file1.isDirectory());
        System.out.println(file1.isFile());
        System.out.println(file1.exists());
        System.out.println(file1.canRead());
        System.out.println(file1.canWrite());
        System.out.println(file1.isHidden());

        File file2 = new File("D:\\idea\\io");

        System.out.println(file2.isDirectory());
        System.out.println(file2.isFile());
        System.out.println(file2.exists());
        System.out.println(file2.canRead());
        System.out.println(file2.canWrite());
        System.out.println(file2.isHidden());

    }

    @Test
    public void test6() throws IOException {
        //文件的创建
        File file = new File("hi.txt");
        if (file.exists() == false){
            file.createNewFile();
            System.out.println("创建成功");
        }else{//文件存在
            file.delete();
            System.out.println("删除成功");
        }
    }
    //文件目录的创建
    //mkdir:文件存在则不创建,上层不存在也不创建
    //mkdirs:上层不存在,一并创建
    @Test
    public void test7(){
        File file = new File("D:\\idea\\io1");

        boolean mkdir = file.mkdir();
        if(mkdir){
            System.out.println("创建成功");
        }
    }
}