Java提高与实践

IO流

IO流概述

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 文件字节输入流:每次读取一个字节
package fileStream;

import java.io.*;

public class HelloFileInputStream {
    public static void main(String[] args) throws IOException {
        //创建文件字节输入流 管道,与源文件接通
        //写法一
        //InputStream is = new FileInputStream(new File("IO\\src\\fileTest.txt"));
        //写法二
        InputStream is = new FileInputStream(("IO\\src\\fileTest.txt"));//文件内容abdc

        //开始读取文件的字节数据
        //int read()每次读取一个字节返回,若无则返回-1
//        int b1 = is.read();
//        System.out.println((char)b1);//a
//        int b2 = is.read(), b3 = is.read(), b4 = is.read(), b5 = is.read();
//        System.out.println((char)b2 +", " +  (char)b3 +", " +  (char)b4);//b, d, c
//        System.out.println(b5);//-1

        //从磁盘中读数据,读取性能很差
        //读取汉字输出会乱码(汉字是多字节存储,而该方法每次只读取一字节)

        //借助循环读取文件内容
        int b;
        while((b = is.read()) != -1){//abdc
            System.out.print((char)b);
        }

        //流使用完毕后,必须关闭!释放系统资源
        is.close();
    }
}
  • 文件 字节输入流:每次读取多个字节
package fileStream;

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

public class FileInputStream1 {
    public static void main(String[] args) throws IOException {
        InputStream is = new FileInputStream(("IO\\src\\fileTest.txt"));
        byte[] buffer = new byte[3];
        //int read(byte[] b)每次读取多个字节到字节数组中,返回读取的字节量,读取完毕则返回-1
        int len = is.read(buffer);
        String s = new String(buffer);
        System.out.println(s);//abd
        System.out.println("本次读取数据的字节量" + len);//3

//        int len1 = is.read(buffer);
//        String s1 = new String(buffer);
//        System.out.println(s1);//cbd 注意:读取多少,就倒出多少
//        System.out.println(len1);//1
        int len1 = is.read(buffer);
        String s1 = new String(buffer, 0, len1);
        System.out.println(s1);//c
        System.out.println(len1);//1

        int len2 = is.read(buffer);
        System.out.println(len2);//-1
        is.close();
    }
}

package fileStream;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class FileInputStream2 {
    public static void main(String[] args) throws IOException {
        InputStream is = new FileInputStream(("IO\\src\\fileTest1.txt"));//我爱你abca我爱你
        byte[] buffer = new byte[3];
        int len;
        //该方法性能有一定提升,但仍无法解决汉字乱码问题
        while((len = is.read(buffer)) != -1){//我爱你abca������
            String s = new String(buffer, 0, len);
            System.out.print(s);
        }
        is.close();
    }
}

  • 文件字节输入流:一次读取全部字节流
    在这里插入图片描述
    在这里插入图片描述
package fileStream;

import java.io.*;

public class FileInputStream3 {
    public static void main(String[] args) throws IOException {
        InputStream is = new FileInputStream(("IO\\src\\fileTest1.txt"));
        File tFile = new File("IO\\src\\fileTest1.txt");
        long size = tFile.length();
        byte[] buffer = new byte[(int) size];
        String s = new String(buffer);
        int len = is.read(buffer);
        System.out.println(s);//
        System.out.println(new String(buffer));//我爱你abca我爱你
        System.out.println(len);//22
        System.out.println(s.length());//22
    }
}

package fileStream;

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

public class FileInputStream4 {
    public static void main(String[] args) throws IOException {
        InputStream is = new FileInputStream(("IO\\src\\fileTest1.txt"));
        byte[] buffer = is.readAllBytes();
        System.out.println(new String(buffer));//我爱你abca我爱你
        is.close();
    }
}

  • 文件字节输出流:写字节出去
    在这里插入图片描述
    在这里插入图片描述
package fileStream;

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

public class FileOutputStream1 {
    public static void main(String[] args) throws IOException {
        //创建一个字节输出流管道和文件接通
        //覆盖管道:覆盖之前的数据内容
        OutputStream os = new FileOutputStream("IO\\src\\fileTest2.txt");
        os.write(97);
        os.write('b');
        //os.write('中');默认只能写出去一个字节
        byte[] bytes = "永远不要挨饿".getBytes();
        os.write(bytes);
        os.write(bytes, 0, 6);
        os.close();
    }
}

在这里插入图片描述

package fileStream;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class FileOutputStream2 {
    public static void main(String[] args) throws IOException {
        OutputStream os = new FileOutputStream("IO\\src\\fileTest2.txt", true);
        os.write("\n冲冲冲".getBytes());
        os.close();
    }
}

在这里插入图片描述

  • 文件复制
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

package fileStream;

import java.io.*;

public class CopyFile {
    public static void main(String[] args) throws IOException {
        InputStream is = new FileInputStream("IO\\src\\dir\\aa\\fileTest.txt");
        OutputStream os = new FileOutputStream("IO\\src\\dir\\bb\\fileCopy.txt");
        byte[] buffer = new byte[1024];//一般大小为1kb
        int len;
        while((len = is.read(buffer)) != -1){
            os.write(buffer, 0, len);
        }
        os.close();//流:后创建,先关闭
        is.close();
    }
}

在这里插入图片描述

释放资源
  • try-catch-finally
    在这里插入图片描述
package fileResource;

