Java_Set集合/Map集合/异常/IO流/File类/反射

Set集合的特点和应用

特点:
不可重复、无序
应用:
Set< T > set = new HashSet<>();
结论:
Set集合保证元素的唯一性依赖:equals()和hashCode()两个方法

package cn.itcast.demo8;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class Test {
    public static void main(String[] args) {
        //1.创建集合对象
        Set<Student> set = new HashSet<>();

        //2.创建元素对象
        Student s1 = new Student("Q",41);
        Student s2 = new Student("W",31);
        Student s3 = new Student("E",21);
        Student s4 = new Student("E",21);
        Student s5 = new Student("Q",41);

        //3.将集合对象添加到元素对象中
        set.add(s1);
        set.add(s2);
        set.add(s3);
        set.add(s4);
        set.add(s5);

        //4.遍历对象
        /*
            为什么Set集合没有“去除”?
                因为Set集合保证元素的唯一性依赖:equals()和hashCode()两个方法
                你没有在Student类中重写这两个方法,默认调用的是Object类中的这两个方法
                而Object类中的equals()方法默认比较的是地址值是否相同
            解决方案:
                在student类中重写equals()和hashCode()方法
         */
        System.out.println(set);
        System.out.println("-----------------");

        //通过迭代器遍历Set集合
        System.out.println("通过迭代器遍历Set集合");
        //A.通过集合对象获取其对应的迭代器对象
        Iterator<Student> it = set.iterator();
        //B.判断迭代器中是否有元素
        while (it.hasNext()) {
            //C.如果有,就获取元素
            Student s = it.next();
            System.out.println(s);
        }
        System.out.println("-----------------");

        //通过增强for循环遍历Set集合
        System.out.println("通过增强for循环遍历Set集合");
        for (Student student : set) {
            System.out.println(student);
        }

    }
}


Map集合的特点和应用

特点:
双列集合,元素由键值对(entry)构成;key — value。
key不可以重复,value可以重复
应用:
Map<T1,T2> map = new HashMap<>();
T1:表示键的数据类型;T2:表示值的数据类型
成员方法:
V put (K key ,V value):添加元素(键值对的形式),元素第一次添加,返回null,重复添加,会用新值覆盖旧值,并返回旧值
V get (Object key):根据键获取其对应的值
Set< K > key Set():获取所有键的集合
遍历步骤:
1.获取所有键的集合 keySet()
2.遍历所有的坚,获取到每一个键 迭代器/增强for
3.根据键,获取指定的值 get()

package cn.itcast.demo8;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Test {
    public static void main(String[] args) {
        //1.创建集合对象
        //键:学生的编号;值:具体的学生对象
        Map<Integer,Student> map = new HashMap<>();
        //2.创建元素对象
        Student s1 = new Student("Q",24);
        Student s2 = new Student("W",23);
        Student s3 = new Student("Q",24);
        //3.将元素对象添加到集合中
        /*Student stu1 = map.put(1,s1);
        System.out.println("stu1:" + stu1);
        Student stu2 = map.put(1,s2);
        System.out.println("stu2:" + stu2);*/
        map.put(1,s1);
        map.put(2,s2);
        map.put(3,s3);

        Student stu3 = map.get(3);
        System.out.println("key:" + 3 + ",value" + stu3);

        System.out.println(map);
        System.out.println("------------------");

        //4.遍历集合
        /*Set<Integer> keys = map.keySet();
        Iterator<Integer> it = keys.iterator();
        while (it.hasNext()){
            Integer key = it.next();
            Student value = map.get(key);
            System.out.println("key:" + key + "...value" + value);
        }*/
        Set<Integer> keys = map.keySet();
        for (Integer key : keys) {
            //key就是双列集合中的每一个键
            Student v = map.get(key);
            System.out.println(v);
        }
    }
}

package cn.itcast.demo8;

import java.util.Objects;

public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age &&
                Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}


案例:模拟斗地主发牌

package cn.itcast.demo8;

import java.util.*;

/*
    案例:模拟斗地主发牌
    步骤:1.买牌 /2.洗牌 /3.发牌 /4.看牌
 */
