java高级的笔记

1 异常处理

1.1 异常概述

在Java中,异常(Exception)是一种处理错误情况的方式。当程序出现错误时,它会抛出一个异常对象,这个对象包含了关于错误的信息。Java通过异常处理机制允许程序员在运行时捕获并处理这些错误。

1.2 异常体系

Java异常体系基于两个主要的基类:ThrowableError

Throwable 是所有错误和异常的父类。

  • Error 表示系统级别的错误,通常是虚拟机错误,这些错误通常不由程序处理。

  • Exception表示需要被程序捕获并处理的异常。

    • RuntimeException 是运行时异常,这些异常通常是因为编程错误导致的,如空指针异常(NullPointerException)、数组越界异常(ArrayIndexOutOfBoundsException)等。运行时异常不需要在方法签名中显式声明。

    • Checked Exception(检查型异常)是除了RuntimeException及其子类以外的异常。这些异常必须在方法签名中显式声明,或者使用try-catch块进行捕获。

1.3 Java常见错误的异常

  • NullPointerException:当应用程序试图在需要对象的地方使用null时。

  • ArrayIndexOutOfBoundsException:当应用程序试图访问数组的非法索引时。

  • ClassCastException:当试图将对象强制转换为不是实例的子类时。

  • FileNotFoundException:当试图打开不存在的文件时。

  • IOException:当发生输入/输出错误时,这是很多I/O相关异常的父类。

1.4 异常处理

Java使用try-catch-finally块来处理异常。

  • try 块:包含可能会抛出异常的代码。

  • catch 块:包含处理异常的代码。可以有多个catch块来处理不同类型的异常。

  • finally 块:无论是否发生异常,都会执行的代码块。通常用于释放资源(如关闭文件或数据库连接)。

1.4.1 捕获异常(try-catch-finally)

try {  
    // 可能会抛出异常的代码  
    File file = new File("nonexistentfile.txt");  
    FileReader fr = new FileReader(file);  
    // ...  
} catch (FileNotFoundException e) {  
    // 处理FileNotFoundException异常的代码  
    System.out.println("文件未找到:" + e.getMessage());  
} catch (IOException e) {  
    // 处理其他IO异常  
    System.out.println("I/O错误:" + e.getMessage());  
} finally {  
    // 无论是否发生异常,都会执行的代码  
    System.out.println("finally块被执行");  
}

1.4.2 finally使用及举例

finally块经常用于确保资源(如文件句柄、网络连接等)的释放,即使发生异常也会执行。

try (FileReader fr = new FileReader("somefile.txt")) {  
    // 读取文件的代码  
} catch (IOException e) {  
    // 处理异常  
} finally {  
    // 无论是否发生异常,都会执行的代码  
    System.out.println("资源被释放");  
}

注意:从Java 7开始,可以使用try-with-resources语句来自动关闭实现了AutoCloseable接口的资源。

1.5 声明抛出异常类型(throws)

如果一个方法可能会抛出异常但不想在方法内部处理它,可以使用throws关键字在方法签名中声明该方法可能会抛出的异常。

public void readFile(String filename) throws IOException {  
    // ... 可能会抛出IOException的代码  
}

1.6 自定义异常的语法格式

自定义异常通常继承自ExceptionRuntimeException

public class MyCustomException extends Exception {  
    public MyCustomException(String message) {  
        super(message);  
    }  
      
    // 可以添加其他方法或构造器  
}  
  
// 使用自定义异常  
public void doSomething() throws MyCustomException {  
    // ...  
    if (/* 某种条件 */) {  
        throw new MyCustomException("发生了自定义异常");  
    }  
    // ...  
}

2 集合

2.1 Set集合

2.1.1 Set 集合概述

Set 集合是一个不包含重复元素的集合,它继承了 Collection 接口。Set 集合中的元素不按照特定的顺序排列,因此它不保证元素的顺序。

2.1.2 Set特点

  • 存储键值对(key-value pairs)的集合。

  • 每个键都是唯一的,但值可以重复。

  • Map集合与Collection集合没有继承关系,它们是并行的两个集合体系。

