java基础复习

面对对象

4.6、线程池

线程池∶其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源

线程池:JDK1.5之后提供的

  • java. util. concurrent. Executors :线程池的工厂类,用来生成线程池

Executors类中的静态方法:

  • static ExecutorService newFixedThreadPool(int nThreads)创建一个可重用固定线程数的线程池
    • 参数: int nThreads:创建线程池中包含的线程数量
    • 返回值: ExecutorService接口,返回的是ExecutorService接口的实现类对象,我们可以使用ExecutorService接口接收(面向接口编程)

线程池的使用步骤:

1、使用线程池的工厂类Executors里边提供的静态方法newFixedThreadPool生产一个指定线程数量的线程池

2、创建一个类,实现Runnable接口,重写run方法,设置线程任务

3、调用ExecutorService中的方法submit,传递线程任务(实现类),开启线程,执行run方法

4、调用ExecutorService中的方法shutdown销毁线程池(不建议执行)

public class RunnableImpl implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"创建了一个线程");

    }
}

public class DemoThreadPool {
    public static void main(String[] args) {
        ExecutorService es = Executors.newFixedThreadPool(2);
        //线程池会一直开启,使用完了线程,会自动把线程归还给线程池,线程可以继续使用
        es.submit(new  RunnableImpl());
        es.submit(new  RunnableImpl());
        es.submit(new  RunnableImpl());

    }
}

4.7、Lambda表达式

面向对象的思想:

  • 做一件事情,找一个能解决这个事情的对象,调用对象的方法,完成事情.

函数式编程思想:

  • 只要能获取到结果,谁去做的,怎么做的都不重要,重视的是结果,不重视过程

lambda使用前提

  • 使用Lambda必须具有接口,且要求接口中有且仅有一个抽象方法。
  • 使用Lambda必须具有上下文推断。
    • 也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例。

Lambda格式

Lambda组成:

  • 一些参数
  • 一个箭头
  • 一段代码

格式:

(参数类型 参数名称)->{代码语句}

解释说明格式:

():接口中抽象方法的参数列表,没有参数,就空着;有参数就写出参数,多个参数使用逗号分隔

->:传递的意思,把参数传递给方法体{}

{}:重写接口的抽象方法的方法体

无参无返回

public interface Cook {
    public abstract void makeFood();
}
public class DemoCook {
    public static void main(String[] args) {
        invokeCook(new Cook() {
            @Override
            public void makeFood() {
                System.out.println("该吃饭了");
            }
        });
        //使用lambda表达式简化匿名内部类
        invokeCook(()->{
            System.out.println("吃饭了");
        });
    }
    
    public static void invokeCook(Cook cook) {
        cook.makeFood();
    }
}

有参有返回值

public class DemoArray {
    public static void main(String[] args) {
        Person[] array={
                new Person("奥巴马",18),
                new Person("赛娜",17),
                new Person("锤石",19),
        };
//        Arrays.sort(array, new Comparator<Person>() {
//            @Override
//            public int compare(Person o1, Person o2) {
//                return o1.getAge()-o2.getAge();
//            }
//        });
        //使用lambda表达式简化
        Arrays.sort(array,(Person o1, Person o2)->{
            return o1.getAge()- o2.getAge();
        });
        for (Person p:array){
            System.out.println(p);
        }
    }
}

省略lambda表达式

可以省略的内容:

  • (参数列表):括号中参数列表的数据类型,可以省略不写

  • (参数列表):括号中的参数如果只有一个,那么类型和 ( ) 都可以省略

  • {一些代码}:如果 { } 中的代码只有一行,无论是否有返回值,都可以省略( {} , return,分号)

    • 注意:要省略{},return,分号必须一起省略

4.8、File类

java把电脑中的文件和文件夹(目录)封装为了一个File类,我们可以使用File类对文件和文件夹进行操作

我们可以使用FiLe类的方法

  • 创建一个文件/文件夹

  • 删除文件/文件夹

  • 获取文件/文件夹

  • 判断文件/文件夹是否存在

  • 对文件夹进行遍历

  • 获取文件的大小

FiLe类是一个与系统无关的类,任何的操作系统都可以使用这个类中的方法

相对路径和绝对路径

绝对路径:是一个完整的路径(以盘符(C :, D:)开始的路径)