public class SendPokerTest {
    public static void main(String[] args) {
        //1.    买牌
        //1.1   定义一个双列集合,键:表示牌的编号;值:表示具体的牌。规则:编号越小,牌越小
        Map<Integer,String> pokers = new HashMap<>();
        //1.2   定义一个单列集合,用来存储所有牌的编号
        List<Integer> list = new ArrayList<>();
        //1.3   具体的买牌动作
        int num = 0;
        String[] colors = {"♠","♥","♣","♦"};
        String[] numbers = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
        for (String number : numbers) {
            for (String color : colors){
                String poker = color + number;
                pokers.put(num,poker);
                list.add(num);
                num++;
            }
        }
        pokers.put(num,"小王");
        list.add(num++);
        pokers.put(num,"大王");
        list.add(num++);

        System.out.println("所有的牌:" + pokers);
        System.out.println("牌的编号:" + list);
        System.out.println("---------------------------");

        //2.洗牌
        Collections.shuffle(list);
        System.out.println( "洗好牌后牌的编号为:" + list);

        //3.    发牌
        //3.1   定义4个集合,分别表示3个玩家,底牌
        List<Integer> LiuYiFei = new ArrayList<>();
        List<Integer> JungSooJung = new ArrayList<>();
        List<Integer> Wo = new ArrayList<>();
        List<Integer> DiPai = new ArrayList<>();
        //3.2   具体的发牌动作,将索引和3取模,决定发给谁
        for (int i = 0; i < list.size(); i++){
            Integer pokerNum = list.get(i);
            if (i >= list.size() - 3){
                DiPai.add(pokerNum);
            } else if (i % 3 == 0){
                LiuYiFei.add(pokerNum);
            } else if (i % 3 == 1){
                JungSooJung.add(pokerNum);
            } else if (i % 3 == 2){
                Wo.add(pokerNum);
            }
        }

        /* //3.3   查看玩家,底牌的编号
        System.out.println("LiuYiFei:" + LiuYiFei);
        System.out.println("JungSooJung:" + JungSooJung);
        System.out.println("Wo:" + Wo);
        System.out.println("DiPai:" + DiPai);*/
        System.out.println("---------------------------");

        //3.3
        /*String str = printPoker(LiuYiFei,pokers);
        System.out.println("LiuYiFei:" + str);*/
        System.out.println("LiuYiFei:" + printPoker(LiuYiFei,pokers));
        System.out.println("JungSooJung:" + printPoker(JungSooJung,pokers));
        System.out.println("Wo:" + printPoker(Wo,pokers));
        System.out.println("DiPai:" + printPoker(DiPai,pokers));


        /*
        4.定义一个方法,用来看牌
          方法名:  printPoker
          参数列表:List<Integer>,Map<Integer,String>
          返回值:  String
        */

        }
    public static String printPoker(List<Integer> nums ,Map<Integer,String> pokers){
        //1.对牌的编号进行升序排列
        Collections.sort(nums);
        //2.遍历牌的编号集合,获取到每一个编号
        StringBuilder sb = new StringBuilder();
        for (Integer num : nums) {
            //3.根据编号去双列集合中查找改编号对应的具体牌
            String poker = pokers.get(num);
            //4.将获取到的牌进行拼接
            sb.append(poker + " ");
        }
        //5.将最后拼接结果返回即可
        String str = sb.toString();
        return str.trim();
    }
}


异常的分类

顶层父类:
Throwable
异常(Exception):
合理的应用程序可能需要捕获的问题,例:NullPointerException
错误(Error):
合理的应用程序不应该试图捕获的问题,例:StackOverFlowError


异常的处理方式

JVM默认的异常处理方式:
在控制台打印错误信息,并终止程序

开发中异常的处理方式:
try…catch ( finally ): 捕获,自己处理

try{
//尝试执行的代码
}
catch(Exception e){
//出现可能的异常之后的处理代码
}
finally{
//一定会执行的代码,如关闭资源
}

处理完异常之后,程序会继续执行
执行流程:先执行try{}中的内容,看是否有问题(异常);没有的话,直接执行finally语句中的内容,有的话,跳转到catch(){}语句中开始执行,再执行finally{}语句中的内容

package cn.itcast.demo8;

public class Test {
    public static void main(String[] args) {
        /*int a = 10 / 0;
        System.out.println("a:" + a);
        System.out.println("TEST");*/

        //通过try.catch.finally来处理异常
        try{
            int a = 10 / 10;
            System.out.println("a:" + a);
            return;
        } catch(Exception e){
            System.out.println("被除数不能为0");
            return;
        } finally {    //即使try或者catch中有return,finally里边的代码也会执行
            System.out.println("TEST");
        }
 //       System.out.println("TEST");
    }
}

throws: 抛出,交给调用者处理
特点:执行结束后,程序不再继续执行

package cn.itcast.demo8;

public class Test {
    public static void main(String[] args) throws Exception {
        //需求:调用show()
        //因为show()方法已经抛出了一个异常,作为调用者(main函数)必须处理这个异常

        /*//方案一:接着抛
        show();*/

        //方案二:采用try.catch处理
        try{
            show();
        }catch (Exception e){
            System.out.println("ERROR!");
        }
        System.out.println("TEST");
    }

    //定义一个方法
    public static void show() throws Exception{
        int a = 10 / 0;
        System.out.println("a:" + a);
    }
}


IO流概述

什么是IO流?
I/O,即输入(Input)输出(Output),IO流指的是数据像连绵的流体一样进行传输。
IO流可以干什么?
再本地磁盘和网络上操作数据
IO流的分类
按数据流向分:输入流 / 输出流
按操作方式分:字节流:InputStream-OutputStream / 字符流:Reader-Writer
IO流体系
1.字符流:按字符读写数据的IO流。Reader:FileReader-BufferedReader;Writer:FileWriter-BufferedWriter
2.字节流:按字节读写数据的IO流。InputStream:FileInputStream-BufferedInputStream;OutputStream:FileOutputStream-BufferedOutputStream