2.1.3 Set 集合的常用方法

  1. add(E e):向集合中添加一个元素。

  2. remove(Object o):从集合中删除指定的元素。

  3. contains(Object o):检查集合中是否包含指定的元素。

  4. size():返回集合中元素的数量。

  5. isEmpty():检查集合是否为空。

  6. clear():清空集合中的所有元素。

  7. iterator():返回一个用于遍历集合中元素的迭代器。

2.1.4 Set 集合的主要实现类

例1:HashSet:基于哈希表实现的 Set 集合,它提供了快速的插入、删除和查找操作。HashSet 不保证元素的顺序。

import java.util.HashSet;
​
public class HashSetExample {
    public static void main(String[] args) {
        HashSet<String> set = new HashSet<>();
        set.add("apple");
        set.add("banana");
        set.add("orange");
        set.add("apple"); // 重复元素,不会被添加
​
        System.out.println(set); // 输出:[orange, banana, apple]
    }
}

例2:LinkedHashSet:基于哈希表和链表实现的 Set 集合,它继承了 HashSet,但保持了元素的插入顺序。

import java.util.LinkedHashSet;
​
public class LinkedHashSetExample {
    public static void main(String[] args) {
        LinkedHashSet<String> set = new LinkedHashSet<>();
        set.add("apple");
        set.add("banana");
        set.add("orange");
        set.add("apple"); // 重复元素,不会被添加
​
        System.out.println(set); // 输出:[apple, banana, orange]
    }
}

例3:TreeSet:基于红黑树实现的有序 Set 集合,它可以对元素进行排序。默认情况下,元素按照自然顺序排序,也可以通过传入自定义的 Comparator 进行排序。

import java.util.TreeSet;
​
public class TreeSetExample {
    public static void main(String[] args) {
        TreeSet<String> set = new TreeSet<>();
        set.add("apple");
        set.add("banana");
        set.add("orange");
        set.add("apple"); // 重复元素,不会被添加
​
        System.out.println(set); // 输出:[apple, banana, orange]
    }
}

2.2 List 集合

2.2.1 List 集合概述

List 集合是一个有序集合,它继承了 Collection 接口。List 集合中的元素可以重复,且元素按照特定的顺序排列。

2.2.2 特点

  • 有序集合,可以存储重复的元素。

  • 用户可以精准地控制元素插入的位置。

  • 可以通过索引访问元素。

2.2.3 List 集合的常用方法

  1. add(E e):向集合中添加一个元素。

  2. add(int index, E element):在指定位置插入一个元素。

  3. remove(int index):删除指定位置的元素。

  4. remove(Object o):删除指定的元素。

  5. get(int index):获取指定位置的元素。

  6. set(int index, E element):设置指定位置的元素。

  7. size():返回集合中元素的数量。

  8. isEmpty():检查集合是否为空。

  9. clear():清空集合中的所有元素。

  10. iterator():返回一个用于遍历集合中元素的迭代器。

2.2.4 List 集合的主要实现类

例1:ArrayList:基于动态数组实现的 List 集合,它提供了快速的随机访问。

import java.util.ArrayList;
​
public class ArrayListExample {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("apple");
        list.add("banana");
        list.add("orange");
​
        System.out.println(list); // 输出:[apple, banana, orange]
    }
}

例2:LinkedList:基于双向链表实现的 List 集合,它提供了快速的插入和删除操作。

import java.util.LinkedList;
​
public class LinkedListExample {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>();
        list.add("apple");
        list.add("banana");
        list.add("orange");
​
        System.out.println(list); // 输出:[apple, banana, orange]
    }
}

2.3 Map 集合

2.3.1 Map 集合概述

Map 集合是一种键值对的数据结构,它继承了 Collection 接口。Map 集合中的键是唯一的,但值可以重复。Map 集合中的元素以键值对的形式存储,可以通过键来快速查找对应的值。

2.3.2 特点

  • 存储键值对(key-value pairs)的集合。

  • 每个键都是唯一的,但值可以重复。

  • Map集合与Collection集合没有继承关系,它们是并行的两个集合体系。

2.3.3 Map 集合的常用方法

  1. put(K key, V value):向集合中添加一个键值对。

  2. remove(Object key):删除指定键的键值对。

  3. get(Object key):获取指定键的值。

  4. containsKey(Object key):检查集合中是否包含指定的键。

  5. containsValue(Object value):检查集合中是否包含指定的值。

  6. size():返回集合中键值对的数量。

  7. isEmpty():检查集合是否为空。

  8. clear():清空集合中的所有键值对。

  9. keySet():返回集合中所有键的集合。

  10. values():返回集合中所有值的集合。

  11. entrySet():返回集合中所有键值对的集合。