public class Finally {
    public static void main(String[] args) {
        try{
            System.out.println(10/0);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        finally代码区:无论try中程序是正常执行还是出现异常,都会执行finally区,除非JVM终止
        //作用:一般用于在程序执行完成后进行资源的释放操作(专业级操作)
        finally{
            System.out.println("finally did");
            System.out.println(divide(10, 2));//-1 结果异常==>建议遵循单一出口原则
        }
    }

    public static int divide(int a, int b){
        try{
            return a / b;
        }
        catch(Exception e){
            e.printStackTrace();
        }
        finally{
            return -1;
        }
    }
}

package fileStream;

import java.io.*;

public class CopyFile {
    public static void main(String[] args) throws IOException {
        InputStream is = null;
        OutputStream os= null;
        try {
            is = new FileInputStream("IO\\src\\dir\\aa\\fileTest.txt");
            os = new FileOutputStream("IO\\src\\dir\\bb\\fileCopy.txt");
            byte[] buffer = new byte[1024];//一般大小为1kb
            int len;
            while((len = is.read(buffer)) != -1){
                os.write(buffer, 0, len);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if(os != null) os.close();//流:后创建,先关闭
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            try {
                if(is != null) is.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

  • try-with-resource
    在这里插入图片描述
package fileStream;

import java.io.*;

public class CopyFile1 {
    public static void main(String[] args) throws IOException {
        try(
            //只能放资源对象(流对象)(资源对象都会实现AutoCloseable接口)
            //AutoCloseable接口有close()方法,故每个资源都会有一个close()方法,用完后进行自动调用
            InputStream is = new FileInputStream("IO\\src\\dir\\aa\\fileTest.txt");
            OutputStream os = new FileOutputStream("IO\\src\\dir\\bb\\fileCopy.txt");
            MyConllection con = new MyConllection();
            ){
            byte[] buffer = new byte[1024];//一般大小为1kb
            int len;
            while((len = is.read(buffer)) != -1){
                os.write(buffer, 0, len);
            }
            System.out.println(con);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

package fileStream;

public class MyConllection implements AutoCloseable{

    @Override
    public void close() throws Exception {
        System.out.println("释放了和某硬件连接的资源~");
    }
}

字符流
  • 文件字符输入流
    在这里插入图片描述
    在这里插入图片描述
package file;

import java.io.FileReader;
import java.io.Reader;

public class HelloFileReader {
    public static void main(String[] args) {
        try(
                Reader fr = new FileReader("IO\\src\\fileTest.txt");
                ){
            int count;
            //每次只读一个字符,性能较差
            while((count = fr.read()) != -1){
                System.out.print((char)count);
            }
        }catch(Exception e){
            e.printStackTrace();
        }

    }
}

package file;

import java.io.FileReader;
import java.io.Reader;

public class HelloFileReader1 {
    public static void main(String[] args) {
        try(
                Reader fr = new FileReader("IO\\src\\fileTest.txt");
                ){
            char[] buffer = new char[3];
            int count;
            while((count = fr.read(buffer)) != -1){
                //System.out.println(new  String(buffer, 0, count));
                System.out.print(new String(buffer, 0, count));
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

  • 文件字符输出流
    在这里插入图片描述
    在这里插入图片描述
package file;

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

public class HelloFileWriter {
    public static void main(String[] args) {
        try(
                //覆盖管道
                Writer fw = new FileWriter("IO\\src\\fileTest3.txt")
                ) {
            fw.write(97);
            fw.write('b');
            fw.write('中');
            fw.write("我是字符串");
            fw.write("\n");
            fw.write("\r\n");//换行
            char[] arr = {'我', '是', '字', 'f', 'u'};
            fw.write(arr, 0, arr.length);
            fw.write("\r\n");
            fw.write(arr, 0, 2);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

package file;

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

public class HelloWrite {
    public static void main(String[] args) {
        try(
                //追加管道
                Writer fw = new FileWriter("IO\\src\\fileTest3.txt", true) ;
                ){
            fw.write("\r\n我是追加内容");
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

在这里插入图片描述

缓冲区已满时,会自动刷新和写入数据

fw.flush();//刷新流(关闭流中包含刷新流)
缓冲流

在这里插入图片描述

  • 字节缓冲流
    在这里插入图片描述
    在这里插入图片描述
package buffer;

import java.io.*;

public class HelloBufferedInputStream {
    public static void main(String[] args){
        try(
                InputStream is = new FileInputStream("IO\\src\\fileTest.txt");
                InputStream bis = new BufferedInputStream(is);
                OutputStream os = new FileOutputStream("IO\\src\\fileTest1.txt");
                OutputStream bos = new BufferedOutputStream(os);
                ){
            byte[] buffer = new byte[1024];
            int len;
            while((len = bis.read(buffer)) != -1){
                bos.write(buffer, 0, len);
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

  • 字符缓冲流
    在这里插入图片描述
    在这里插入图片描述
package buffer;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.Reader;

public class HelloBufferedReader {
    public static void main(String[] args){
        try(
                Reader r = new FileReader("IO\\src\\fileTest.txt");
                BufferedReader br = new BufferedReader(r);
                ){
            char[] buffer = new char[3];
            int len;
            while((len = br.read(buffer)) != -1){
                System.out.print(new String(buffer, 0,len));
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

package buffer;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.Reader;

public class HelloBufferedReader1 {
    public static void main(String[] args){
        try(
                Reader r = new FileReader("IO\\src\\fileTest.txt");
                BufferedReader br = new BufferedReader(r);
                ){
            String line;//记住每次读取的一行数据
            while((line = br.readLine()) != null){
                System.out.println(line);
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

package buffer;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.Writer;

public class HelloBufferedWriter {
    public static void main(String[] args){
        try(
                Writer w = new FileWriter("IO\\src\\dir\\fileTestW.txt");
                BufferedWriter bw = new BufferedWriter(w);
                ){
            bw.write(97);
            bw.write('b');
            bw.write('中');
            bw.newLine();//换行
            bw.write("我是字符串吖");
        }catch(Exception e){
			e.printStackTrace();
        }
    }

}

在这里插入图片描述

简单应用:拷贝文件内容到另一个文件,并对内容排序

在这里插入图片描述
在这里插入图片描述

package buffer;

import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Apply {
    public static void main(String[] args){
        try(
                Writer w = new FileWriter("IO\\src\\dir\\fileTestCopy.txt");
                BufferedWriter bw  = new BufferedWriter(w);
                Reader r = new FileReader("IO\\src\\dir\\fileTestW.txt");
                BufferedReader br = new BufferedReader(r);
                ){
            List<String> list = new ArrayList<>();
            String line;
            while((line = br.readLine()) != null){
                list.add(new String(line));
            }
            list.sort(((o1, o2) -> o1.compareTo(o2)));
            //System.out.println(list);[1静夜思⑴, 2床前明月光⑵,, 3疑是地上霜⑶。, 4举头望明月⑷,, 5低头思故乡]
            for(String s : list){
                bw.write(s);
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

package buffer;

import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class Apply1 {
    public static void main(String[] args){
        try(
            BufferedWriter bw  = new BufferedWriter(new FileWriter("IO\\src\\dir\\fileTestCopy.txt"));
            BufferedReader br = new BufferedReader(new FileReader("IO\\src\\dir\\fileTestW.txt"));
        ){
            List<String> list = new ArrayList<>();
            String line;
            while((line = br.readLine()) != null){
                list.add(new String(line));
            }
            Collections.sort(list);
            //System.out.println(list);[1静夜思⑴, 2床前明月光⑵,, 3疑是地上霜⑶。, 4举头望明月⑷,, 5低头思故乡]
            for(String s : list){
                bw.write(s);
                bw.newLine();
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

原始流和缓冲流的性能分析

在这里插入图片描述
在一定范围内,内存越大越好;
到达极限后,内存已经最优化之后再增加也不会有效提高速度
在这里插入图片描述

转换流

在这里插入图片描述
在这里插入图片描述

  • 字符输入转换流
    在这里插入图片描述
package transform;

import java.io.*;

public class HeyInputStreamReader {
    public static void main(String[] args){
        try(
                Reader isr = new InputStreamReader(new FileInputStream("IO\\src\\dir\\fileTestW.txt"), "GBK");
                BufferedReader bs = new BufferedReader(isr);
                ){
            String line;
            while((line = bs.readLine()) != null){
                System.out.println(line);
            }
        }catch(Exception e){

        }
    }
}

  • 字符输出转换流
    在这里插入图片描述
package transform;

import java.io.*;

public class HeyOutputStreamWriter {
    public static void main(String[] args){
        try(
                Writer w = new OutputStreamWriter(new FileOutputStream("IO\\src\\dir\\fileTestTrans.txt"), "GBK");
                BufferedWriter bw = new BufferedWriter(w);
                ){
            bw.write("I am English123");
            bw.write("我是中文456");
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

打印流

在这里插入图片描述
在这里插入图片描述

package printStream;

import java.io.PrintStream;
import java.nio.charset.Charset;

public class HelloPrintStream {
    public static void main(String[] args){
        try(
                PrintStream ps = new PrintStream("IO\\src\\dir\\filePrint.txt", Charset.forName("GBK"));
                ){
            ps.println(97);
            ps.write(97);
            ps.println('b');
            ps.println('中');
            ps.println("我是中English123");
            ps.println(100.9);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

在这里插入图片描述
在这里插入图片描述

package printStream;

import java.io.PrintStream;
import java.io.PrintWriter;
import java.nio.charset.Charset;

public class HelloPrintWriter {
    public static void main(String[] args){
        try(
                PrintWriter ps = new PrintWriter("IO\\src\\dir\\filePrint1.txt", Charset.forName("GBK"));
        ){
            ps.println(97);
            ps.write(97);
            ps.println('b');
            ps.println('中');
            ps.println("我是中English123");
            ps.println(100.9);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

package printStream;

import java.io.FileOutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.nio.charset.Charset;

public class HelloPrintWriter {
    public static void main(String[] args){
        try(//追加数据需要借助低级流实现
                PrintWriter ps = new PrintWriter(new FileOutputStream("IO\\src\\dir\\filePrint1.txt", true));
        ){
            ps.println(97);
            ps.write(97);
            ps.println('b');
            ps.println('中');
            ps.println("我是中English123");
            ps.println(100.9);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

在这里插入图片描述
在这里插入图片描述

打印流的应用:输出语句的重定向

在这里插入图片描述

package printStream;

import java.io.PrintStream;

public class Apply {
    public static void main(String[] args) {
        System.out.println("生如夏花");
        try(
                PrintStream ps = new PrintStream("IO\\src\\dir\\filePrint2.txt");
                ){
            System.setOut(ps);
            System.out.println("直挂云帆济沧海");
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

数据流

在这里插入图片描述
在这里插入图片描述

package dataStream;

import java.io.DataOutputStream;
import java.io.FileOutputStream;

public class HeyDataOutputStream {
    public static void main(String[] args){
        try(DataOutputStream dos = new DataOutputStream(new FileOutputStream("IO\\src\\dir\\dataStreamW.txt"));){
            dos.writeInt(97);
            dos.writeBoolean(true);
            dos.writeUTF("字符串");
            dos.writeDouble(100.1);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

下图文件内容可理解为一种特殊的存法
在这里插入图片描述

在这里插入图片描述

package dataStream;

import java.io.DataInputStream;
import java.io.FileInputStream;

public class HeyDataInputStream {
    public static void main(String[] args){
        try(DataInputStream dis = new DataInputStream(new FileInputStream("IO\\src\\dir\\dataStreamW.txt"))){
            System.out.println(dis.readInt());//97
            System.out.println(dis.readBoolean());//true
            System.out.println(dis.readUTF());//字符串
            System.out.println(dis.readDouble());//100.1
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

序列化流
  • 对象序列化:把Java对象写入到文件中去
  • 对象反序列化:把文件里的Java对象读出来
    在这里插入图片描述
    在这里插入图片描述
package objectStream;

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;

public class HeyObjectOutputStream {
    public static void main(String[] args){
        try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("IO\\src\\dir\\objectStream.txt"))){
            Student s = new Student("刘亦菲", 26, 100.1);
            oos.writeObject(s);
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

package objectStream;

import java.io.Serializable;

public class Student implements Serializable {
    private String name;
    private int age;
    private double score;

    public Student() {
    }

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

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

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

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

在这里插入图片描述

在这里插入图片描述

package objectStream;

import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class HeyObjectInputStream {
    public static void main(String[] args){
        try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream("IO/src/dir/objectStream.txt"))){
//            Student s = (Student) ois.readObject();
//            System.out.println(s);//Student{name='刘亦菲', age=26, score=100.1}
            System.out.println(ois.readObject());//Student{name='刘亦菲', age=26, score=100.1}
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

 //transient修饰后,表示该成员变量不参与序列化
    private transient double score;

在这里插入图片描述

在这里插入图片描述

IO框架

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

commons_IO下载地址
下载版本为:
在这里插入图片描述

package commonsIO;

import org.apache.commons.io.FileUtils;

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

public class Test {
    public static void main(String[] args) throws IOException {
        //复制文件
        FileUtils.copyFile(new File("IO/src/dir/fileTestCopy.txt"), new File("IO/src/dir/helloCommons.txt"));
        //复制文件夹
        FileUtils.copyDirectory(new File("IO/src/dir/aa"), new File("IO/src/dir/cc"));
        //删除文件夹(可直接删除非空文件夹)
        FileUtils.deleteDirectory(new File("IO/src/dir/aa"));
    }
}

package commonsIO;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public class TestJavaself {
    public static void main(String[] args) throws IOException {
        //Java提供的高效原生代码
        Files.copy(Path.of("IO/src/dir/bb/fileCopy.txt"), Path.of("IO/src/dir/cc/fileCopyC.txt"));
        System.out.println(Files.readString(Path.of("IO/src/dir/cc/fileTest.txt")));
    }
}

特殊文件

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

properties属性文件

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package specialFile;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;

public class HelloProperties {
    public static void main(String[] args) throws IOException {
        //创建Properties对象(键值对集合的空容器)
        Properties p = new Properties();
        System.out.println(p);

        //加载属性文件中的键值对信息到Properties对象中
        p.load(new FileReader("IO\\src\\users.properties"));
        System.out.println(p);

        //根据键 取值
        System.out.println(p.getProperty("summer"));
        System.out.println(p.getProperty("rick"));

        //遍历全部的键和值
        Set<String> users = p.stringPropertyNames();
        for(String s : users){
            String value = p.getProperty(s);
            System.out.println(s + ":" + value);
        }

        System.out.println();
        p.forEach((k, v) -> System.out.println(k + ":" + v));
    }
}

在这里插入图片描述

package specialFile;

import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

public class Properties1 {
    public static void main(String[] args) throws IOException {
        Properties p = new Properties();
        p.setProperty("jerry", "5555");
        p.setProperty("morty", "6666");
        //覆盖式存入
        p.store(new FileWriter("IO/src/users.properties"), "save more users");
    }
}

简单应用:在这里插入图片描述

package specialFile;

import java.io.*;
import java.util.Properties;

public class Apply {
    public static void main(String[] args) throws IOException {
        Properties p = new Properties();
        p.load(new FileReader("IO\\src\\users.properties"));

        if(p.containsKey("jerry")){
            p.setProperty("jerry", "6666");
        }
        
        p.store(new FileWriter("IO/src/users.properties"), "modify jerry password");
    }
}

XML文件

在这里插入图片描述
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!-- 上面是抬头声明,必须有且需要放在第一行 -->
<!--根标签只能有一个-->
<users>
    <user>
        <name>斯嘉丽</name>
        <score>105</score>
        <special>1 &lt; 3 &amp;&amp; 2 &gt;0</special>
        <中文>可以吗</中文>
    </user>
    <user>
        <name>梅兰</name>
        <score>100</score>
        <special>&quot;</special>
        <中文>可以的</中文>
    </user>
</users>


在这里插入图片描述

在这里插入图片描述

解析XML文件

在这里插入图片描述

dom4j下载地址(下载首个jar包即可,若想了解源码则下载第二个source,若想了解使用说明则下载第三个)
在这里插入图片描述

在idea中可以展开jar包即为导入成功
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

package dom4jTest;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import javax.xml.parsers.SAXParser;
import java.util.Arrays;
import java.util.List;

public class HelloSAX {
    public static void main(String[] args) throws DocumentException {
        //创建一个dom4j框架提供的解析器对象
        SAXReader saxReader = new SAXReader();

        //使用SAXReader对象把要解析的XMl文件读成一个document对象
        Document document = saxReader.read("IO\\src\\helloWorld.xml");

        //从Document对象中读取XML中的全部数据元素
        Element root = document.getRootElement();
        System.out.println(root.getName());//users

        //List<Element> elements()获取当前元素下的所有子元素
        List<Element> elements = root.elements();
        for (Element element : elements) {
            System.out.println(element.getName());
        }

        System.out.println();
        //List<Element> elements(String name)获取当前元素下 指定名字的子元素集合
        List<Element> elements1 = root.elements("user");
        elements1.forEach(o1 -> System.out.println(o1.getName()));

        //Element element(String name)获取当前元素下指定名字的子元素,若有重复则返回首次出现的
        //String getText()得到文本内容
        Element element = root.element("visitor");
        System.out.println(element.getText());//会话访问

        //String attributeValues(String name)通过属性名直接获得属性值
        System.out.println(root.attributeValue("num"));//4
    }
}

XML文件的生成

在这里插入图片描述

package xml;

import java.io.BufferedWriter;
import java.io.FileWriter;

public class WriteIn {
    public static void main(String[] args){
        //使用StringBuilder对象来拼接XML格式的数据
        StringBuilder sb = new StringBuilder();
        sb.append("<?xml version = \"1.0\" encoding = \"UTF-8\"?>\r\n");
        sb.append("<book>\r\n");
        sb.append("\t<id>1</id>\r\n");
        sb.append("\t<name>乱世佳人</name>\r\n");
        sb.append("</book>");

        try(
                BufferedWriter bw = new BufferedWriter(new FileWriter("IO\\src\\testW.xml"))
                ){
            bw.write(sb.toString());
        }catch(Exception e){
            e.printStackTrace();
        }
    }

}

在这里插入图片描述

约束XML文件的编写(简单了解)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

日志技术

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

体系结构

在这里插入图片描述
在这里插入图片描述

Logback

在这里插入图片描述

package log;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Scanner;

public class Hello {
    public static final Logger LOGGER = LoggerFactory.getLogger("logTest1");

    public static void main(String[] args) {
        try {
            LOGGER.info("程序开始执行~");
            Scanner sc = new Scanner(System.in);
            int m = sc.nextInt(), n = sc.nextInt();
            divide(m, n);
            LOGGER.info("程序成功执行完毕~");
        } catch (Exception e) {
            LOGGER.error("程序执行异常");
        }
    }
    public static void divide(int m, int n){
        LOGGER.debug("参数m:" + m);
        LOGGER.debug("参数n" + n);
        System.out.println(m / n);
        LOGGER.info("结果是" + m / n);
    }
}

在这里插入图片描述
在这里插入图片描述

logback核心配置文件

在这里插入图片描述
在这里插入图片描述

多线程

在这里插入图片描述

线程创建方式
创建方式1:继承Thread类

在这里插入图片描述
java是单继承的

package thread;

public class HelloThread {
    //main()方法由默认的主线程负责执行
    public static void main(String[] args) {
        //创建一个MyThread线程类对象代表一个线程
        Thread thread = new MyThread();
        thread.start();//启动线程,自动执行run()方法
        for (int i = 0; i < 7; i++) {
            System.out.println("主线程main输出" + i);
        }
    }
}

package thread;

public class MyThread extends Thread{//子类继承Thread线程类
    @Override
    public void run(){//需要重写Thread类的run()方法
        //描述线程的执行任务
        for (int i = 0; i < 7; i++) {
            System.out.println("子线程输出" + i);
        }
    }
}

在这里插入图片描述
在这里插入图片描述

创建方式2:实现Runnable接口

在这里插入图片描述

package thread;

public class HelloThread {
    //main()方法由默认的主线程负责执行
    public static void main(String[] args) {
        //创建任务对象
        MyRunnable myRunnable = new MyRunnable();
        new Thread(myRunnable).start();//把任务对象交给一个线程对象来处理
        for (int i = 0; i < 7; i++) {
            System.out.println("主线程main输出" + i);
        }
    }
}

package thread;

public class MyRunnable implements Runnable{

    @Override
    public void run() {
        //线程要执行的任务
        for (int i = 0; i < 7; i++) {
            System.out.println("子线程输出" + i);
        }
    }
}

在这里插入图片描述

package thread;

public class HelloThread {
    //main()方法由默认的主线程负责执行
    public static void main(String[] args) {
        //简化1:匿名内部类写法
        Runnable runnable1 = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 7; i++) {
                    System.out.println("子线程1输出" + i);
                }
            }
        };
        new Thread(runnable1).start();
        //简化版本2
        new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i = 0; i < 7; i++){
                    System.out.println("子线程2输出" + i);
                }
            }
        }).start();
        //简化版本3(Lambda表达式)
        new Thread(() ->
        {
            for (int i = 0; i < 7; i++) {
                System.out.println("子线程3输出" + i);
            }
        }).start();
        for (int i = 0; i < 7; i++) {
            System.out.println("主线程main输出" + i);
        }
    }
}

创建方式3:实现Callable接口

在这里插入图片描述
在这里插入图片描述

package thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class HelloThread {
    //main()方法由默认的主线程负责执行
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Callable<String> call = new MyCallable(10);//创建Callable对象
        //FutureTask对象 :一个任务对象,实现了Runnable接口;在线程执行完后,用get方法获取线程执行结果
        FutureTask<String> futureTask = new FutureTask<>(call);//把Callable对象封装为FutureTask对象
        //把任务对象交给一个Thread对象
        new Thread(futureTask).start();
        //获取线程执行完毕的结果
        System.out.println(futureTask.get());
    }
}

在这里插入图片描述

Thread常用方法

在这里插入图片描述

package thread;

public class HeyThread {
    public static void main(String[] args) {
        MyThread thread1 = new MyThread();
        thread1.start();
        //String getName()获取当前线程的名称,线程名默认是Thread-索引
        System.out.println(thread1.getName());//Thread-0

        MyThread thread2  = new MyThread();
        thread2.start();
        System.out.println(thread2.getName());//Thread-1

        MyThread thread3 = new MyThread();
        //void setName(String name)为线程设置名称
        thread3.setName("俺是三号");//俺是三号
        thread3.start();
        System.out.println(thread3.getName());
        Thread m = Thread.currentThread();
        System.out.println(m.getName());//main

        for(int i = 0; i < 7; i++){
            System.out.println(m.getName() + "输出了" + i);
        }
    }
}

package thread;

public class MyThread extends Thread{//子类继承Thread线程类
    @Override
    public void run(){//需要重写Thread类的run()方法
        Thread t = Thread.currentThread();
        //描述线程的执行任务
        for (int i = 0; i < 7; i++) {
            System.out.println(t.getName() + "子线程输出" + i);
        }
    }
}

在这里插入图片描述

package thread;

public class TestThread {
    public static void main(String[] args) throws InterruptedException {
        MyThread thread1 = new MyThread();
        thread1.start();
        //final void join()让调用该方法的线程先执行完(原理类似信号量机制)
        thread1.join();

        MyThread thread2 = new MyThread();
        thread2.start();
        thread2.join();

        MyThread thread3 = new MyThread();
        thread3.start();
        thread3.join();
    }
}

线程安全问题

在这里插入图片描述
在这里插入图片描述

线程同步

在这里插入图片描述
在这里插入图片描述

package thread;

public class Account {
    private String name;
    private double money;

    public void drawMoney(double draw){
        String name = Thread.currentThread().getName();
        if(this.money >= draw){
            System.out.println(name + "取款成功!");
            this.money -= draw;
            System.out.println("当前账户余额为" + this.money);
        }
        else System.out.println(name + "取款失败!");
    }

    public Account() {
    }

    public Account(String name, double money) {
        this.name = name;
        this.money = money;
    }

    public String getName() {
        return name;
    }

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

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }
}

package thread;

public class DrawThread extends Thread{
    private Account acc;

    public DrawThread(Account acc, String name){
        super(name);
        this.acc = acc;
    }

    @Override
    public void run() {
        acc.drawMoney(10000);
    }
}

package thread;

public class ThreadTest {
    public static void main(String[] args) {
        Account acc = new Account("Shared_account", 10000);
        new DrawThread(acc, "共同持有人1号").start();
        new DrawThread(acc, "共同持有人2号").start();
    }
}

在这里插入图片描述

方式一:同步代码块

在这里插入图片描述
在这里插入图片描述

 public void drawMoney(double draw){
        String name = Thread.currentThread().getName();
        synchronized (this) {
            if(this.money >= draw){
                System.out.println(name + "取款成功!");
                this.money -= draw;
                System.out.println("当前账户余额为" + this.money);
            }
            else System.out.println(name + "取款失败!");
        }
    }

在这里插入图片描述

方式二:同步方法

在这里插入图片描述
在这里插入图片描述

public synchronized void drawMoney(double draw){
        String name = Thread.currentThread().getName();
        if(this.money >= draw){
            System.out.println(name + "取款成功!");
            this.money -= draw;
            System.out.println("当前账户余额为" + this.money);
        }
        else System.out.println(name + "取款失败!");
    }

在这里插入图片描述

方式三:Lock锁

在这里插入图片描述

package thread;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Account {
    private String name;
    private double money;
    private final Lock lock = new ReentrantLock();

    public synchronized void drawMoney(double draw){
        String name = Thread.currentThread().getName();
        lock.lock();
        try {
            if(this.money >= draw){
                System.out.println(name + "取款成功!");
                this.money -= draw;
                System.out.println("当前账户余额为" + this.money);
            }
            else System.out.println(name + "取款失败!");
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }
    }

    public Account() {
    }

    public Account(String name, double money) {
        this.name = name;
        this.money = money;
    }

    public String getName() {
        return name;
    }

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

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }
}

线程通信(简单了解)

思想同OS中的进程通信问题
在这里插入图片描述

线程池
认识线程池

在这里插入图片描述
在这里插入图片描述

创建线程池

在这里插入图片描述

  • 方式一
    在这里插入图片描述
    在这里插入图片描述
线程池处理Runnable任务

在这里插入图片描述

  • 新任务拒绝错误
    • AbortPolicy:拒绝并抛出异常。
    • CallerRunsPolicy:使用当前调用的线程来执行此任务。
    • DiscardOldestPolicy:抛弃队列头部(最旧)的一个任务,并执行当前任务。
    • DiscardPolicy:忽略并抛弃当前任务。
package threadPool;

import java.util.concurrent.*;

public class Test {
    public static void main(String[] args) {
        ExecutorService pool = new ThreadPoolExecutor(3, 5,
                8, TimeUnit.SECONDS, new ArrayBlockingQueue<>(4)
                , Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

        Runnable target = new MyRunnable();
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);//三个核心线程被占
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);//任务队列共四个位置被占满
        pool.execute(target);//可创建临时线程(max-core)个
        pool.execute(target);

        pool.shutdown();//等全部线程执行完毕后,再关闭线程池
//        pool.shutdownNow();//直接关闭全部线程池,无论任务是否执行完毕
    }
}

package threadPool;

public class MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

线程池处理Callable任务

在这里插入图片描述

package threadPool;

import java.util.concurrent.Callable;

public class MyCallable implements Callable<String> {
    private int n;
    public MyCallable(){}
    public MyCallable(int n){
        this.n = n;
    }

    @Override
    public String call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= n; i++) {
            sum += i;
        }
        return Thread.currentThread().getName() + " test " + sum;
    }
}

package threadPool;

import java.util.concurrent.Callable;

public class MyCallable implements Callable<String> {
    private int n;
    public MyCallable(){}
    public MyCallable(int n){
        this.n = n;
    }

    @Override
    public String call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= n; i++) {
            sum += i;
        }
        return Thread.currentThread().getName() + " test " + sum;
    }
}

Executors工具类实现线程池

在这里插入图片描述
在这里插入图片描述

  • 关于核心线程数量的设置:
    • 计算密集型:CPU核数(逻辑上)+1
    • IO密集型:CPU核数(逻辑上)*2
并发vs并行

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

线程的生命周期

在这里插入图片描述
在这里插入图片描述

乐观锁
悲观锁
package lockThread;

public class MyRunnable implements  Runnable{
    private int count;//记录访问人数
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            synchronized (this) {
                System.out.println(Thread.currentThread().getName() + ":" + (++count));
            }
        }
    }
}

package lockThread;

public class PassiveLock {
    public static void main(String[] args) {
        Runnable target = new MyRunnable();

        for (int i = 0; i < 100; i++) {
            new Thread(target).start();
        }
    }
}

在这里插入图片描述

乐观锁
package lockThread;

public class Optimistic {
    public static void main(String[] args) {
        Runnable target = new MyRunnable1();

        for (int i = 0; i < 100; i++) {
            new Thread(target).start();
        }
    }
}

package lockThread;

import java.util.concurrent.atomic.AtomicInteger;

public class MyRunnable1 implements  Runnable{
    private AtomicInteger count = new AtomicInteger();//记录访问人数
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            synchronized (this) {
                System.out.println(Thread.currentThread().getName() + ":" + count.incrementAndGet());
            }
        }
    }
}

网络通信

网络通信三要素:IP地址、端口号、协议

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

IP地址

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package iNetAddress;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;

public class Test {
    public static void main(String[] args) throws IOException {
        InetAddress ip1 = InetAddress.getLocalHost();//获取本机IP
        System.out.println(ip1.getHostAddress());//获取该IP地址对象对应的IP地址
        System.out.println(ip1.getHostName());//获取该IP地址对象的主机名

        InetAddress ip2 = InetAddress.getByName("www.baidu.com");
        System.out.println(ip2.getHostAddress());
        System.out.println(ip2.getHostName());//www.baidu.com
        System.out.println(ip2.isReachable(5000));//true
    }
}

端口号

在这里插入图片描述

协议

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

UDP通信

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package UDP;

import java.io.IOException;
import java.net.*;

public class Client {
    public static void main(String[] args) throws IOException {
        //创建客户端对象
        DatagramSocket socket = new DatagramSocket();
        //创建数据包对象,用于发送数据
        byte[] bytes = "我是客户端对象啊!".getBytes();
        DatagramPacket packet = new DatagramPacket(bytes, bytes.length
                , InetAddress.getLocalHost(), 7777);
        //正式发送封装好的数据包
        socket.send(packet);
        System.out.println("数据发送完成");
        //释放资源
        socket.close();
    }
}

package UDP;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class Server {
    public static void main(String[] args) throws IOException {
        //创建一个服务端对象,需要注册端口
        DatagramSocket socket = new DatagramSocket(7777);
        //创建数据包对象,用于接受数据
        byte[] bytes = new byte[64 * 1024];
        DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
        //使用数据包来接受客户端发送的数据
        socket.receive(packet);

        int len = packet.getLength();
        String data = new String(bytes, 0, len);
        System.out.println(data);
        System.out.println("客户端完成");
        socket.close();
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package UDP;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class Server {
    public static void main(String[] args) throws IOException {
        System.out.println("----------服务端已启动---------");
        //创建一个服务端对象,需要注册端口
        DatagramSocket socket = new DatagramSocket(7777);
        //创建数据包对象,用于接受数据
        byte[] bytes = new byte[64 * 1024];
        DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
        while (true) {
            //使用数据包来接受客户端发送的数据
            socket.receive(packet);
            int len = packet.getLength();
            String data = new String(bytes, 0, len);
            System.out.println(data);
            System.out.println(packet.getAddress().getHostAddress());
            System.out.println(packet.getAddress().getHostName());
            System.out.println();
        }
    }
}

package UDP;

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

public class Client {
    public static void main(String[] args) throws IOException {
        //创建客户端对象
        DatagramSocket socket = new DatagramSocket();
        Scanner sc = new Scanner(System.in);
        while (true) {
            //创建数据包对象,用于发送数据
            System.out.println("请输入待发送内容:");
            String msg = sc.next();
            if(msg.equals("exit")){
                System.out.println("您已成功退出!");
                //释放资源
                socket.close();
                break;
            }
            byte[] bytes = msg.getBytes();
            DatagramPacket packet = new DatagramPacket(bytes, bytes.length
                    , InetAddress.getLocalHost(), 7777);
            //正式发送封装好的数据包
            socket.send(packet);
        }
    }
}

TCP通信

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package tcp;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        System.out.println("————————————————服务器端成功启动——————————————————");
        //创建ServerSocket对象,同时为服务器注册端口
        ServerSocket serverSocket = new ServerSocket(6666);
        //使用ServerSocket对象调用accept()方法,,等待客户端连接请求
        Socket socket = serverSocket.accept();
        //从Socket管道得到一个字节输入流
        InputStream is = socket.getInputStream();
        //字节输入流包装为数据输入流
        DataInputStream dis = new DataInputStream(is);
        //使用数据输入流读取客户端发过来的信息
        String data = dis.readUTF();
        System.out.println(data);
        //此时也能够获取客户端地址
        System.out.println(socket.getRemoteSocketAddress());

        dis.close();
        socket.close();
    }
}

package tcp;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

public class Client {
    public static void main(String[] args) throws IOException {
        //创建Socket对象,同时请求与服务器端程序的连接
        Socket socket = new Socket("127.0.0.1", 6666);
        //从Socket管道获得一个字节输出流,来给服务端程序发送数据
        OutputStream os = socket.getOutputStream();
        //把低级的字节输出流包装为数据输出流
        DataOutputStream dos = new DataOutputStream(os);
        //开始写入数据
        dos.writeUTF("在吗,开连~");
        dos.close();
        socket.close();//释放连接资源
    }
}

在这里插入图片描述

package tcp1;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws IOException {
        //创建Socket对象,同时请求与服务器端程序的连接
        Socket socket = new Socket("127.0.0.1", 6666);
        //从Socket管道获得一个字节输出流,来给服务端程序发送数据
        OutputStream os = socket.getOutputStream();
        //把低级的字节输出流包装为数据输出流
        DataOutputStream dos = new DataOutputStream(os);
        Scanner sc = new Scanner(System.in);
        //开始写入数据
        while (true) {
            System.out.println("请输入待发送内容:");
            String msg = sc.next();
            if(msg.equals("exit")) {
                System.out.println("已成功退出!");
                //释放连接资源
                dos.close();
                socket.close();
                break;
            }
            dos.writeUTF(msg);
            dos.flush();
        }
    }
}

package tcp1;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        System.out.println("————————————————服务器端成功启动——————————————————");
        //创建ServerSocket对象,同时为服务器注册端口
        ServerSocket serverSocket = new ServerSocket(6666);
        //使用ServerSocket对象调用accept()方法,,等待客户端连接请求
        Socket socket = serverSocket.accept();
        //从Socket管道得到一个字节输入流
        InputStream is = socket.getInputStream();
        //字节输入流包装为数据输入流
        DataInputStream dis = new DataInputStream(is);
        while (true) {
            try {
                //使用数据输入流读取客户端发过来的信息
                String data = dis.readUTF();
                System.out.println(data);
            } catch (IOException e) {
                System.out.println(socket.getRemoteSocketAddress() + "已离线哦");
                dis.close();
                socket.close();
                break;
            }
        }
    }
}

在这里插入图片描述
在这里插入图片描述

TCP:实现与多个客户端同时通信

在这里插入图片描述
在这里插入图片描述

package tcp1;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws IOException {
        //创建Socket对象,同时请求与服务器端程序的连接
        Socket socket = new Socket("127.0.0.1", 6666);
        //从Socket管道获得一个字节输出流,来给服务端程序发送数据
        OutputStream os = socket.getOutputStream();
        //把低级的字节输出流包装为数据输出流
        DataOutputStream dos = new DataOutputStream(os);
        Scanner sc = new Scanner(System.in);
        //开始写入数据
        while (true) {
            System.out.println("请输入待发送内容:");
            String msg = sc.next();
            if(msg.equals("exit")) {
                System.out.println("已成功退出!");
                //释放连接资源
                dos.close();
                socket.close();
                break;
            }
            dos.writeUTF(msg);
            dos.flush();
        }
    }
}

package tcp1;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        System.out.println("————————————————服务器端成功启动——————————————————");
        //创建ServerSocket对象,同时为服务器注册端口
        ServerSocket serverSocket = new ServerSocket(6666);
        while (true) {
            //使用ServerSocket对象调用accept()方法,,等待客户端连接请求
            Socket socket = serverSocket.accept();
            System.out.println(socket.getRemoteSocketAddress() + "已上线~");
            new ServerReadThread(socket).start();
        }

    }
}

package tcp1;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.util.Scanner;

public class ServerReadThread extends Thread{
    private Socket socket;

    public ServerReadThread(Socket socket){
        this.socket = socket;
    }
    @Override
    public void run() {
            try {
                InputStream is = socket.getInputStream();
                DataInputStream dis = new DataInputStream(is);
                while (true) {
                    try {
                        String msg = dis.readUTF();
                        System.out.println(msg);
                    } catch (IOException e) {
                        System.out.println(socket.getRemoteSocketAddress() + "已离线哦");
                        dis.close();
                        socket.close();
                        break;
                    }
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

TCP:实现BS架构

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

package tcp3;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        System.out.println("--------服务器已启动----------");
        //创建ServerSocket对象,同时为服务端注册端口
        ServerSocket serverSocket = new ServerSocket(8080);//8080端口是被用于WWW代理服务的,可以实现网页浏览
        while(true){
            //使用ServerSocket对象调用accept()方法
            Socket socket = serverSocket.accept();
            System.out.println(socket.getRemoteSocketAddress() + "已上线~");
            new ServerReadThread(socket).start();
        }
    }
}

package tcp3;

import java.io.DataOutputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;

public class ServerReadThread extends Thread{
    private Socket socket;
    public ServerReadThread(Socket socket){
        this.socket = socket;
    }

    @Override
    public void run(){
        try{
            OutputStream os = socket.getOutputStream();
            PrintStream ps = new PrintStream(os);
            ps.println("HTTP/1.1 200 OK");
            ps.println("Content-Type:text/html;charset=UTF-8");
            ps.println();
            ps.println("<div style='color:blue;font-size:120px;text-align:center'>Hello,B/S</div>");
            ps.close();
            socket.close();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

在这里插入图片描述

Java高级

单元测试

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

package junit;

public class StringUtil {
    public static void printNum(String name){
        if(name == null){
            System.out.println(0);
            return;
        }
        System.out.println(name + "名字长度为" + name.length());
    }

    public static int getMaxIndex(String data){
        if(data == null) return -1;
        return data.length() - 1;
    }
}

package junit;

import org.junit.Assert;
import org.junit.Test;

public class StringUtilTest {
    @Test
    public void testPrintNum(){
        StringUtil.printNum("刘亦菲");
        StringUtil.printNum(null);
    }

    @Test
    public void testGetMaxIndex(){
        int index2 = StringUtil.getMaxIndex(null);
        System.out.println(index2);

        int index1 = StringUtil.getMaxIndex("茜茜");
        System.out.println(index1);
        //断言机制:用于对测试需要满足的条件进行验证
        Assert.assertEquals("error!", 1, index1);
    }
}

在这里插入图片描述

  • 常用注解
    在这里插入图片描述
package junit;

import org.junit.*;

public class StringUtilTest {
    @Before
    public void testBefore(){
        System.out.println("Before did");
    }

    @BeforeClass
    public static void testBeforeClass(){
        System.out.println("-----------BeforeClass did----------------");
    }

    @After
    public void testAfter(){
        System.out.println("After did");
    }

    @AfterClass
    public static void testAfterClass(){
        System.out.println("--------AfterClass did----------");
    }

    @Test
    public void testPrintNum(){
        StringUtil.printNum("刘亦菲");
        StringUtil.printNum(null);
    }

    @Test
    public void testGetMaxIndex(){
        int index2 = StringUtil.getMaxIndex(null);
        System.out.println(index2);

        int index1 = StringUtil.getMaxIndex("茜茜");
        System.out.println(index1);
        //断言机制:用于对测试需要满足的条件进行验证
        Assert.assertEquals("error!", 1, index1);
    }
}

在这里插入图片描述

在这里插入图片描述

反射
认识反射,获取类

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package reflect;

public class Hello {
    public static void main(String[] args) throws ClassNotFoundException {
        //方式一:Class c1 = 类名.class
        Class c1 = Student.class;
        System.out.println(c1.getName());//全类名 reflect.Student
        System.out.println(c1.getSimpleName());//简名(类名)Student

        //方式二:调用Class提供的方法:Class forName(String packet)
        Class c2 = Class.forName("reflect.Student");
        System.out.println(c1 == c2);//比较地址 true

        //方式三:调用Object提供的方法:Class getClass()
        Student student = new Student();
        Class c3 = student.getClass();
        System.out.println(c1 == c3);//true
    }
}

获取类的构造器

在这里插入图片描述

package reflect;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Hey {
    @Test
    public void testGetConstructors(){
        //拿到这个类的Class对象
        Class c = Student.class;
        //获取该类的全部构造器(只能获得public修饰的)
        Constructor[] constructors = c.getConstructors();
        for(Constructor constructor : constructors){
            System.out.println(constructor.getName() + ":" + constructor.getParameterCount());
        }

        System.out.println();
        //获取全部构造器,只要存在就能拿到
        Constructor[] constructors1 = c.getDeclaredConstructors();
        for(Constructor constructor : constructors1){
            System.out.println(constructor.getName() + ":" + constructor.getParameterCount());
        }
    }

    @Test
    public void testGetConstructor() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //先得到该类的Class
        Class c = Student.class;
        //获取某个构造器(只能获取public修饰的)
        Constructor constructor = c.getConstructor();
        System.out.println(constructor.getName() + ":" + constructor.getParameterCount());//reflect.Student:0
        //调用此构造器对象表示的构造器,可能需要传入参数(有参构造器),完成对象的初始化并返回
        Student student = (Student) constructor.newInstance();//无参构造器执行!
        System.out.println(student);//Student{name='null', age=0}

        //获取某个构造器(只要存在就能拿到)
        Constructor constructor1 = c.getDeclaredConstructor(String.class);
        //设置为true,表示禁止检查访问控制(暴力反射)
        constructor1.setAccessible(true);
        Student student1 = (Student)constructor1.newInstance("刘亦菲");//参数为String name的构造器执行!
        System.out.println(student1);//Student{name='刘亦菲', age=0}
        System.out.println(constructor1.getName() + ":" + constructor1.getParameterCount());//reflect.Student:1
    }
}

package reflect;

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

    public Student() {
        System.out.println("无参构造器执行!");
    }

    private Student(String name){
        System.out.println("参数为String name的构造器执行!");
        this.name = name;
    }

    public Student(String name, int age) {
        System.out.println("有参构造器执行!");
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", 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;
    }
}

获取类的成员变量

在这里插入图片描述

package reflect;

import org.junit.Test;

import java.lang.reflect.Field;

public class TestField {
    @Test
    public void testGetFields() throws NoSuchFieldException, IllegalAccessException {
        //反射第一步:先拿到该类的Class
        Class c = Worker.class;
        //获取类的全部成员变量(只要存在就能拿到)
        Field[] fields = c.getDeclaredFields();
        //遍历该成员变量数组
        for(Field f : fields){
            System.out.println(f.getName() + ":" + f.getType());
        }
        //定位某个成员变量
        Field field = c.getDeclaredField("salary");
        System.out.println(field.getName() + ":" + field.getType());//salary:double

        Field fName = c.getDeclaredField("name");
        System.out.println(fName.getName() + ":" + fName.getType());//name:class java.lang.String
        //赋值
        Worker worker = new Worker();//无参构造器执行!
        fName.setAccessible(true);
        fName.set(worker, "刘强东");
        System.out.println(worker);//Worker{name='刘强东', age=0}
        //取值
        String name = (String)fName.get(worker);
        System.out.println(name);//刘强东
    }
}

package reflect;

public class Worker {
    public static double salary;
    public static final String health = "keep";
    private String name;
    private int age;

    public Worker() {
        System.out.println("无参构造器执行!");
    }

    public Worker(String name, int age) {
        System.out.println("有参构造器执行!");
        this.name = name;
        this.age = age;
    }

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

    public static double getSalary() {
        return salary;
    }

    public static void setSalary(double salary) {
        Worker.salary = salary;
    }

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

获取类的成员方法

在这里插入图片描述

package reflect;

import org.junit.Test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestMethod {
    @Test
    public void testGetMethods() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //反射第一步:先得到Class对象
        Class c = Human.class;
        //获取类的全部成员方法(只要存在就能拿到)
        Method[] methods = c.getDeclaredMethods();
        //遍历该数组中的每个方法对象
        for(Method method : methods){
            System.out.println(method.getName() + " : " + method.getParameterCount()
            + "," + method.getReturnType());
        }

        System.out.println();
        //获取某方法对象
        Method mRun = c.getDeclaredMethod("pursue");
        System.out.println(mRun.getName() + " : " + mRun.getParameterCount()
                + "," + mRun.getReturnType());//pursue : 0,void
        Method mEat = c.getDeclaredMethod("eat", String.class);
        System.out.println(mEat.getName() + ":" + mEat.getParameterCount()
        + "," + mEat.getReturnType());//eat:1,class java.lang.String

        Human human = new Human();
        //设置为true,表示禁止检查访问控制(暴力反射)
        mRun.setAccessible(true);
        Object rs = mRun.invoke(human);//人可以追寻太阳
        System.out.println(rs);//null 该方法无返回值结果
        mEat.setAccessible(true);
        String rs1 = (String)mEat.invoke(human, "罗锅配煎饼");
        System.out.println(rs1);//人类爱吃罗锅配煎饼
    }
}

package reflect;

public class Human {
    public void see(){
        System.out.println("人可以看太阳");
    }

    private void pursue(){
        System.out.println("人可以追寻太阳");
    }

    public void eat(){
        System.out.println("人类爱吃");
    }

    private String eat(String food){
        return "人类爱吃" + food;
    }

    private String play(String activity){
        return "人类爱玩" + activity;
    }
}

作用&应用场景

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package reflect;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;

public class ObjectFrame {
    //保存任意对象的字段和其数据到文件中
    public static void saveObject(Object obj) throws FileNotFoundException, IllegalAccessException {
        PrintStream ps = new PrintStream(new FileOutputStream("src\\reflect\\data.txt"));
        Class c = obj.getClass();
        ps.println("----------" + c.getSimpleName() + "----------");
        Field[] fields = c.getDeclaredFields();
        for(Field field : fields){
            String name = field.getName();
            field.setAccessible(true);
            String value = field.get(obj) + "";
            ps.println(name + ":" + value);
        }
        ps.close();
    }
}

package reflect;

import org.junit.Test;

import java.io.FileNotFoundException;

public class TestFrame {
    @Test
    public void testSave() throws FileNotFoundException, IllegalAccessException {
        ObjectFrame.saveObject(new Student("吴彦祖", 45));
        //ObjectFrame.saveObject(new Worker("刘强东", 55));
    }
}

在这里插入图片描述

注解
概述&自定义注解

在这里插入图片描述
在这里插入图片描述

package annotation;

public @interface MyAnnotation {
    String language();
    int version() default 11;
}

package annotation;
@MyAnnotation(language = "Java", version = 17)//也可以不使用默认值;可以用在类上
public class Hello {
    @MyAnnotation(language = "GO")//可以用在构造器上
    public Hello(){}

    @MyAnnotation(language = "Java")//可以直接用默认值;可以用在方法上
    public void test(){

    }
}

在这里插入图片描述

元注解

在这里插入图片描述
在这里插入图片描述

package annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.FIELD, ElementType.METHOD})//所修饰的注解只能用在成员变量和方法上
@Retention(RetentionPolicy.RUNTIME)//所修饰的注解一直保留到运行阶段
public @interface MyAnnotation1 {

}

package annotation;

//@MyAnnotation1() 报错'@MyAnnotation1' not applicable to type
public class Hey {
    @MyAnnotation1
    private int a;

    //@MyAnnotation1 报错'@MyAnnotation1' not applicable to constructor
    public Hey(){}

    @MyAnnotation1
    public void test(){}
}

注解的解析

在这里插入图片描述
在这里插入图片描述

package annotation;

import org.junit.Test;

import java.lang.reflect.Method;
import java.util.Arrays;

public class TestAnnotation {
    @Test
    public void parseClass(){
        //得到Class对象
        Class c = Demo.class;
        //解析类上的注解
        if(c.isAnnotationPresent(MyAnnotation2.class)){//判断该类中是否包含某个注解
            MyAnnotation2 myAnnotation2 = (MyAnnotation2)c.getDeclaredAnnotation(MyAnnotation2.class);
            System.out.println(myAnnotation2.value());//JavaWeb
            System.out.println(myAnnotation2.score());//100.0
            System.out.println(Arrays.toString(myAnnotation2.pleasure()));//[语法, 高效]
        }
    }

    @Test
    public void parseMethod() throws NoSuchMethodException {
        //先得到Class对象
        Class c = Demo.class;
        //解析方法上的注解
        Method method = c.getDeclaredMethod("test");
        if(method.isAnnotationPresent(MyAnnotation1.class)){//判断方法对象是否包含了某个注解
            MyAnnotation1 myAnnotation1 = (MyAnnotation1) method.getDeclaredAnnotation(MyAnnotation1.class);
            System.out.println(myAnnotation1 + " exist");//@annotation.MyAnnotation1() exist
        }
    }
}

package annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})
public @interface MyAnnotation2 {
    String value();
    double score() default 100.0;
    String[] pleasure();
}

package annotation;

@MyAnnotation2(value = "JavaWeb", pleasure = {"语法", "高效"})
@MyAnnotation(language = "SQL")
public class Demo {
    @MyAnnotation1()
    public void test(){

    }
}

应用场景

在这里插入图片描述

package annotation;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Apply {
    @MyAnnotation3
    public void test1(){
        System.out.println("test1 did");
    }

    //@MyAnnotation3
    public void test2(){
        System.out.println("test2 did");
    }

    @MyAnnotation3
    public void test3(){
        System.out.println("test3 did");
    }

    @MyAnnotation3
    public void test4(){
        System.out.println("test4 did");
    }

    //@MyAnnotation3
    public void test5(){
        System.out.println("test5 did");
    }

    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
        Class c = Apply.class;
        Apply apply = new Apply();
        Method[] methods = c.getDeclaredMethods();
        for(Method method : methods){
            if(method.isAnnotationPresent(MyAnnotation3.class)){
                method.invoke(apply);
            }
        }
    }
}

package annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation3 {
}

动态代理
快速入门

在这里插入图片描述

应用案例&优点

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/124569.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

getid3 获取视频时长

1、首先&#xff0c;我们需要先下载一份PHP类—getid3https://codeload.github.com/JamesHeinrich/getID3/zip/master 2.我在laravel6.0 中使用 需要在composer.json 自动加载 否则系统访问不到 在命令行 执行 composer dump-autoload $getID3 new \getID3();//视频文件需要放…

『 C++类与对象 』多继承与虚继承

文章目录 ⌨️多继承的概念语法 &#x1f5b1;️ ⌨️棱形继承⌨️虚继承虚继承是如何解决数据冗余和二义性的(不谈虚表概念)?&#x1f5b1;️ ⌨️多继承的概念 多继承指的是一个派生类是由多个基类继承而来的; 而在生活当中也有类似的例子:番茄既可以是水果,也可以是蔬菜;…

内核移植笔记 Cortex-M移植

常用寄存器 PRIMASK寄存器 为1位宽的中断屏蔽寄存器。在置位时&#xff0c;它会阻止不可屏蔽中断&#xff08;NMI&#xff09;和HardFault异常之外的所有异常&#xff08;包括中断&#xff09;。 实际上&#xff0c;它是将当前异常优先级提升为0&#xff0c;这也是可编程异常/…

K8S知识点(五)

&#xff08;1&#xff09;资源管理介绍 Pod控制器的作用&#xff0c;就是为了最终产生各种各样的Pod&#xff0c;Pod里面运行容器&#xff0c;容器里面运行程序 程序需要数据持久化&#xff0c;可以用数据存储卷来存储 Pod想要让外部访问需要通过Service代理&#xff0c;外部…

SAP-PP-报错:工作中心 7333_JQ 工厂 7331 对任务清单类型 N 不存在

创建工艺路线时报错&#xff1a;工作中心 7333_JQ 工厂 7331 对任务清单类型 N 不存在&#xff0c; 这是因为在创建工作中心时未维护控制键值导致的

latex加密符号怎么打|同态加密|Paillier

最近在写论文的时候遇到了一点阻碍&#xff0c;因为论文中需要用到paillier加密算法&#xff0c;想用一个公式表达加密的过程&#xff0c;但是不知道怎么打加密符号。 加密符号如下所示&#xff1a; 其中a是被加密的数字 $[\![a]\!] $ 公式&#xff1a; \begin{equation} …

【编程语言发展史】SQL的发展历史

目录 目录 SQL概述 SQL发展历史 SQL特点 SQL基本语句 SQL是结构化查询语言(Structure Query Language)的缩写&#xff0c;它是使用关系模型的数据库应用语言&#xff0c;由IBM在70年代开发出来&#xff0c;作为IBM关系数据库原型System R的原型关系语言&#xff0c;实现了…

单链表详解

今天我们继续来学习我们的链表&#xff0c;今天我们来学习单链表&#xff0c;什么是单链表呢&#xff0c;我们逻辑结构上可以认为是下面这个图。 然后我们结构体的定义就是下面这个 typedef int SLDateType; typedef struct SList {SLDateType x;struct SList* next; }SL;为什么…

(14)学习笔记:动手深度学习(Pytorch神经网络基础)

文章目录 神经网络的层与块块的基本概念自定义块 问答 神经网络的层与块 块的基本概念 以多层感知机为例&#xff0c; 整个模型接受原始输入&#xff08;特征&#xff09;&#xff0c;生成输出&#xff08;预测&#xff09;&#xff0c; 并包含一些参数&#xff08;所有组成层…

vue3 开启 https

1、安装mkcert证书创建器 npm i mkcert -g 2、检验是否安装成功 mkcert --version 有版本好出现则成功 3、创建证书颁发机构 mkcert create-ca 会在当前目录生成&#xff0c;ca.crt 和 ca.key 两个文件 4、创建证书 mkcert create-cert 会在当前目录生成&#xff0c;…

【2023.11.6】OpenAI发布会——近期chatgpt被攻击,不能使用

OpenAI发布会 写在最前面发布会内容GPT-4 Turbo 具有 128K 上下文函数调用更新改进了指令遵循和 JSON 模式可重现的输出和对数概率更新了 GPT-3.5 Turbo 助手 API、检索和代码解释器API 中的新模式GPT-4 Turbo 带视觉DALLE 3文字转语音 &#xff08;TTS&#xff09;收听语音样本…

Linux第一个小程序进度条

缓冲区 ​ 在写进度条程序之前我们需要介绍一下缓冲区&#xff0c;缓冲区有两种&#xff0c;输入和输出缓冲区&#xff0c;这里主要介绍输出缓冲区。在我们用C语言写代码时&#xff0c;输出一些信息&#xff0c;实际上是先输出到输出缓冲区里&#xff0c;然后才输出到我们的显…

AI系统ChatGPT程序源码+AI绘画系统源码+支持GPT4.0+Midjourney绘画+已支持OpenAI GPT全模型+国内AI全模型

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如…

3D全景技术,为我们打开全新宣传领域

随着科技的发展&#xff0c;3D全景技术正在融入我们的生活&#xff0c;这种全新视觉体验方式为我们打开了一扇全新的宣传领域&#xff0c;可以让我们多方位、多视角地探索各个行业&#xff0c;无论是对教育、商业、还是其他领域&#xff0c;都产生了深远的影响。 3D全景技术结合…

【云备份|| 日志 day5】文件热点管理模块

云备份day5 热点管理模块 热点管理模块 服务器端的热点文件管理是对上传的非热点文件进行压缩存储&#xff0c;节省磁盘空间。 而热点文件的判断在于上传的文件的最后一次访问时间是否在热点判断时间之内&#xff0c;比如如果一个文件一天都没有被访问过我们就认为这是一个非…

多VLAN之间的通信,静态路由

一、适用场景 1、多个C类网络&#xff08;不同网段&#xff09;之间需要通信&#xff0c;每个网段有1个网关ip。 2、当网络结构比较简单时&#xff0c;只需配置静态路由就可以使网络正常工作。本例采用简单网络结构 3、在复杂网络环境中&#xff0c;配置静态路由可以改进网络的…

牛客出bug(华为机试HJ71)

Hj71&#xff1a;字符串通配符 描述 问题描述&#xff1a;在计算机中&#xff0c;通配符一种特殊语法&#xff0c;广泛应用于文件搜索、数据库、正则表达式等领域。现要求各位实现字符串通配符的算法。 要求&#xff1a; 实现如下2个通配符&#xff1a; *&#xff1a;匹配0个…

Java --- Mybatis的动态sql标签

一、if标签 <select id"queryEmpByCondition" resultType"User">select * from t_user where 11<if test"username ! null and username ! ">and username #{username}</if></select> if&#xff1a;根据标签中的test…

AWTK 与 Qt 的异同点比较

相似之处&#xff1a; 跨平台支持&#xff1a; AWTK 和 Qt 都提供了跨平台的支持&#xff0c;可以在多种操作系统上进行开发和部署&#xff0c;包括 Windows、Linux、macOS 等。丰富的组件库&#xff1a; 两者都提供了丰富的图形界面组件库&#xff0c;能够满足各种应用程序的…

pytest全局变量的使用

这里重新阐述下PageObject设计模式&#xff1a; PageObject设计模式是selenium自动化最成熟&#xff0c;最受欢迎的一种模式&#xff0c;这里用pytest同样适用 这里直接提供代码&#xff1a; 全局变量 conftest.py """ conftest.py 全局变量&#xff0c;主要实…