相对路径:是一个简化的路径(相对指的是相对于当前项目的根目录(C :\Userslitcast\IdeaProjects \shungyuan)

注意:

  • 路径是不区分大小写
  • 路径中的文件名称分隔符windows使用反斜杠,反斜杠是转义字符,两个反斜杠代表一个普通的反斜杠

常用方法

  • public string getAbsolutePath():返回此File的绝对路径名字符串。

  • public string getPath():将此File转换为路径名字符串。

  • public string getName():返回由此File表示的文件或目录的名称。

  • public long length():返回由此File表示的文件的长度。

判断方法

  • public boolean exists( ) :此File表示的文件或目录是否实际存在。

  • public boolean isDirectory() :此FiLe表示的是否为目录。

  • public booLean isFile() :此File表示的是否为文件。

删除方法

  • public boolean createNewFile():当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。

    • 当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。创建文件的路径和名称在构造方法中给出(构造方法的参数)
  • public booLean delete() :删除由此File表示的文件或目录。

    • 此方法,可以删除构造方法路径中给出的文件/文件夹,文件/文件夹删除成功,返回true;文件夹中有内容,不会删除返回false;构造方法中路径不存在false
  • public boolean mkdir() :创建由此FiLe表示的目录。

    • 创建单级空文件夹
  • public boolean mkdirs():创建由此File表示的目录,包括任何必需但不存在的父目录。

    • 既可以创建单级空文件夹,也可以创建多级文件夹

file类遍历

  • public String[] list(): 返回一个string数组,表示该File目录中的所有子文件或目录。

  • public File[ ] listFiles(): 返回一个File数组,表示该File目录中的所有的子文件或目录。

注意:

  • List方法和ListFiles方法遍历的是构造方法中给出的目录
  • 如果构造方法中给出的目录的路径不存在,会抛空指针异常
  • 如果构造方法中给出的路径不是一个自录,也会抛出空指针异常

FileFilter过滤器

在File类中有两个和ListFiLes重载的方法,方法的参数传递的就是过滤器

  • java.io.FileFilter接口:用于抽象路径名(File对象)的过滤器。
    • 作用:用来过滤文件(FiLe对象)
    • boolean accept(File pathname)测试指定抽象路径名是否应该包含在某个路径名列表中。
    • FiLe pathname:使用ListFiles方法遍历目录,得到的每一个文件对象
  • java.io.FilenameFiLter接口:实现此接口的类实例可用于过滤器文件名。
    • 作用:用于过滤文件名称
    • boolean accept(File dir,String name)测试指定文件是否应该包含在某一文件列表中。
    • File dir:构造方法中传递的被遍历的目录
    • String name:使用ListFiles方法遍历自录,获取的每一个文件/文件夹的名称

注意

两个过滤器接口是没有实现类的,需要我们自己写实现类,重写过滤的方法accept,在方法中自己定义过滤的规则

public class FileFilterImpl implements FileFilter {
    @Override
    public boolean accept(File pathname) {
        if (pathname.isDirectory()){
            return true;
        }
        return pathname.getName().toLowerCase().endsWith(".exe");
    }
}
public class DemoFile02 {
    public static void main(String[] args) {
        File file = new File("D:\\向日葵\\SunloginClient");
        getAllFile(file);
    }
//定义一个方法,参数传运FiLe类型的目录方法中对目录进行遍历
    private static void getAllFile(File dir) {
        File[] files = dir.listFiles(new FileFilterImpl());
        for (File f: files){
            if (f.isDirectory()){   //对遍历得到的FiLe对象f进行判断,判断是否是文件夹
                getAllFile(f);
            }else {
                System.out.println(f);  //f是一个文件打印即可
            }
        }
    }
}

4.9、递归

  • 递归:指在当前方法内调用自己的这种现象。

  • 递归的分类:(直接递归和间接递归)

    • 直接递归称为方法自身调用自己。
    • 间接递归可以A方法调用B方法,B方法调用C方法,C方法调用A方法。
  • 递归的使用前提:

    • 当调用方法的时候,方法的主体不变,每次调用方法的参数不同,可以使用递归

计算 1~n的合

public class Demo01 {
    public static void main(String[] args) {
        int s = sum(3);
        System.out.println(s);
    }

    private static int sum(int n) {
        if (n==1){
            return 1;
        }
        return n+sum(n-1);
    }
}

5.0、IO流

字节输出流OutputStream

定义了一些子类共性的成员方法:

  • public void close(): 关闭此涂出渣并释放与此渣相关联的任何系统资源。
  • public void flush( ): 刷新此输出凌并强制任何缓冲的输出字节被写出。

  • public void write(byte[] b): 将b.length字节从指定的字节数组写入此输出流。

  • public void write(byte[ ] b,int off , int len):从指定的字节数组写入leni字节,从偏移量off开始输丝到此I出渣。

  • public obstract void write(int b) :将指定的字节输出流。

字节输出流的使用步骤(重点):

1、创建一个FileoutputStream对象,构造方法中传递写入数据的目的地

2、调用FileoutputStream对象中的方法write ,把数据写入到文件中

3、释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提供程序的效率)