IO流简介:
    概述:
        I(Input,输入)/ O(Output,输出)流,是Java中用来传输数据的方式。
    划分:
        按照流向分:
            输入流:读数据
            输出流:写数据
        按照操作分:
            字节流:以字节为单位来操作数据
                InputStream:        字节输入流的顶层抽象类
                    FileInputStream:        普通的字节输入流
                    BufferedInputStream:    高效的字节输入流(也叫:缓冲字节输入流)
                OutputStream:       字节输出流的顶层抽象类
                    FileOutputStream:       普通的字节输出流
                    BufferedOutputStream:   高效的字节输出流(也叫:缓冲字节输出流)
            字符流:以字符为单位来操作数据
                 Reader:        字符输入流的顶层抽象类
                     FileReader:        普通的字符输入流
                     BufferedReader:    高效的字符输入流(也叫:缓冲字符输入流)
                 Writer:       字节输出流的顶层抽象类
                     FileWriter:        普通的字符输出流
                     BufferedWriter:    高效的字符输出流(也叫:缓冲字符输出流)


File类

概念:
文件,文件夹,一个对象代表磁盘上的某个文件或文件夹
构造方法:
File(String pathname)
File(String parent,String child)
File(File parent,String child)
成员方法:
1.创建功能——createNewFile():创建文件;mkdir()和mkdirs():创建目录
2.判断功能——isDirectory():判断File对象是否为目录;isFile():判断File对象是否为文件;exists():判断File对象是否存在。

package cn.itcast.demo8;

import java.io.File;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        //需求:将D:\abc\1.txt封装成对象
        //法一:根据字符串形式的路径获取FIle对象
//      File file1 = new File("D:\\abc\\1.txt");
        File file1 = new File("D:/abc/1.txt");
        System.out.println(file1);

        //法二:根据字符串形式的父目录以及子目录创建File对象
        File file2 = new File ("D:/abc/","1.txt");
        System.out.println(file2);

        //法三:根据父目录对象,以及字符串形式的子目录来获取File对象
        File file3 = new File("D:/abc/");
        File file4 = new File(file3,"1.txt");
        System.out.println(file4);
        System.out.println("----------------------");

        System.out.println("创建对象");
        File file5 = new File("D:/2.txt");
        boolean flag1 = file5.createNewFile();
        System.out.println(flag1);

        File file6 = new File("D:/a");
        boolean flag2 = file6.mkdir();      //make directory,创建单级目录
        System.out.println(flag2);

        File file7 = new File("D:/a/b/c");
//      boolean flag3 = file7.mkdir();
        boolean flag3 = file7.mkdirs();     //创建多级目录(也可以创建单级目录)
        System.out.println(flag3);
        System.out.println("----------------------");

        System.out.println("创建判断功能");
        File file8 = new File("D:/a/b");
        /*boolean flag4 = file8.isDirectory();
        System.out.println("是否文件夹:" + flag4);*/
        System.out.println("是否文件夹:" + file8.isDirectory());
        System.out.println("是否是文件: " + file8.isFile());
        System.out.println("是否存在: " + file8.exists());
    }
}

3.获取功能——getAbsolutePath():获取绝对路径(以盘符开头的路径),如 D:/1.txt;getPath():获取文件的绝对路径 (一般是相对于当前项目路径来讲的),如1.txt;getName():获取文件名;list():获取指定目录下所有文件(夹)名称数组;listFiles():获取指定目录下所有文件(夹)File数组。

package cn.itcast.demo1;

import java.io.File;

public class Test {
    public static void main(String[] args) {
        File file1 = new File("lib/1.txt");
        //获取file1的绝对路径
        System.out.println(file1.getAbsolutePath());
        //获取file1的相对路径
        System.out.println(file1.getPath());
        //获取文件名
        System.out.println(file1.getName());
        System.out.println("---------------------------");
        //获取lib文件夹下所有的文件(夹)的:名称数组
        File file2 = new File("lib");
        String[] names = file2.list();
        for (String name : names) {
            System.out.println(name);
        }
        System.out.println("---------------------------");

        //获取lib文件夹下所有的文件(夹)的:File对象数组 File[]
        File[] files = file2.listFiles();
        for (File file : files) {
            System.out.println(file);
        }
    }
}


字符流读数据 - 按单个字符读写

创建字符流读文件对象:
Reader reader = new FileReader(“readme.txt”);
调用方法读取数据:
int data = reader.read();
读取一个字符,返回该字符代表的整数,若到达流的末尾,返回-1
异常处理:
throws IOException
关闭资源:
reader.close();

package cn.itcast.demo1;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class ReaderDemo1 {
    public static void main(String[] args) throws IOException {
        //通过字符流读取数据
        //1.创建字符输入流对象
        Reader reader = new FileReader("lib/1.txt");
        //2.读取数据
        /*int ch1 = reader.read();
        System.out.println(ch1);    //97
        int ch2 = reader.read();
        System.out.println(ch2);    //98
        int ch3 = reader.read();
        System.out.println(ch3);    //99
        int ch4 = reader.read();
        System.out.println(ch4);    //-1*/

        /*
        优化上述的读法,用循环改进
        又因为不知道循环次数,所以用while循环
         */
        //定义变量,用来接收读取到的字符
        int ch;
        /*
        (ch = reader.read()) != -1 做的三件事
        1.执行(ch = reader.read()),去文件中读取一个字符。
        2.执行 ch = reader.read(),将读取到的字符赋值给变量。
        3.(ch = reader.read()) != -1,用读取到的字符(内容)与 -1 进行比较
         */
        while ((ch = reader.read()) != -1){
            System.out.println(ch);
        }
        //3.释放资源
        reader.close();
    }
}


字符流读数据 - 一次读取一个字符数组