2.3.4 Map 集合的主要实现类

例1:HashMap:基于哈希表实现的 Map 集合,它提供了快速的插入、删除和查找操作。HashMap 不保证元素的顺序。

import java.util.HashMap;
​
public class HashMapExample {
    public static void main(String[] args) {
        HashMap<String, Integer> map = new HashMap<>();
        map.put("apple", 1);
        map.put("banana", 2);
        map.put("orange", 3);
​
        System.out.println(map); // 输出:{orange=3, banana=2, apple=1}
    }
}

例2:LinkedHashMap:基于哈希表和链表实现的 Map 集合,它继承了 HashMap,但保持了元素的插入顺序。

import java.util.LinkedHashMap;
​
public class LinkedHashMapExample {
    public static void main(String[] args) {
        LinkedHashMap<String, Integer> map = new LinkedHashMap<>();
        map.put("apple", 1);
        map.put("banana", 2);
        map.put("orange", 3);
​
        System.out.println(map); // 输出:{apple=1, banana=2, orange=3}
    }
}

例3:TreeMap:基于红黑树实现的有序 Map 集合,它可以对键进行排序。默认情况下,键按照自然顺序排序,也可以通过传入自定义的 Comparator 进行排序。

import java.util.TreeMap;
​
public class TreeMapExample {
    public static void main(String[] args) {
        TreeMap<String, Integer> map = new TreeMap<>();
        map.put("apple", 1);
        map.put("banana", 2);
        map.put("orange", 3);
​
        System.out.println(map); // 输出:{apple=1, banana=2, orange=3}
    }
}

3 File类与IO流

3.1 File类

在 Java 中,File 类是用于表示文件或目录的路径名的类

3.1.1 File 类概述

File 类提供了许多方法来操作文件或目录,如创建、删除、重命名、获取文件属性(如大小、修改时间等)以及判断文件类型(如是否是文件、是否是目录等)。

3.1.2 File 类的构造器

  1. File(String pathname):构造一个表示指定路径名的 File 对象。

  2. File(String parent, String child):构造一个表示指定父路径名和子路径名的 File 对象。

  3. File(File parent, String child):构造一个表示指定父文件和子路径名的 File 对象。

3.1.3 File 类的常用方法

  1. createNewFile():创建一个新文件。

  2. delete():删除此文件或目录。

  3. exists():检查文件或目录是否存在。

  4. isFile():判断是否是文件。

  5. isDirectory():判断是否是目录。

  6. length():返回文件的大小(字节数)。

  7. listFiles():返回此目录中的所有文件和子目录。

  8. mkdir():创建一个新目录。

  9. mkdirs():创建一个新目录,包括任何必需的父目录。

  10. renameTo(File dest):重命名此文件或目录。

3.1.4 File 类的案例

例1:创建一个新文件:

import java.io.File;
import java.io.IOException;
​
public class FileExample {
    public static void main(String[] args) {
        File file = new File("example.txt");
        try {
            if (file.createNewFile()) {
                System.out.println("文件创建成功");
            } else {
                System.out.println("文件已存在");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

例2:删除一个文件:

import java.io.File;
​
public class FileExample {
    public static void main(String[] args) {
        File file = new File("example.txt");
        if (file.delete()) {
            System.out.println("文件删除成功");
        } else {
            System.out.println("文件删除失败");
        }
    }
}

例3:检查文件或目录是否存在:

import java.io.File;
​
public class FileExample {
    public static void main(String[] args) {
        File file = new File("example.txt");
        if (file.exists()) {
            System.out.println("文件或目录存在");
        } else {
            System.out.println("文件或目录不存在");
        }
    }
}

例4:创建一个新目录:

import java.io.File;
​
public class FileExample {
    public static void main(String[] args) {
        File dir = new File("example_dir");
        if (dir.mkdir()) {
            System.out.println("目录创建成功");
        } else {
            System.out.println("目录创建失败");
        }
    }
}

3.2 IO 流

3.2.1 IO 流原理

Java IO 流(Input/Output Stream)是 Java 中用于读取和写入数据的通道。IO 流可以从文件、网络连接或其他数据源读取数据,也可以将数据写入文件、网络连接或其他数据目标。

3.2.2 流的分类

  1. 字节流:以字节为单位处理数据,主要用于处理二进制数据。

    • 输入流InputStream 类及其子类,如 FileInputStreamBufferedInputStream 等。

    • 输出流OutputStream 类及其子类,如 FileOutputStreamBufferedOutputStream 等。

  2. 字符流:以字符为单位处理数据,主要用于处理文本数据。

    • 输入流Reader 类及其子类,如 FileReaderBufferedReader 等。

    • 输出流Writer 类及其子类,如 FileWriterBufferedWriter 等。

3.2.3 常用方法

例1:FileInputStream:从文件中读取字节数据。

import java.io.FileInputStream;
import java.io.IOException;
​
public class FileInputStreamExample {
    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("example.txt")) {
            int data;
            while ((data = fis.read()) != -1) {
                System.out.print((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

例2:FileOutputStream:将字节数据写入文件。

import java.io.FileOutputStream;
import java.io.IOException;
​
public class FileOutputStreamExample {
    public static void main(String[] args) {
        try (FileOutputStream fos = new FileOutputStream("output.txt")) {
            String content = "Hello, World!";
            fos.write(content.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

例3:BufferedReader:从文件中读取字符数据,支持按行读取。

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
​
public class BufferedReaderExample {
    public static void main(String[] args) {
        try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

例4:BufferedWriter:将字符数据写入文件,支持按行写入。

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
​
public class BufferedWriterExample {
    public static void main(String[] args) {
        try (BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) {
            String content = "Hello, World!\n";
            bw.write(content);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

例5:DataInputStream:从文件中读取基本数据类型。

import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
​
public class DataInputStreamExample {
    public static void main(String[] args) {
        try (DataInputStream dis = new DataInputStream(new FileInputStream("example.bin"))) {
            int num = dis.readInt();
            System.out.println("读取到的整数: " + num);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

例6:DataOutputStream:将基本数据类型写入文件。

import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
​
public class DataOutputStreamExample {
    public static void main(String[] args) {
        try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("output.bin"))) {
            int num = 42;
            dos.writeInt(num);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.3 序列化与反序列化

3.3.1 序列化与反序列化的概念

Java序列化是指将一个Java对象转换成字节序列,以便在网络上传输或存储在本地磁盘中。而反序列化则是将已经序列化的字节序列恢复为Java对象。

3.3.2 序列化的重要性

序列化机制使得对象可以脱离程序的运行而独立存在。所有在网络上传输的对象都必须是可序列化的,如RMI(远程方法调用),传入的参数或返回的对象都必须是可序列化的,否则会出错。同样,所有必须保存到磁盘的Java对象也必须是可序列化的。

3.3.3 实现序列化的方式

Java提供了两种主要的序列化方式:

  1. 实现Serializable接口:Java提供了Serializable接口作为标记接口,用于标识一个类可以被序列化。Serializable接口没有任何方法,只是一个标记接口,用于表示类的对象可以被序列化。

  2. 实现Externalizable接口:Externalizable接口继承自Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以采用默认的序列化方式。

3.3.4 序列化和反序列化的常用API

  1. java.io.ObjectOutputStream:代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。

  2. java.io.ObjectInputStream:代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。

3.3.5 序列化案例

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
​
class Person implements Serializable {
    private String name;
    private int age;
​
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
​
    public String getName() {
        return name;
    }
​
    public int getAge() {
        return age;
    }
}
​
public class SerializationExample {
    public static void main(String[] args) {
        Person person = new Person("John Doe", 30);
​
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser"))) {
            oos.writeObject(person);
            System.out.println("对象序列化成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.3.6 反序列化

反序列化(Deserialization)是将字节流转换回对象的过程。反序列化的过程可以通过 java.io.ObjectInputStream 类实现。

3.3.7 反序列化案例

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
​
class Person implements Serializable {
    private String name;
    private int age;
​
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
​
    public String getName() {
        return name;
    }
​
    public int getAge() {
        return age;
    }
}
​
public class DeserializationExample {
    public static void main(String[] args) {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"))) {
            Person person = (Person) ois.readObject();
            System.out.println("对象反序列化成功");
            System.out.println("姓名: " + person.getName());
            System.out.println("年龄: " + person.getAge());
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

4 多线程

4.1 多线程概念

多线程(Multithreading)是指在一个程序中同时运行多个线程,以实现并发执行。多线程可以提高程序的执行效率,充分利用 CPU 资源。

4.2 多线程生命周期

Java 线程的生命周期包括以下几个阶段:

  1. 新建(New):当创建一个新的线程对象时,线程处于新建状态。

  2. 可运行(Runnable):当调用线程对象的 start() 方法时,线程进入可运行状态。此时,线程已经准备好运行,等待系统分配 CPU 资源。

  3. 运行(Running):当线程获得 CPU 资源后,线程开始执行 run() 方法中的代码,此时线程处于运行状态。

  4. 阻塞(Blocked):线程在运行过程中,可能会因为某些原因进入阻塞状态。例如,等待 I/O 操作完成、等待获取锁等。当阻塞条件解除后,线程会重新进入可运行状态。

  5. 等待(Waiting):线程在运行过程中,可能会进入等待状态。例如,调用 wait() 方法、join() 方法等。当其他线程执行相应操作后,线程会重新进入可运行状态。

  6. 超时等待(Timed Waiting):线程在运行过程中,可能会进入超时等待状态。例如,调用带有超时参数的 wait() 方法、join() 方法、sleep() 方法等。当超时时间到达后,线程会重新进入可运行状态。

  7. 终止(Terminated):当线程执行完 run() 方法中的代码或因为异常而终止时,线程进入终止状态。此时,线程的生命周期结束。

4.3 多线程实现方式

Java 提供了两种实现多线程的方式:

  1. 继承 Thread

class MyThread extends Thread {
    @Override
    public void run() {
        // 线程执行的代码
    }
}
​
public class Main {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
    }
}
  1. 实现 Runnable 接口

class MyRunnable implements Runnable {
    @Override
    public void run() {
        // 线程执行的代码
    }
}
​
public class Main {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
    }
}

4.4 多线程案例

案例 1:创建两个线程,分别输出奇数和偶数

class PrintNumbers implements Runnable {
    private int start;
    private int end;
​
    public PrintNumbers(int start, int end) {
        this.start = start;
        this.end = end;
    }
​
    @Override
    public void run() {
        for (int i = start; i <= end; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
        }
    }
}
​
public class MultiThreadExample {
    public static void main(String[] args) {
        Thread t1 = new Thread(new PrintNumbers(1, 50), "奇数线程");
        Thread t2 = new Thread(new PrintNumbers(2, 50), "偶数线程");
​
        t1.start();
        t2.start();
    }
}

案例2:使用 synchronized 关键字实现线程同步

class SharedResource {
    private int counter = 0;
​
    public synchronized void increment() {
        counter++;
    }
​
    public synchronized int getCounter() {
        return counter;
    }
}
​
class IncrementThread extends Thread {
    private SharedResource sharedResource;
​
    public IncrementThread(SharedResource sharedResource) {
        this.sharedResource = sharedResource;
    }
​
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            sharedResource.increment();
        }
    }
}
​
public class SynchronizedExample {
    public static void main(String[] args) throws InterruptedException {
        SharedResource sharedResource = new SharedResource();
​
        Thread t1 = new IncrementThread(sharedResource);
        Thread t2 = new IncrementThread(sharedResource);
​
        t1.start();
        t2.start();
​
        t1.join();
        t2.join();
​
        System.out.println("Counter: " + sharedResource.getCounter());
    }
}

5 网络编程

在 Java 中,网络编程是指编写程序实现数据在计算机之间的传输

5.1 网络编程概述

Java 提供了一套丰富的网络编程 API,主要包括以下几个部分:

  1. InetAddress:表示互联网协议(IP)地址。

  2. Socket:用于实现客户端和服务器之间的通信。

  3. ServerSocket:用于监听来自客户端的连接请求。

  4. DatagramSocket:用于发送和接收数据报(UDP)。

5.2 Socket 编程

Socket 编程是 Java 网络编程的核心,它允许客户端和服务器之间建立连接并进行数据传输。以下是 Socket 编程的基本步骤:

  1. 创建一个 ServerSocket 对象,监听指定端口的连接请求。

  2. 创建一个 Socket 对象,连接到服务器。

  3. 通过 Socket 对象的输入流接收数据。

  4. 通过 Socket 对象的输出流发送数据。

  5. 关闭 Socket 对象。

5.3 Socket 相关 API

1. java.net.Socket:表示一个套接字,用于实现客户端和服务器之间的通信。

Socket socket = new Socket("localhost", 8080);

2. java.net.ServerSocket:用于监听来自客户端的连接请求。

ServerSocket serverSocket = new ServerSocket(8080);
Socket socket = serverSocket.accept();

3. java.net.InetAddress:表示互联网协议(IP)地址。

InetAddress address = InetAddress.getByName("www.example.com");

4. java.net.DatagramSocket:用于发送和接收数据报(UDP)。

DatagramSocket datagramSocket = new DatagramSocket(8080);

5.4 Socket 案例

示例 1:创建一个简单的 Socket 服务器和客户端

服务器端代码:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
​
public class Server {
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(8080);
        Socket socket = serverSocket.accept();
​
        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
​
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println("Received: " + line);
            writer.println("Server received: " + line);
        }
​
        socket.close();
        serverSocket.close();
    }
}

客户端代码:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
​
public class Client {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("localhost", 8080);
​
        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
​
        writer.println("Hello, Server!");
​
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println("Received: " + line);
        }
​
        socket.close();
    }
}

示例 2:创建一个简单的多线程 Socket 服务器

服务器端代码:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
​
public class MultiThreadServer {
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(8080);
​
        while (true) {
            Socket socket = serverSocket.accept();
            new Thread(new ClientHandler(socket)).start();
        }
    }
}
​
class ClientHandler implements Runnable {
    private Socket socket;
​
    public ClientHandler(Socket socket) {
        this.socket = socket;
    }
​
    @Override
    public void run() {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
​
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println("Received: " + line);
                writer.println("Server received: " + line);
            }
​
            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

客户端代码

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
​
public class Client {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("localhost", 8080);
​
        BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
​
        writer.println("Hello, Server!");
​
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println("Received: " + line);
        }
​
        socket.close();
    }
}

6 常用的API

6.1 String类

String是Java中的不可变字符序列。一旦创建,就不能改变其值。

6.1.1 常用方法

  • length(): 返回字符串的长度。

  • charAt(int index): 返回指定索引处的字符。

  • substring(int beginIndex, int endIndex): 返回一个新字符串,它是此字符串的一个子字符串。

  • indexOf(int ch, int fromIndex): 返回指定字符在此字符串中第一次出现处的索引,从指定的索引开始搜索。

  • lastIndexOf(int ch, int fromIndex): 返回指定字符在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索。

  • replace(char oldChar, char newChar): 返回一个新的字符串,它是通过用newChar替换此字符串中出现的所有oldChar得到的。

  • equals(Object anObject): 比较此字符串与指定的对象是否相等。

  • equalsIgnoreCase(String anotherString): 将此String与另一个String进行比较,不考虑大小写。

6.1.2 案例:

public class StringDemo {  
    public static void main(String[] args) {  
        String str = "Hello, World!";  
        System.out.println("Length: " + str.length());  
        System.out.println("Character at index 0: " + str.charAt(0));  
        System.out.println("Substring from 0 to 5: " + str.substring(0, 5));  
        System.out.println("Index of 'o': " + str.indexOf('o'));  
        System.out.println("New string with 'l' replaced by 'L': " + str.replace('l', 'L'));  
        System.out.println("Equals: " + str.equals("Hello, World!"));  
        System.out.println("EqualsIgnoreCase: " + str.equalsIgnoreCase("hello, world!"));  
    }  
}

6.2 StringBuffer类

StringBuffer是一个可变的字符序列。与String相比,StringBuffer允许对字符序列进行修改。

6.2.1 常用方法

  • append(String str): 将指定的字符串追加到此字符序列的末尾。

  • insert(int offset, String str): 在此字符序列的指定位置插入给定的字符串。

  • delete(int start, int end): 移除此序列的子字符串中的字符。

  • replace(int start, int end, String str): 用给定字符串替换此序列的子字符串中的字符。

6.2.2 案例:

public class StringBufferDemo {  
    public static void main(String[] args) {  
        StringBuffer sb = new StringBuffer("Hello");  
        sb.append(", World!");  
        System.out.println(sb.toString()); // 输出: Hello, World!  
  
        sb.insert(7, " Java");  
        System.out.println(sb.toString()); // 输出: Hello, Java World!  
  
        sb.delete(7, 11);  
        System.out.println(sb.toString()); // 输出: Hello, World!  
  
        sb.replace(7, 12, "Universe");  
        System.out.println(sb.toString()); // 输出: Hello, Universe!  
    }  
}

6.3 Date和DateFormat类

Date类表示特定的瞬间,精确到毫秒。但是,Date类的方法已经过时,因为它们的许多功能已由Calendarjava.time包中的类替代。不过,这里还是简要介绍DateDateFormat

6.3.1 常用方法(对于Date类):

  • getTime(): 返回自1970年1月1日 00:00:00 GMT以来的此Date对象的毫秒偏移量。

DateFormat

  • DateFormat是一个用于日期/时间格式化和解析的抽象类。通常使用其子类SimpleDateFormat

6.3.2案例:

import java.text.DateFormat;  
import java.text.SimpleDateFormat;  
import java.util.Date;  
  
public class DateDemo {  
    public static void main(String[] args) {  
        Date date = new Date();  
        System.out.println("Current Date: " + date.toString());  
  
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
        String formattedDate = dateFormat

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

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

相关文章

数据赋能(73)——数据要素:特征

生产要素中的数据要素具有一系列基本特征&#xff0c;这些特征使得数据在现代经济活动中发挥着越来越重要的作用。数据要素的主要特征如下图所示。 数据已经成为关键的生产要素&#xff0c;数据要素的基本特征可以概括为&#xff1a;虚拟性、非消耗性、非稀缺性、非均质性、排他…

移植USB RTL8723DU WIFI无线驱动给RK3588

wifi 通过dmesg发现可以识别到设备为无线网卡&#xff0c;并驱动蓝牙&#xff0c;但是在ifconfig中没有找到对应的wlan0。 推断有可能是内核里面没有针对8723du wifi的驱动。所以需要查询当前的5.10内核是否包含8723du的驱动。到https://linux-hardware.org/ 上查看。 并结合…

使用RTSP将笔记本摄像头的视频流推到开发板

一、在Windows端安装ffmpeg 1. 下载ffmpeg:下载ffmpeg 解压ffmpeg-master-latest-win64-gpl.zip bin 目录下是 dll 动态库 , 以及 可执行文件 ;将 3 33 个可执行文件拷贝到 " C:\Windows " 目录下 ,将所有的 " .dll " 动态库拷贝到 " C:\Windows\Sy…

linus下Anaconda创建虚拟环境pytorch

一、虚拟环境 1.创建 输入下面命令 conda create -n env_name python3.8 输入y 2.激活环境 输入 conda activate env_name 二、一些常用的命令 在Linux的控制平台 切换到当前的文件夹 cd /根目录/次目录 查看conda目录 conda list 查看pip目录 pip list查看历史命…

Springboot+Vue项目-基于Java+MySQL的教学资料管理系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

[游戏陪玩系统] 陪玩软件APP小程序H5游戏陪玩成品软件源码-线上线下可爆改家政,整理师等功能

简介 随着电竞行业的快速发展&#xff0c;电竞陪玩APP正在逐渐成为用户在休闲娱乐时的首选。为了吸引用户和提高用户体验&#xff0c;电竞陪玩APP开发需要定制一些特色功能&#xff0c;并通过合适的盈利模式来获得收益。本文将为您介绍电竞陪玩APP开发需要定制的特色功能以及常…

AI图书推荐:将 ChatGPT和Excel融合倍增工作效率

《将 ChatGPT和Excel融合倍增工作效率》&#xff08; Hands-on ChatGPT in Excel. Enhance Your Excel Workbooks&#xff09;由Mitja Martini撰写&#xff0c;旨在教授读者如何将ChatGPT与Excel结合使用&#xff0c;以提升工作效率和创造AI增强的Excel工具。它还提供了Excel中…

2024年Docker常用操作快速查询手册

目录 一、Linux系统上 Docker安装流程&#xff08;以ubuntu为例&#xff09; 一、卸载所有冲突的软件包 二、设置Docker的apt存储库&#xff08;这里使用的是阿里云软件源&#xff09; 三、直接安装最新版本的Docker 三、安装指定版本的Docker 四、验证Docker是否安装成功…

06_Flutter自定义锚点分类列表

06_Flutter自定义锚点分类列表 这样的效果&#xff0c;大家在一些商超应用里&#xff0c;应该也看到过。接下来咱们就用Flutter一步一步的来实现。 一.自定义属性抽取 categoryWidth: 左侧边栏的宽度&#xff0c;右侧区域的宽度填充剩余空间即可。itemCount: 总共有多少个分类…

Centos 系列 安装ArchR

Analyzing single-cell regulatory chromatin in R. • ArchRhttps://www.archrproject.com/ ArchR is a scalable software package for integrative single-cell chromatin accessibility analysis 一、Installation of ArchR &#xff08;Ideal&#xff09; ArchR is desig…

四川古力未来科技抖音小店安全:守护您的网购体验

在互联网购物日益普及的今天&#xff0c;四川古力未来科技抖音小店以其独特的魅力和安全保障措施&#xff0c;成为越来越多消费者信赖的购物平台。本文将为您详细解读四川古力未来科技抖音小店的安全保障措施&#xff0c;让您在享受便捷购物的同时&#xff0c;也能安心、放心。…

【简单讲解下FastStone Capture】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

首页最新 多IP浏览器防关联:如何配置多个独立且稳定的IP地址?

在互联网时代&#xff0c;IP地址的重要性不言而喻。然而&#xff0c;IP关联问题却成为一项令人担忧的隐私和安全挑战。针对这个问题&#xff0c;多IP浏览器是一种解决方案&#xff0c;可以帮助用户单独配置多个独立且稳定的IP地址&#xff0c;有效地防止IP关联。 一、IP关联是…

如何使用 ArcGIS Pro 查找小区最近的地铁站

学习 GIS 除了可以用在工作上之外&#xff0c;还可以将其运用到生活之中&#xff0c;比如查找距离小区最近的地铁站&#xff0c;这里为大家介绍一下查找的方法&#xff0c;希望能对你有所帮助。 数据来源 教程所使用的数据是从水经微图中下载的POI数据&#xff0c;除了POI数据…

【PyTorch与深度学习】4、PyTorch的Dataset与DataLoader详细使用教程

课程地址 最近做实验发现自己还是基础框架上掌握得不好&#xff0c;于是开始重学一遍PyTorch框架&#xff0c;这个是课程笔记&#xff0c;这个课还是讲的简略&#xff0c;我半小时的课听了一个半小时。 1. Dataset与DataLoader Dataset类是处理单个训练样本的&#xff0c;也就…

Jetson Orin NX L4T35.5.0平台LT6911芯片 调试记录(2)vi discarding frame问题调试

基于上篇调试记录 Jetson Orin NX L4T35.5.0平台LT6911芯片 调试记录(1)MIPI问题调试-CSDN博客 1.前言 当通过gstreamer持续捕获视频设备时,帧数会下降,并且I输入越高,丢失的帧数越多。 当达到4k30hz时,它完全无法使用,系统会在几秒钟的收集后崩溃并重新启动 4k30hz …

Stm32CubeMX 为 stm32mp135d 添加 adc

Stm32CubeMX 为 stm32mp135d 添加 adc 一、启用设备1. adc 设备添加2. adc 引脚配置2. adc 时钟配置 二、 生成代码1. optee 配置 adc 时钟和安全验证2. linux adc 设备 dts 配置 bringup 可参考&#xff1a; Stm32CubeMX 生成设备树 一、启用设备 1. adc 设备添加 启用adc设…

六氟化硫红外吸收峰

特此记录 anlog 2024年4月30日

标准汽车试验铁地板的技术要求

在现代科技化发展的工作中&#xff0c;试验平台被广泛使用。铸铁试验平台&#xff08;试验铁地板&#xff09;又叫试验工作平台&#xff0c;听名字大家也不难想象出来这是一款带有箱式体的台面&#xff0c;这是一种有长方形或者圆形又或者正方形的试验工作台。 铸铁试验平台&a…

Unity类银河恶魔城学习记录15-5,6 p157 Audio time limiter p158 Area sound

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili​​ AreaSound.cs using System.Collections; using System.Collections.G…
最新文章