public class DemoOutputStream {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("F:\\练习\\1.txt");
        fos.write(97);
        fos.close();
    }
}

一次写多个字节:

  • 如果写的第一个字节是正数(0-127),那么显示的时候会查询AsCII表

  • 如果写的第一个字节是负数,那第一个字节会和第二个字节,两个字节组成一个中文显示,查询系统默认码表(GBK)

public class Demo02OutputStream {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream(new File("F:\\练习\\2.txt"));
        fos.write(49);
        fos.write(48);
        fos.write(48);

        byte[] bytes={65,66,67,68,69};  //ABCDE
        //byte[] bytes={-65,-66,-67,68,69};
        fos.write(bytes);

        fos.write(bytes,1,2);//BC

        //写入字符的方法:可以使用String类中的方法把字符串,转换为字节数组
        byte[] bytes1="你好".getBytes();
        System.out.println(Arrays.toString(bytes1));
        fos.write(bytes1);//100ABCDBC你好

        fos.close();
    }
}

追加写/续写:使用两个参数的构造方法

  • FileOutputStream(String name, boolean append) 创建一个向具有指定name的文件中写入数据的文件输出流
  • FileOutputStream(File file, boolean append)创建一个向指定file对象表示的文件中写入数据的文件输出流

true 创建对象不会覆盖文件,继续在文件的末尾追加数据

false 创建一个新文件,覆盖源文件

public class Demo03OutputStream {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("F:\\练习\\3.txt", true);
        fos.write("你好".getBytes());
        fos.close();
    }
}

换行

Windows:\r\n

Linux: /n

mac: /r

public class Demo03OutputStream {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("F:\\练习\\4.txt", true);
        for (int i = 1; i < 10; i++) {
            fos.write("你好".getBytes());
            fos.write("\r\n".getBytes());
        }
        fos.close();
    }
}

字节输入流InputStream

定义了所有子类共性的方法:

  • int read( ) 从输入流中读取数据的下一个字节。
  • int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中。
  • void close( ) 关闭此输入流并释放与该流关联的所有系统资源。

构造方法:

  • FileInputStream( String name)

  • FileInputstream(File file)

参数:读取文件的数据源

  • String name:文件的路径

  • File file:文件

字节输入流的使用步骤(重点):

1、创建FileInputStream对象,构造方法中绑定要读取的数据源

2、使用FileInputStream对象中的方法read,读取文件

3、释放资源

public class DemoInputStream {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("F:\\练习\\1.txt");
        //int read()读取文件中的一个字节并返回,读取到文件的末尾返回-1
        int i = fis.read();
        System.out.println(i);
        //释放资源
        fis.close();
    }
}
public class DemoInputStream {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("F:\\练习\\2.txt");
        int i = 0;
        while ((i= fis.read())!=-1){
            System.out.println((char) i);
        }
        //释放资源
        fis.close();
    }
}

字节输入流一次读取多个字节的方法:

  • int read(byte[] b)从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b中。

明确两件事情:

1、方法的参数byte[] 的作用?

2、方法的返回值int是什么?

String类的构造方法

  • string( byte[] bytes): 把字节数组转换为字符串

  • String(byte[ ] bytes, int offset,int length)把字节数组的一部分转换为字符串 offset:数组的开始索引Length :转换的字节个数

public class DemoInputStream {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("F:\\练习\\2.txt");//100ABCDE
        byte[] bytes = new byte[2];
        int len = fis.read(bytes);
        System.out.println(len);//2
        System.out.println(Arrays.toString(bytes));//[49,48]
        System.out.println(new String(bytes));//10
        fis.close();
    }
}
public class DemoInputStream {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("F:\\练习\\2.txt");//100ABCDEBC你好
        byte[] bytes = new byte[1024];//存储读取到的多个字节
        int len = 0;//记录每次读取的有效字节个数
        while ((len= fis.read(bytes))!=-1){
            System.out.println(new String(bytes,0,len));//100ABCDEBC你好
        }
        fis.close();
    }
}