创建字符流读文件对象:
Reader reader = new FileReader(“readme.txt”);
调用方法读取数据:
char[ ] chs = new char [2048];
int len = r.read.(chs);
读取字符到数组中,返回读取的字符数,若到达流的末尾,返回-1
异常处理:
throws IOException
关闭资源:
reader.close();

package cn.itcast.demo1;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class ReaderDemo2 {
    public static void main(String[] args) throws IOException {
        //需求:通过字符流读取数据,一次读取一个字符数组
        //1.创建字符输入流对象
        Reader reader = new FileReader("lib/2.txt");
        //2.读取数据
        /*char[] chs = new char[3];
        int len1 = reader.read(chs);
        System.out.println(chs);    //abc
        System.out.println(len1);   //3

        int len2 = reader.read(chs);
        System.out.println(chs);    //def
        System.out.println(len2);   //3

        int len3 = reader.read(chs);
        System.out.println(chs);    //gef
        System.out.println(len3);   //1

        int len4 = reader.read(chs);
        System.out.println(chs);    //def
        System.out.println(len4);   //3*/

        /*
        用while循环优化上述的代码
         */
        char[] chs = new char[3];
        //定义一个变量,记录读取到的有效字符数
        int len;
        while ((len = reader.read(chs)) != -1){
            //将读取到的内容转换成字符串
            /*
            chs:表示要操作的数组
            0:表示起始索引
            len:表示要操作的字符的个数
             */
            String s = new String(chs,0,len);
            System.out.println(s);
        }
        //3.释放资源
        reader.close();
    }
}


字符流写数据 - 按单个字符写入

创建字符流写文件对象:
Writer writer = new FileWriter(“dest.txt”);
调用方法写入数据:
int x = ‘中’;
writer.write(x);
写一个字符
异常处理:
throws IOException
关闭资源:
writer.close();

字符流写数据 - 按单个字符写入

创建字符流写文件对象:
Writer writer = new FileWriter(“dest.txt”);
调用方法写入数据:
char[ ] chs = {‘橙’,‘心’,‘橙’,‘意’};
writer.write(chs);
写一个字符数组
异常处理:
throws IOException
关闭资源:
writer.close();

字符流写数据 - 按字符串写入

创建字符流写文件对象:
Writer writer = new FileWriter(“dest.txt”);
调用方法写入数据:
writer.write(“我爱学习”);
写一个字符串
异常处理:
throws IOException
关闭资源:
writer.close();

package cn.itcast.demo2;

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class WriterDemo {
    public static void main(String[] args) throws IOException {
        //通过字符流写数据
        //1.创建字符输出流对象
        Writer writer = new FileWriter("lib/1.txt");
        //2.写数据
        /*//一次写一个字符
        writer.write('i');*/

        /*//一次写一个指定的字符
        char[] chs = {'h','e','l','l','o'};
        writer.write(chs);
//      writer.write(chs,0,2);*/

        //一次写一个字符串
        writer.write("HelloWorld");
        //3.释放资源
        writer.close();
    }
}


字符流拷贝文件 - 按单个字符读写

创建字符流读文件对象:
Reader reader = new FileReader(“readme.txt”);
调用字符流写文件对象:
Writer writer = new FileWriter(“dest.txt”);
调用方法读取数据:
int data = reader.read();
调用方法写入数据:
writer.write(data);
异常处理:
throws IOException
关闭资源:
reader.close();
write.close();

package cn.itcast.demo3;

import java.io.*;

public class CopyFile1 {
    public static void main(String[] args) throws IOException {
        //需求:通过字符流拷贝文件,一次读写一个字符
        //例如:将1.txt文件中的内容赋值到2.txt文件中
        /*
        IO流拷贝文件核心六步:
            1.创建字符输入流对象,关联数据源文件
            2.创建字符输出流对象,关联目的地文件
            3.定义变量,记录读取到的内容
            4.循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量
            5.将读取到的数据写入到目的地文件中
            6.释放资源
         */
        //1
        //Reader reader = new FileReader("lib/1.txt");
        FileReader fr = new FileReader("lib/1.txt");
        //2
        FileWriter fw = new FileWriter("lib/2.txt");	//如果目的地文件不存在,程序会自动创建
        //3
        int len;
        //4
        while ((len = fr.read()) != -1){
            //5
            fw.write(len);
        }
        //6
        fr.close();
        fw.close();
    }
}


字符流拷贝文件 - 按字符数组读写

创建字符流读文件对象:
Reader reader = new FileReader(“readme.txt”);
调用字符流写文件对象:
Writer writer = new FileWriter(“dest.txt”);
调用方法读取数据:
char[ ] chs = new char[2048];
int len = reader.read(chs);
调用方法写入数据:
writer.write(chs, 0, len);
异常处理:
throws IOException
关闭资源:
reader.close();
writer.close();

package cn.itcast.demo3;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyFile2 {
    public static void main(String[] args) throws IOException {
        //需求:通过字符流拷贝文件,一次读写一个字符数组
        //例如:将1.txt文件中的内容复制到2.txt文件中
        /*
        IO流拷贝文件核心六步:
            1.创建字符输入流对象,关联数据源文件
            2.创建字符输出流对象,关联目的地文件
            3.定义变量,记录读取到的内容
            4.循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量
            5.将读取到的数据写入到目的地文件中
            6.释放资源
         */
        //1
        FileReader fr = new FileReader("lib/1.txt");
        //2
        FileWriter fw = new FileWriter("lib/2.txt");
        //3
        //定义一个字符数组
        char[] chs = new char[1024];
        //用来记录读取到的有效字符数
        int len;
        //4
        while ((len = fr.read(chs)) != -1){
            //5
            fw.write(chs,0,len);
        }
        fr.close();
        fw.close();
    }
}


字符缓冲流拷贝文件的标准代码

创建字符流写文件对象:
BufferReader br = new BufferedReader(new FileReader(“readme.txt”));
创建字符流写文件对象:
BufferedWriter bw = new BufferedWriter(new FileWriter(“dest.txt”));
异常处理:
throws IOException
使用while循环读写数据:
int len ;
while((len = br.read()) !+ -1){
bw.write(len);
}
关闭资源:
br.close();
bw.close();

package cn.itcast.demo4;

/*
字符缓冲流用法:
    分类:
        BufferedReader:字符缓冲输入流(也叫高效字符输入流)
            构造方法:
            public BufferedReader(Reader reader);
        BufferedWriter:字符缓冲输出流(也叫高效字符输出流)
            构造方法:
            public BufferedWriter(Writer writer);
     特点:
        字符缓冲流自带有缓冲区,大小为8192个字符,也就是16KB
 */

import java.io.*;

public class CopyFile1 {
    public static void main(String[] args) throws IOException {
        //需求:通过字符缓冲流,将1.txt文件中的内容拷贝到2.txt文件中

        //1.创建字符缓冲输入流对象,关联数据源文件
        //1.1 创建普通的字符输入流对象
        FileReader fr = new FileReader("lib/1.txt");
        //1.2 创建字符流缓冲输入流对象
        BufferedReader br = new BufferedReader(fr);
        //简化上述的代码
//        BufferedReader br2 = new BufferedReader(new FileReader("lib/1.txt"));

        //2.创建字符缓冲输出流对象,关联目的地文件
        //2.1 创建普通的字符输出流对象
        FileWriter fw = new FileWriter("lib/2.txt");
        //2.2 创建字符流缓冲输出流对象
        BufferedWriter bw = new BufferedWriter(fw);

        //3.定义变量,记录读取到的数据
        int len;
        //4.循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量
        while ((len = br.read()) != -1){
            //5.将读取到的数据写入到目的地文件中
            bw.write(len);
        }
        //6.释放资源
        br.close();
        bw.close();
    }
}


package cn.itcast.demo4;

import java.io.*;

public class CopyFile2 {
/*
字符缓冲流用法:
    分类:
        BufferedReader:字符缓冲输入流(也叫高效字符输入流)
            成员方法:
            public String readLine;
        BufferedWriter:字符缓冲输出流(也叫高效字符输出流)
            构造方法:
            public void newLine();           根据当前操作系统给出对应的换行符:
                                                windows:\r\n
                                                mac:\r
                                                unix:\n   
     特点:
        字符缓冲流自带有缓冲区,大小为8192个字符,也就是16KB

 */
    public static void main(String[] args) throws IOException {
        //需求:通过字符缓冲流“一次读写一行”的方式,将1.txt文件中的内容拷贝到2.txt文件中
        //1.创建字符流缓冲输入流对象,关联数据源文件
        //分开写
        /*FileReader fr = new FileReader("lib/1.txt");
        BufferedReader br = new BufferedReader(fr);*/
        //合并
        BufferedReader br = new BufferedReader(new FileReader("lib/1.txt"));
        //2.创建字符缓冲流输出流对象,关联目的地文件
        BufferedWriter bw = new BufferedWriter(new FileWriter("lib/2.txt"));
        //3.定义变量,记录读取到的内容
        String str;
        //4.循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量
        while ((str = br.readLine()) != null){
            //5.将读取到的内容写入到目的地文件中
            bw.write(str);
            //千万注意一个小细节,特别容易忽略——换行
//            bw.write("\r\n");
            bw.newLine();
        }
        //6.释放资源
        br.close();
        bw.close();
    }
}


普通字节流 - 一次读写一个字节

创建字节流读文件对象:
InputStream is = new FileInputStream(“Desktop.jpg”);
创建字节流写文件对象:
OutputStreas os = new FileOutputStream(“D:\xxx.jpg”);
异常处理:
throws IOException
使用while循环读写数据:
int b;
while((b = is.read()) != -1){
os.write(b);
}
关闭资源:
is.close();
os.close();

package cn.itcast.demo1;
/*
字节流的用法
    File InputStream:普通的字节输入流,用来读取数据的
        构造方法:
            public FileInputStream(String pathname);
        成员方法:
            public ine read();  一次读取一个字节,并返回读取到的内容,读不到返回-1
    FileOutputStream:普通的字节输出流,用来写数据的
        构造方法:
            public FileOutputStream(String pathname);
        成员方法:
            public void write(int len); 一次写入一个字节
*/

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyFile1 {
    public static void main(String[] args) throws IOException {
        //需求:通过普通的字节流,一次读写一个字节的方式,将a.jpg复制到b.jpg
        //1.创建字节输入流,关联数据源文件
        FileInputStream fis = new FileInputStream("lib/a.jpg");
        //2.创建字节输出流,关联目的地文件
        FileOutputStream fos = new FileOutputStream("lib/b.jpg");
        //3.定义变量,用来记录读取到的内容
        int len;
        //4.循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量
        while ((len = fis.read()) != -1){
            //5.将读取到的内容写入到目的地文件中
            fos.write(len);
        }
        //6.释放资源
        fis.close();
        fos.close();
    }
}