文件复制

文件复制:一读一写

文件复制的步望:
1、创建一个字节输入流对象,构造方法中绑定要读取的数据源

2、创建一个字节输出流对象,构造方法中绑定要写入的目的地

3、使用字节输入流对象中的方法read读权文件

4、使用字节输出流中的方法write,把读取到的字节写入到目的地的文件中

5、释放资源

public class DemoCopyFile {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("F:\\练习\\1.png");
        FileOutputStream fos = new FileOutputStream("D:\\练习\\1.png");
        int len = 0;//一次读取一个字节写入一个字节的方式
        while ((len=fis.read())!=-1){
            fos.write(len);
        }
        fos.close();//释放资源(先关写的,后关读的;如果写完了,肯定读取完毕了)
        fis.close();
    }
}
public class DemoCopyFile {
    public static void main(String[] args) throws IOException {
        long s = System.currentTimeMillis();
        FileInputStream fis = new FileInputStream("F:\\练习\\1.png");
        FileOutputStream fos = new FileOutputStream("D:\\练习\\1.png");
        byte[] bytes = new byte[1024];//使用数组缓冲读取多个字节,写入多个字节
        int len = 0;//一次读取一个字节写入一个字节的方式
        while ((len=fis.read(bytes))!=-1){
            fos.write(bytes,0,len);
        }
        fos.close();//释放资源(先关写的,后关读的;如果写完了,肯定读取完毕了)
        fis.close();
        long e = System.currentTimeMillis();
        System.out.println("文件复制共耗时"+(e-s)+"毫秒");//文件复制共耗时3毫秒
    }
}

文件字符输入流FileReader

构造方法:

  • FileReader(String fileName )

  • FileReader( File file)

参数:读取文件的数据源

  • String fileName :文件的路径

  • File file:—个文件

字符输入流的使用步骤;

1、创建FileReader对象,构选方法中绑定要读取的数据源

2、使用FileReader对象中的方法read读取文件

3、释放资源

public class DemoReader {
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("F:\\练习\\2.txt");
        int len = 0;
        while ((len= fr.read())!=-1){
            System.out.println((char) len);
        }
        fr.close();
    }
}
public class DemoReader {
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("F:\\练习\\2.txt");
        char[] cs = new char[1024];
        int len = 0;
        while ((len= fr.read(cs))!=-1){
            System.out.println(new String(cs,0,len));
        }
        fr.close();
    }
}

文件字符输出流FileWriter

构造方法:

  • FiLewriter(File file) 根据给定的FiLe 对象构造一个Filewriter对象。

  • FiLewriter(String fileName)根据给定的文件名构造一个Filewriter 对象。

参数:写入数据的目的地

  • string fiLeName:文件的路径

  • File file:是一个文件

字符输出流的使用步骤(重点):

1、创建FiLelwriter对象,构造方法中绑定要写入数据的目的地

2、使用Filewriter中的方法vrite,把数据写入到内存缓冲区中(字符转换为字节的过程)

3、使用Filelwriter中的方法flush,把内存缓冲区中的数据,刷新到文件中

4、释放资源(会先把内存缓冲区中的数据刷新到文件中)

public class DemoWriter {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("F:\\练习\\5.txt");
        fw.write(97);//使用FileWriter中的方法write ,把数据写入到内存缓冲区中(字符转换为字节的过程)
        fw.flush();//刷新之后流可以继续使用
        fw.close();//释放资源(会先把内存缓冲区中的数据刷新到文件中)
    }
}
追加和续写
  • Filewriter(Strinig fiLeName , boolear append )

  • FiLeMriter(File file,boolean append )

参数:

  • String fileName , File file:写入数据的目的地

  • boolean append :续写开关 true;不会创建新的文件覆盖源文件,可以续写;false :创建新的文件覆盖源文件

换行:换行符号

Windows:\r\n

linux: /n

mac: /r

public class DemoWriter {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("F:\\练习\\7.txt",true);
        for (int i = 0; i < 10; i++) {
            fw.write("helloworld"+i+"\r\n");
        }
        fw.close();
    }
}