普通字节流 - 一次读写一个字节数组

创建字节流读文件对象:
InputStream is = new FileInputStream("Desktop.jpg);
创建字节流写文件对象:
OutputStream os = new FileOutputStream(D:\xxx.jpg);
异常处理:
throws IOException
定义字节数组,每次读取2048个字节:
byte [ ] b = new byte[2048];
使用while循环读写数据:
int len;
while((len = is.read(b) != -1){
os.write(b,0,len);
}
关闭资源:
is.close();
os.close();

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyFile2 {
/*
字节流的用法
    File InputStream:普通的字节输入流,用来读取数据的
        成员方法:
            public int read(byte[] bys);  一次读取一个字节数组,将读取到的内容存入到数组中,并返回读取到的有效字节数,读不到返回-1
    FileOutputStream:普通的字节输出流,用来写数据的
        成员方法:
            public void write(byte[] bys,int index,int len); 一次写入一个字节
*/
    public static void main(String[] args) throws IOException {
        //需求:通过普通的字节流,一次读写一个字节数组的方式,将a.jpg复制到b.jpg
        //1.创建字节输入流,关联数据源文件
        FileInputStream fis = new FileInputStream("lib/a.jpg");
        //2.创建字节输出流,关联目的地文件
        FileOutputStream fos = new FileOutputStream("lib/b.jpg");
        //3.定义变量,用来记录读取到的内容
        byte[] bys = new byte[1024];
        //用来记录读取到的有效字节数
        int len;
        //4.循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量
        while ((len = fis.read(bys)) != -1){
            //5.将读取到的内容写入到目的地文件中
            fos.write(bys,0,len);
        }
        //6.释放资源
        fis.close();
        fos.close();
    }
}


字节缓冲流拷贝文件的标准代码

创建字节流读文件对象:
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(“a.jpg”));
创建字节流写文件对象:
BufferedOutStream bos = new
BufferedOutputStream(new FileOutputStream(
“b.jpg”));
异常处理:
throws IOException
使用while循环读取数据:
int len;
while((len = bis.read()) != -1){
bos.write(len);
}
关闭资源:
bis.close();
bos.close();
总结:
拷贝纯文本文件使用字符流,拷贝其他(图片,音频,视频等)使用字节流。

package cn.itcast.demo2;
/*
字节缓冲流的用法
    BufferedInputStream:字节缓冲输入流(也叫:高效字节输入流),用来读取数据的
        构造方法:
            public BufferedInputStream(InputStream is);
        成员方法:
            public ine read();  一次读取一个字节,并返回读取到的内容,读不到返回-1
    BufferedOutputStream:字节缓冲输出流(也叫:高效字节输出流),用来写数据的
        构造方法:
            public BufferedOutputStream(String pathname);
        成员方法:
            public void write(int len); 一次写入一个字节
    特点:
        字节缓冲流有自己的缓冲区,大小为8192个字节,也就是8KB
*/

import java.io.*;

public class CopyFile1 {
    public static void main(String[] args) throws IOException {
        //需求:通过字节缓冲流,将a.jpg复制到b.jpg中
        //1.创建字节输入流,关联数据源文件
        /*//1.1 创建普通的字节输入流
        FileInputStream fis = new FileInputStream("lib/a.jpg");
        //1.2 创建高效的字节输入流
        BufferedInputStream bis = new BufferedInputStream(fis);*/
        //合并版
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("lib/a.jpg"));

        //2.创建字节输出流,关联目的地文件
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("lib/b.jpg"));
        //3.定义变量,用来记录读取到的内容
        int len;
        //4.循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量
        while ((len = bis.read()) != -1){
            //5.将读取到的内容写入到目的地文件中
            bos.write(len);
        }
        //6.释放资源
        bis.close();
        bos.close();
    }
}


案例:模拟用户上传头像

package cn.itcast.demo;

import java.io.*;
import java.util.Scanner;

public class UploadFile {
    public static void main(String[] args) throws IOException {
        //需求:模拟用户上传头像的功能,假设所有的用户头像都应该上传到:项目下的lib文件夹中
        //1.定义一个方法用来获取要上传的用户头像的路径。  getPath();
        File path = getPath();
        System.out.println(path);
        //2.定义一个方法用来判断眼上传的用户头像,在lib文件夹中是否存在
        boolean flag = isExists(path.getName());
        if (flag){
            //3.如果存在,提示:该用户头像已经存在,上传失败
            System.out.println("该用户头像已经存在,上传失败");
        }else{
            //4.如果不存在,就上传该用户头像,并提示上传成功
            //数据源文件     D:\1.png
            //目的地文件     lib/1.png
            uploadFile(path);
        }
    }

    public static File getPath(){
        //7.因为不知道用户多少次能录入,所以用while(true)改进
        while (true){
            //1.提示用户录入要上传的用户头像路径,并接收
            Scanner sc = new Scanner(System.in);
            System.out.println("请录入您要上传的用户头像的路径:");
            String path = sc.nextLine();
            //2.判断该路径的后缀名是否是:.jpg .png .bmp
            //3.如果不是,就提示:您录入的不是图片,请重新录入
            if (!path.endsWith(".jpg") && !path.endsWith(".png") && !path.endsWith(".bmp")){
                System.out.println("您录入的不是图片,请重新录入");
                //细节,千万注意,别忘了写
                continue;
            }
            //4.如果是,判断路径是否存在,并且是否是文件
            File file = new File(path);
            if (file.exists() && file.isFile()){
                //6.如果是,说明就是我们想要的数据(图片,文件),直接返回
                return file;
            }else{
                //5.如果不是,就提示:您录入的路径不合法,请重新录入
                System.out.println("您录入的路径不合法,请重新录入");
            }

        }
    }
    public static boolean isExists(String path){
        //1.将lib文件夹封装成File对象
        File file = new File("lib");
        //2.获取lib文件夹中所有的文件(夹)的名称数组
        String[] names = file.list();
        //3.遍历第二步获取到的数组,用获取到的数据依次和path进行比较
        for (String name:names){
            if (name.equals(path)){
                //4.如果一致,说明该用户头像已经存在了,就返回true
                return true;
            }
        }
        //5.如果不一致,说明该用户头像不存在,就返回false
        return false;
    }
    public static void uploadFile(File path) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(path));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("lib/" + path.getName()));
        int len;
        while((len = bis.read()) != -1){
            bos.write(len);
        }
        bis.close();
        bos.close();
        System.out.println("上传成功");
    }
}


反射基本概念

什么是反射:
在程序运行剁成中分析类的一种能力
作用:
1.分析类:加载并初始化一个类,查看类的所有属性和方法
2.查看并使用对象:查看一个对象的所有属性和方法,使用对象的任意属性和方法
应用场景:
1.构建通用的工具
2.搭建具有高度灵活性和扩展性的系统框架
类加载器(ClassLoader):
负责将类的字节码文件(.class文件)加载到内存中,并生成对应的Class对象
Class对象:
java.lang.Class类的对象,也叫字节码文件对象,每个Class对象对应一个字节码文件
类的加载时机:
1.创建类的实例:Student stu =new Student();
2.访问类的静态成员:Calendar.getInstance();
3.初始化类的子类:class User extends Person{};User user = new User();
4.反射方式创建类的class对象:Class cazz = Class.forName(“类的正名”);
正名:包名 + 类名,例如:cn.itcast.demo1.Student
获取class对象的三种方式:
1.Object类的getClass()方法:Class clazz = 对象名.getClass();
2.类的静态属性:Class clazz = 类名.class;
3.Class类的静态方法:Clas clazz = Class.forName(“类的正名”);
正名:包类路径名,如cn.itcast.bean.Student

package cn.itcast.demo1;

public class ReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        //需求:获取Class对象
        //方式一:
        Student stu = new Student();
        Class clazz = stu.getClass();

        //方式二
        Class clazz2 = Student.class;

        //方式三
        Class clazz3 = Class.forName("cn.itcast.demo1.Student");

        //思考:如何验证这三个class对象是同一个对象?
        System.out.println(clazz == clazz2);
        System.out.println(clazz3 == clazz2);
    }
}

package cn.itcast.demo1;

public class Student {
}


通过反射的方法获取构造方法并使用

Constructor< T >对象:
构造器对象,属于java.base模块,java.lang.reflect包
通过Class对象获取构造器对象:
1.getConstructor(Class<?>...parameterTypes):返回一个Constructor对象,仅公共构造函数;Class<?>…:可变参数,代表Class类型的数组;?:通配符,代表不确定的任意类型
2.getDeclaredConstructor(Class<?>…parameterTypes):返回一个Constructor对象,可获取私有构造函数
3.getConstructors():返回此类所有(不含私有)构造函数的数组
Constructor的常用方法:
1.String getName():返回构造函数名
2.T newInstance(Object… initargs):使用此构造函数和指定参数创建并初始化对象

package cn.itcast.demo2;

import java.lang.reflect.Constructor;

public class ReflectDemo1 {
    public static void main(String[] args) throws Exception {
        //需求:通过反射的方式创建:Student类的对象
        //1.    获取Student类的字节码文件对象
        Class clazz = Class.forName("cn.itcast.demo2.Student");
        //2.    根据第一步获取到的字节码文件对象,获取指定的构造器对象
        /*//2.1   获取公共的无参构造
        Constructor con1 = clazz.getConstructor();
        System.out.println(con1);
        //2.2   获取公共的带参构造
        Constructor con2 = clazz.getConstructor(String.class);
        System.out.println(con2);
        //2.3   获取私有的有参构造
        Constructor con3 = clazz.getDeclaredConstructor(int.class);
        System.out.println(con3);
        //2.4   获取Student类所有公共的构造函数
        System.out.println("----------------------");
        Constructor[] con4 = clazz.getConstructors();
        //      遍历数组
        for (Constructor con : con4) {
            System.out.println(con);
        }*/

        //2.2   获取公共的带参构造
        Constructor con2 = clazz.getConstructor(String.class);
        System.out.println(con2);

        //获取构造器的名字,看看它是哪个类的构造
        String name = con2.getName();
        System.out.println(name);

        //3.    根据构造器对象和参数,创建对应的Student对象
        Student stu = (Student) con2.newInstance("ZhangSan");
        //4.    打印结果
        System.out.println(stu);
    }
}

package cn.itcast.demo2;

public class Student {
    //公共的无参构造
    public Student(){}

    //公共的带参构造
    public Student(String name){
        System.out.println("your name is " + name);
    }

    //私有的带参构造
    private Student(int age){
        System.out.println("your age is " + age);
    }
}


通过反射的方法获取成员方法并使用

Method对象:
方法对象,属于java.base模块,java.lang.reflect包
通过Class对象获取构造器对象:
1.getMethod(String name,Class<?>…parameterTypes):返回一个method对象,仅公共成员方法;name:方法ming;parameterTypes:方法的参数列表
2.getDeclaredMethod(String,Class<?>…):返回一个Method对象,可获取私有成员方法
3.getMethod():返回此类所有(不含私有)方法的数组
Method的常用方法
1.String getName():返回方法名
2.Object invoke(Object obj,Object…args):在指定对象上调用此方法,参数为args

package cn.itcast.demo3;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class ReflectDemo3 {
    public static void main(String[] args) throws Exception {
        //需求:通过反射获取Student类中的成员方法并调用
        //1.    获取Student类的字节码文件对象
        Class clazz = Class.forName("cn.itcast.demo3.Student");

        //2.    获取该类的构造器对象,然后创建Student类的对象
        Constructor con = clazz.getConstructor();
        Student stu = (Student)con.newInstance();
        //System.out.println(stu);

        //3.    获取该类的成员方法对象,然后调用此方法
        //3.1   调用公共的空参方法
        Method method1 = clazz.getMethod("show1");
        //打印方法对象
        System.out.println(method1);
        System.out.println("------------------------");
        //打印方法名
        System.out.println(method1.getName());
        System.out.println("------------------------");
        //调用此方法
        method1.invoke(stu);
        System.out.println("------------------------");

        //3.2   公共的带参方法
        Method method2 = clazz.getMethod("show2", int.class);
        method2.invoke(stu,100);
        System.out.println("------------------------");

        //3.3   私有的带参方法
        Method method3 = clazz.getDeclaredMethod("show3", int.class, int.class);
        //开启暴力反射
        method3.setAccessible(true);
        //调用此方法
        int sum = (int)method3.invoke(stu,10,20);
        System.out.println(sum);
        System.out.println("------------------------");

        //3.4
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
    }
}

package cn.itcast.demo3;

public class Student {
    //公共的空参方法
    public void show1(){
        System.out.println("EMPTY");
    }

    //公共的带参方法
    public void show2(int a){
        System.out.println(a);
    }

    //私有的带参方法
    private int show3(int a ,int b){
        System.out.println("PRIVATE");
        return a + b;
    }
}


案例:通过反射获取方法并使用

package cn.itcast.demo4;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class ReflectDemo1 {
    public static void main(String[] args) throws Exception {
        //需求:通过反射获取类的setter方法,使用该方法为属性赋值
        //1.通过反射获取Student类的字节码文件对象
        Class clazz = Class.forName("cn.itcast.demo4.Student");

        //2.通过反射获取Student类的构造方法,并创建该类的对象
        Constructor con = clazz.getConstructor();
        Student stu = (Student)con.newInstance();

        //3.获取到指定的setName()方法,给Student对象设置值
        Method method1 = clazz.getMethod("setName", String.class);
        //调用此方法
        method1.invoke(stu,"ZhangWuJi");
        //4.打印学生对象
        System.out.println(stu);
    }
}

package cn.itcast.demo4;

//标准的JavaBean类,学生类
public class Student {
    //成员变量
    private String name;

    //空参构造
    public Student() {
    }

    //带参构造
    public Student(String name) {
        this.name = name;
    }

    //get&set
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    //toString

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                '}';
    }
}

反射方法获取成员变量并使用

Field对象:
域(属性、成员变量)对象,属于java.base模块,java.lang.reflect包
通过Class对象获取属性:
1.getField(String name):返回一个field对象,仅公共属性;name:属性名
2.getDeclaredField(String nam):返回一个field对象,可获取私有属性
3.getDeclaredFields():返回此类所有(含私有)属性的数组
Field的常用方法::
1.void set (Objict obj,Object value):设置obj对象的指定属性值为value
2.void setAccessible(boolean flag):将此属性的可访问性设置为指定布尔值

package cn.itcast.demo5;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class ReflectDemo1 {
    public static void main(String[] args) throws Exception {
        //需求:通过反射获取成员变量并使用
        //1.获取Student类的字节码文件对象
        Class clazz = Class.forName("cn.itcast.demo5.Student");

        //2.通过字节码文件对象获取构造器对象然后创建学生类对象
        Constructor con = clazz.getConstructor();
        Student stu = (Student)con.newInstance();
//      Student stu2 = (Student)clazz.getConstructor().newInstance();    
        
        //3.设置学生对象的各个属性值
        //3.1   设置姓名
        Field field1 = clazz.getField("name");
        field1.set(stu,"Q");
        
        //3.2   设置年龄
        Field field2 = clazz.getDeclaredField("age");
        //开启暴力反射
        field2.setAccessible(true);
        field2.set(stu,30);
        
        //4.答应学生对象
        System.out.println(stu);
    }
}

package cn.itcast.demo5;

public class Student {
    public String name;
    private int age;

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值