Java基础知识三

news/2025/2/12 1:42:48/文章来源:https://www.cnblogs.com/qiaozc/p/18710826

五十、Java 中的并发工具类 CountDownLatch

50.1 概述

CountDownLatch 是 Java 并发包中的一个同步工具类,它允许一个或多个线程等待其他线程完成操作后再继续执行。CountDownLatch 内部维护一个计数器,初始化时指定计数器的值,当计数器的值减为 0 时,等待的线程将被唤醒。

50.2 示例代码

import java.util.concurrent.CountDownLatch;class Worker implements Runnable {private final CountDownLatch latch;public Worker(CountDownLatch latch) {this.latch = latch;}@Overridepublic void run() {try {System.out.println(Thread.currentThread().getName() + " is working.");Thread.sleep(2000);System.out.println(Thread.currentThread().getName() + " has finished working.");} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {latch.countDown(); // 计数器减 1}}
}public class CountDownLatchExample {public static void main(String[] args) throws InterruptedException {int workerCount = 3;CountDownLatch latch = new CountDownLatch(workerCount);for (int i = 0; i < workerCount; i++) {new Thread(new Worker(latch)).start();}latch.await(); // 等待所有线程完成System.out.println("All workers have finished, main thread can continue.");}
}

五十一、Java 中的 ThreadLocal

51.1 概述

ThreadLocal 是 Java 提供的一个线程局部变量工具类,它为每个使用该变量的线程都提供一个独立的变量副本,每个线程都可以独立地改变自己的副本,而不会影响其他线程所对应的副本。

51.2 示例代码

public class ThreadLocalExample {private static final ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>() {@Overrideprotected Integer initialValue() {return 0;}};public static void main(String[] args) {Thread t1 = new Thread(() -> {for (int i = 0; i < 5; i++) {int value = threadLocal.get();threadLocal.set(value + 1);System.out.println(Thread.currentThread().getName() + ": " + threadLocal.get());}});Thread t2 = new Thread(() -> {for (int i = 0; i < 5; i++) {int value = threadLocal.get();threadLocal.set(value + 1);System.out.println(Thread.currentThread().getName() + ": " + threadLocal.get());}});t1.start();t2.start();}
}

五十二、Java 中的异步编程补充:CompletableFuture 组合与异常处理进阶

52.1 CompletableFuture 的组合操作进阶

thenCompose 方法

thenCompose 方法用于将多个 CompletableFuture 串联起来,前一个 CompletableFuture 的结果作为后一个 CompletableFuture 的输入。

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;public class CompletableFutureThenComposeExample {public static CompletableFuture<Integer> asyncTask1() {return CompletableFuture.supplyAsync(() -> 10);}public static CompletableFuture<Integer> asyncTask2(int input) {return CompletableFuture.supplyAsync(() -> input * 2);}public static void main(String[] args) throws ExecutionException, InterruptedException {CompletableFuture<Integer> combinedFuture = asyncTask1().thenCompose(CompletableFutureThenComposeExample::asyncTask2);System.out.println(combinedFuture.get());}
}

52.2 CompletableFuture 的异常处理进阶

handle 方法

handle 方法可以处理 CompletableFuture 执行过程中出现的异常,无论是否出现异常,该方法都会被调用。

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;public class CompletableFutureHandleExample {public static void main(String[] args) throws ExecutionException, InterruptedException {CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {if (Math.random() < 0.5) {throw new RuntimeException("Something went wrong");}return 10;}).handle((result, ex) -> {if (ex != null) {System.out.println("Exception: " + ex.getMessage());return 0;}return result;});System.out.println(future.get());}
}

这些 Java 基础知识进一步深入了内存管理、并发编程等方面,有助于你更全面地理解和运用 Java 语言。

五十三、Java 中的 Fork/Join 框架

53.1 概述

Fork/Join 框架是 Java 7 引入的一个用于并行执行任务的框架,它基于分治算法,将一个大任务拆分成多个小任务,并行执行这些小任务,最后将结果合并。该框架使用 ForkJoinPool 来管理线程池,RecursiveTaskRecursiveAction 是实现具体任务的两个抽象类,前者有返回值,后者无返回值。

53.2 示例:使用 RecursiveTask 计算数组元素之和

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;class ArraySumTask extends RecursiveTask<Integer> {private static final int THRESHOLD = 10;private final int[] array;private final int start;private final int end;public ArraySumTask(int[] array, int start, int end) {this.array = array;this.start = start;this.end = end;}@Overrideprotected Integer compute() {if (end - start <= THRESHOLD) {int sum = 0;for (int i = start; i < end; i++) {sum += array[i];}return sum;} else {int mid = (start + end) / 2;ArraySumTask leftTask = new ArraySumTask(array, start, mid);ArraySumTask rightTask = new ArraySumTask(array, mid, end);leftTask.fork();int rightResult = rightTask.compute();int leftResult = leftTask.join();return leftResult + rightResult;}}
}public class ForkJoinExample {public static void main(String[] args) {int[] array = new int[100];for (int i = 0; i < 100; i++) {array[i] = i + 1;}ForkJoinPool forkJoinPool = new ForkJoinPool();ArraySumTask task = new ArraySumTask(array, 0, array.length);int result = forkJoinPool.invoke(task);System.out.println("Sum of array elements: " + result);}
}

五十四、Java 中的 Atomic

54.1 概述

Atomic 类位于 java.util.concurrent.atomic 包下,提供了一些可以进行原子操作的类,例如 AtomicIntegerAtomicLongAtomicBoolean 等。原子操作是指不会被线程调度机制打断的操作,这种操作一旦开始,就一直运行到结束,中间不会有任何线程上下文切换。使用 Atomic 类可以在不使用锁的情况下实现线程安全的操作。

54.2 示例:使用 AtomicInteger 实现计数器

import java.util.concurrent.atomic.AtomicInteger;class AtomicCounter {private final AtomicInteger counter = new AtomicInteger(0);public void increment() {counter.incrementAndGet();}public int getCount() {return counter.get();}
}public class AtomicExample {public static void main(String[] args) throws InterruptedException {AtomicCounter atomicCounter = new AtomicCounter();int threadCount = 10;Thread[] threads = new Thread[threadCount];for (int i = 0; i < threadCount; i++) {threads[i] = new Thread(() -> {for (int j = 0; j < 1000; j++) {atomicCounter.increment();}});threads[i].start();}for (Thread thread : threads) {thread.join();}System.out.println("Final count: " + atomicCounter.getCount());}
}

五十五、Java 中的 CompletableFutureExecutorService 结合

55.1 概述

CompletableFuture 可以和 ExecutorService 结合使用,通过自定义线程池来执行异步任务,这样可以更好地控制线程资源,避免使用默认线程池可能带来的性能问题。

55.2 示例:使用自定义线程池执行 CompletableFuture 任务

import java.util.concurrent.*;public class CompletableFutureWithExecutorExample {public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService executor = Executors.newFixedThreadPool(2);CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(2000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}return "Task completed";}, executor);System.out.println(future.get());executor.shutdown();}
}

五十六、Java 中的注解元注解

56.1 概述

元注解是用于注解其他注解的注解,Java 提供了几种元注解,用于控制注解的使用范围、生命周期等。常见的元注解有 @Retention@Target@Documented@Inherited 等。

56.2 常见元注解介绍及示例

@Retention

指定注解的保留策略,有 RetentionPolicy.SOURCE(只在源文件中保留,编译时丢弃)、RetentionPolicy.CLASS(在编译后的字节码文件中保留,但运行时不可用)、RetentionPolicy.RUNTIME(在运行时可用)三种取值。

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;@Retention(RetentionPolicy.RUNTIME)
@interface MyRuntimeAnnotation {String value();
}

@Target

指定注解可以应用的目标元素类型,例如类、方法、字段等。

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;@Target({ElementType.METHOD, ElementType.FIELD})
@interface MyTargetAnnotation {String value();
}

@Documented

表示该注解会被包含在 JavaDoc 文档中。

import java.lang.annotation.Documented;@Documented
@interface MyDocumentedAnnotation {String value();
}

@Inherited

表示该注解可以被继承,如果一个使用了 @Inherited 注解的注解应用在一个类上,那么该类的子类也会继承这个注解。

import java.lang.annotation.Inherited;@Inherited
@interface MyInheritedAnnotation {String value();
}@MyInheritedAnnotation("Test")
class ParentClass {}class ChildClass extends ParentClass {}

五十七、Java 中的泛型通配符的更多使用场景

57.1 通配符上限和下限结合使用

在某些情况下,需要同时使用通配符的上限和下限来限制泛型类型。例如,在一个方法中,需要接收一个集合,该集合的元素类型必须是某个类的子类,并且可以添加该类或其子类的元素。

import java.util.ArrayList;
import java.util.List;class Animal {}
class Dog extends Animal {}
class Labrador extends Dog {}public class WildcardCombinationExample {public static void addDogs(List<? super Dog> dogList) {dogList.add(new Dog());dogList.add(new Labrador());}public static void printAnimals(List<? extends Animal> animalList) {for (Animal animal : animalList) {System.out.println(animal);}}public static void main(String[] args) {List<Dog> dogList = new ArrayList<>();addDogs(dogList);printAnimals(dogList);}
}

57.2 通配符在方法参数中的使用

通配符可以使方法更加灵活,能够处理不同类型的泛型集合。

import java.util.ArrayList;
import java.util.List;public class WildcardInMethodExample {public static double sum(List<? extends Number> numbers) {double total = 0;for (Number num : numbers) {total += num.doubleValue();}return total;}public static void main(String[] args) {List<Integer> intList = new ArrayList<>();intList.add(1);intList.add(2);intList.add(3);double result = sum(intList);System.out.println("Sum: " + result);}
}

这些 Java 基础知识进一步拓展了并发编程、泛型、注解等方面的内容,对于深入理解和运用 Java 语言有很大帮助。

五十八、Java 中的垃圾回收算法

58.1 标记 - 清除算法(Mark - Sweep)

概述

标记 - 清除算法是最基础的垃圾回收算法,分为两个阶段:标记阶段和清除阶段。在标记阶段,垃圾回收器会从根对象开始遍历,标记所有可达的对象;在清除阶段,会清除所有未被标记的对象。

缺点

该算法会产生大量的内存碎片,随着时间的推移,可能会导致无法为大对象分配连续的内存空间。

58.2 标记 - 整理算法(Mark - Compact)

概述

标记 - 整理算法在标记 - 清除算法的基础上进行了改进。同样先进行标记阶段,标记出所有可达对象,然后将这些存活的对象向一端移动,最后清除边界以外的内存空间。

优点

解决了标记 - 清除算法产生内存碎片的问题,使得内存空间更加连续。

58.3 复制算法(Copying)

概述

复制算法将可用内存划分为大小相等的两块,每次只使用其中一块。当这一块内存用完后,就将还存活的对象复制到另一块上,然后把已使用过的内存空间一次清理掉。

优点

实现简单,运行高效,不会产生内存碎片。

缺点

可用内存空间减少为原来的一半。

58.4 分代收集算法(Generational Collection)

概述

分代收集算法是目前大多数 Java 虚拟机采用的垃圾回收算法。它根据对象的存活周期将内存划分为不同的区域,一般分为新生代和老年代。新生代中对象的存活时间较短,采用复制算法进行垃圾回收;老年代中对象的存活时间较长,采用标记 - 清除或标记 - 整理算法进行回收。

五十九、Java 中的垃圾回收器

59.1 Serial 垃圾回收器

概述

Serial 垃圾回收器是最古老的垃圾回收器,它是单线程的,在进行垃圾回收时会暂停所有的用户线程(Stop - The - World)。适用于单 CPU 环境下的小型应用。

启用方式

在 JVM 启动时添加 -XX:+UseSerialGC 参数。

59.2 Parallel 垃圾回收器

概述

Parallel 垃圾回收器也称为吞吐量优先的垃圾回收器,它使用多线程进行垃圾回收,能够充分利用多核 CPU 的优势,提高垃圾回收的效率。同样会产生 Stop - The - World 现象。

启用方式

新生代使用 Parallel Scavenge 回收器,老年代使用 Parallel Old 回收器,可通过 -XX:+UseParallelGC-XX:+UseParallelOldGC 参数启用。

59.3 CMS 垃圾回收器

概述

CMS(Concurrent Mark Sweep)垃圾回收器是一种以获取最短回收停顿时间为目标的回收器,它在大部分时间内可以与用户线程并发执行,减少了 Stop - The - World 的时间。主要应用于对响应时间要求较高的场景。

启用方式

通过 -XX:+UseConcMarkSweepGC 参数启用。

59.4 G1 垃圾回收器

概述

G1(Garbage - First)垃圾回收器是一种面向服务端应用的垃圾回收器,它将整个堆划分为多个大小相等的 Region,跟踪各个 Region 里的垃圾堆积程度,在后台维护一个优先列表,每次根据允许的收集时间,优先回收垃圾最多的 Region。

启用方式

通过 -XX:+UseG1GC 参数启用。

六十、Java 中的异常链

60.1 概述

异常链是指在捕获一个异常后,抛出另一个新的异常,并将原始异常作为新异常的原因。这样可以保留原始异常的信息,方便后续的调试和问题定位。

60.2 示例代码

class CustomException extends Exception {public CustomException(String message, Throwable cause) {super(message, cause);}
}public class ExceptionChainExample {public static void method1() throws Exception {try {int result = 1 / 0;} catch (ArithmeticException e) {throw new CustomException("An error occurred in method1", e);}}public static void main(String[] args) {try {method1();} catch (Exception e) {System.out.println("Caught exception: " + e.getMessage());System.out.println("Original exception: " + e.getCause());}}
}

六十一、Java 中的守护线程

61.1 概述

守护线程(Daemon Thread)是一种特殊的线程,它的作用是为其他线程提供服务。当所有的非守护线程结束时,守护线程会自动终止,即使它的任务还没有完成。常见的守护线程如垃圾回收线程。

61.2 示例代码

class MyDaemonThread extends Thread {@Overridepublic void run() {while (true) {try {System.out.println("Daemon thread is running...");Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}public class DaemonThreadExample {public static void main(String[] args) {MyDaemonThread daemonThread = new MyDaemonThread();daemonThread.setDaemon(true); // 设置为守护线程daemonThread.start();try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Main thread is exiting.");}
}

六十二、Java 中的对象克隆

62.1 浅克隆

概述

浅克隆是指创建一个新对象,新对象的属性和原对象相同,但对于引用类型的属性,新对象和原对象引用的是同一个对象。在 Java 中,可以通过实现 Cloneable 接口并重写 clone() 方法来实现浅克隆。

示例代码

class Person implements Cloneable {String name;int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}public class ShallowCloneExample {public static void main(String[] args) throws CloneNotSupportedException {Person p1 = new Person("Alice", 20);Person p2 = (Person) p1.clone();System.out.println(p2.name + " " + p2.age);}
}

62.2 深克隆

概述

深克隆是指创建一个新对象,新对象的属性和原对象相同,对于引用类型的属性,也会创建一个新的对象,而不是引用同一个对象。可以通过序列化和反序列化来实现深克隆。

示例代码

import java.io.*;class Address implements Serializable {String city;public Address(String city) {this.city = city;}
}class Employee implements Serializable {String name;Address address;public Employee(String name, Address address) {this.name = name;this.address = address;}public Employee deepClone() throws IOException, ClassNotFoundException {ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(this);ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bis);return (Employee) ois.readObject();}
}public class DeepCloneExample {public static void main(String[] args) throws IOException, ClassNotFoundException {Address address = new Address("New York");Employee emp1 = new Employee("Bob", address);Employee emp2 = emp1.deepClone();System.out.println(emp2.name + " " + emp2.address.city);}
}

这些内容涵盖了 Java 垃圾回收、异常处理、线程和对象克隆等方面的基础知识,有助于你更深入地理解 Java 语言的底层机制和编程技巧。

六十三、Java 中的同步器 Phaser

63.1 概述

Phaser 是 Java 7 引入的一个可重用的同步屏障,类似于 CyclicBarrierCountDownLatch,但功能更强大。Phaser 可以动态地调整参与线程的数量,并且支持分阶段执行任务。每个阶段称为一个 “相位(Phase)”,当所有注册的线程都到达某个相位的屏障点时,该相位结束,进入下一个相位。

63.2 示例代码

import java.util.concurrent.Phaser;class Task implements Runnable {private final Phaser phaser;public Task(Phaser phaser) {this.phaser = phaser;phaser.register(); // 注册当前线程到 Phaser}@Overridepublic void run() {for (int phase = 0; phase < 3; phase++) {System.out.println(Thread.currentThread().getName() + " arrived at phase " + phase);phaser.arriveAndAwaitAdvance(); // 到达当前相位并等待其他线程}phaser.arriveAndDeregister(); // 完成所有阶段,注销线程}
}public class PhaserExample {public static void main(String[] args) {Phaser phaser = new Phaser(1); // 初始注册一个线程for (int i = 0; i < 3; i++) {new Thread(new Task(phaser)).start();}// 主线程参与 Phaserfor (int phase = 0; phase < 3; phase++) {System.out.println("Main thread arrived at phase " + phase);phaser.arriveAndAwaitAdvance();}phaser.arriveAndDeregister();}
}

六十四、Java 中的 ScheduledExecutorService

64.1 概述

ScheduledExecutorService 是 Java 提供的一个用于执行定时任务和周期性任务的接口,它继承自 ExecutorService。通过 ScheduledExecutorService 可以方便地安排任务在未来某个时间点执行,或者按照一定的周期重复执行。

64.2 示例代码

延迟执行任务

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;public class ScheduledExecutorDelayExample {public static void main(String[] args) {ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);Runnable task = () -> System.out.println("Task executed after delay.");executor.schedule(task, 2, TimeUnit.SECONDS); // 延迟 2 秒执行任务executor.shutdown();}
}

周期性执行任务

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;public class ScheduledExecutorPeriodicExample {public static void main(String[] args) {ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);Runnable task = () -> System.out.println("Periodic task executed.");executor.scheduleAtFixedRate(task, 1, 2, TimeUnit.SECONDS); // 延迟 1 秒后,每 2 秒执行一次任务try {TimeUnit.SECONDS.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}executor.shutdown();}
}

六十五、Java 中的反射调用构造方法

65.1 概述

通过反射可以在运行时动态地调用类的构造方法来创建对象。可以获取类的构造方法对象,然后使用该对象的 newInstance() 方法来创建实例。

65.2 示例代码

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;class MyClass {private String message;public MyClass() {this.message = "Default message";}public MyClass(String message) {this.message = message;}public String getMessage() {return message;}
}public class ReflectionConstructorExample {public static void main(String[] args) {try {// 获取无参构造方法并创建对象Constructor<MyClass> constructor1 = MyClass.class.getConstructor();MyClass obj1 = constructor1.newInstance();System.out.println(obj1.getMessage());// 获取有参构造方法并创建对象Constructor<MyClass> constructor2 = MyClass.class.getConstructor(String.class);MyClass obj2 = constructor2.newInstance("Custom message");System.out.println(obj2.getMessage());} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {e.printStackTrace();}}
}

六十六、Java 中的 try-with-resources 语句的深入理解

66.1 概述

try-with-resources 语句是 Java 7 引入的一种语法糖,用于自动关闭实现了 AutoCloseable 接口的资源。在 try 语句块结束时,会自动调用资源的 close() 方法,无论是否发生异常。

66.2 示例代码

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

66.3 多个资源的处理

try-with-resources 语句可以同时管理多个资源,资源会按照声明的相反顺序关闭。

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;public class MultipleResourcesExample {public static void main(String[] args) {try (BufferedReader br = new BufferedReader(new FileReader("input.txt"));BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) {String line;while ((line = br.readLine()) != null) {bw.write(line);bw.newLine();}} catch (IOException e) {e.printStackTrace();}}
}

六十七、Java 中的字符串拼接性能比较

67.1 不同拼接方式概述

在 Java 中,常见的字符串拼接方式有 + 运算符、StringBuilderStringBufferString.join() 方法。不同的拼接方式在性能上有差异,尤其是在大量拼接操作时。

67.2 性能比较示例代码

public class StringConcatenationPerformance {public static void main(String[] args) {int loopCount = 10000;// 使用 + 运算符拼接long startTime1 = System.currentTimeMillis();String result1 = "";for (int i = 0; i < loopCount; i++) {result1 += "a";}long endTime1 = System.currentTimeMillis();System.out.println("Using + operator: " + (endTime1 - startTime1) + " ms");// 使用 StringBuilder 拼接long startTime2 = System.currentTimeMillis();StringBuilder sb = new StringBuilder();for (int i = 0; i < loopCount; i++) {sb.append("a");}String result2 = sb.toString();long endTime2 = System.currentTimeMillis();System.out.println("Using StringBuilder: " + (endTime2 - startTime2) + " ms");// 使用 StringBuffer 拼接long startTime3 = System.currentTimeMillis();StringBuffer sbf = new StringBuffer();for (int i = 0; i < loopCount; i++) {sbf.append("a");}String result3 = sbf.toString();long endTime3 = System.currentTimeMillis();System.out.println("Using StringBuffer: " + (endTime3 - startTime3) + " ms");// 使用 String.join() 方法拼接long startTime4 = System.currentTimeMillis();String[] array = new String[loopCount];for (int i = 0; i < loopCount; i++) {array[i] = "a";}String result4 = String.join("", array);long endTime4 = System.currentTimeMillis();System.out.println("Using String.join(): " + (endTime4 - startTime4) + " ms");}
}

一般来说,StringBuilder 的性能最好,适合单线程环境下的大量拼接操作;StringBuffer 是线程安全的,但性能相对较低;+ 运算符在少量拼接时方便,但大量拼接时性能较差;String.join() 方法在拼接数组元素时较为方便。

这些内容进一步丰富了 Java 基础知识体系,涵盖了并发同步器、定时任务、反射、资源管理和字符串操作等方面,有助于你更全面地掌握 Java 编程。

六十八、Java 中的契约式设计(Design by Contract)

68.1 概述

契约式设计是一种编程范式,强调在软件设计中明确定义模块之间的契约。在 Java 里,通常通过前置条件、后置条件和不变式来实现。前置条件是调用方法前必须满足的条件;后置条件是方法执行完毕后必须满足的条件;不变式是在对象的整个生命周期内都必须满足的条件。虽然 Java 本身没有直接的语法支持契约式设计,但可以通过断言或自定义检查逻辑来模拟。

68.2 示例代码

class BankAccount {private double balance;public BankAccount(double initialBalance) {// 前置条件:初始余额不能为负assert initialBalance >= 0 : "Initial balance cannot be negative";this.balance = initialBalance;}public void deposit(double amount) {// 前置条件:存款金额必须为正assert amount > 0 : "Deposit amount must be positive";double oldBalance = balance;balance += amount;// 后置条件:新余额等于旧余额加上存款金额assert balance == oldBalance + amount : "Deposit operation failed";}public void withdraw(double amount) {// 前置条件:取款金额必须为正且不能超过余额assert amount > 0 && amount <= balance : "Invalid withdrawal amount";double oldBalance = balance;balance -= amount;// 后置条件:新余额等于旧余额减去取款金额assert balance == oldBalance - amount : "Withdrawal operation failed";}// 不变式:余额始终不能为负public boolean invariant() {return balance >= 0;}
}public class DesignByContractExample {public static void main(String[] args) {BankAccount account = new BankAccount(1000);account.deposit(500);account.withdraw(200);assert account.invariant() : "Invariant violated";}
}

六十九、Java 中的 Locale 类和国际化(i18n)

69.1 Locale 类概述

Locale 类用于表示特定的地理、政治或文化区域。在 Java 中,它被广泛应用于国际化和本地化(i18n 和 l10n)。通过 Locale 对象,可以根据不同的地区和语言环境显示不同的文本、日期、数字等信息。

69.2 示例代码

获取默认 Locale

import java.util.Locale;public class LocaleExample {public static void main(String[] args) {Locale defaultLocale = Locale.getDefault();System.out.println("Default Locale: " + defaultLocale);}
}

使用 Locale 格式化日期和数字

import java.text.DateFormat;
import java.text.NumberFormat;
import java.util.Date;
import java.util.Locale;public class LocaleFormattingExample {public static void main(String[] args) {Date currentDate = new Date();double number = 12345.67;// 美国地区Locale usLocale = Locale.US;DateFormat usDateFormat = DateFormat.getDateInstance(DateFormat.FULL, usLocale);NumberFormat usNumberFormat = NumberFormat.getNumberInstance(usLocale);System.out.println("US Date: " + usDateFormat.format(currentDate));System.out.println("US Number: " + usNumberFormat.format(number));// 法国地区Locale frLocale = Locale.FRANCE;DateFormat frDateFormat = DateFormat.getDateInstance(DateFormat.FULL, frLocale);NumberFormat frNumberFormat = NumberFormat.getNumberInstance(frLocale);System.out.println("French Date: " + frDateFormat.format(currentDate));System.out.println("French Number: " + frNumberFormat.format(number));}
}

七十、Java 中的方法句柄(Method Handles)

70.1 概述

方法句柄是 Java 7 引入的一种新的反射机制,它提供了一种更轻量级、更高效的方式来调用方法、构造函数和字段访问。与传统的反射相比,方法句柄的性能更好,并且可以在运行时动态绑定方法。

70.2 示例代码

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;class MyClass {public void printMessage(String message) {System.out.println(message);}
}public class MethodHandleExample {public static void main(String[] args) throws Throwable {MyClass obj = new MyClass();MethodHandles.Lookup lookup = MethodHandles.lookup();MethodType methodType = MethodType.methodType(void.class, String.class);MethodHandle methodHandle = lookup.findVirtual(MyClass.class, "printMessage", methodType);methodHandle.invoke(obj, "Hello, Method Handles!");}
}

七十一、Java 中的 VarHandle

71.1 概述

VarHandle 是 Java 9 引入的一个新特性,用于在 Java 中进行变量的低级别访问和操作。它提供了一种统一的方式来访问和修改字段、数组元素和其他变量,支持原子操作和内存排序语义。

71.2 示例代码

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;class Counter {private int value;private static final VarHandle VALUE;static {try {MethodHandles.Lookup lookup = MethodHandles.lookup();VALUE = lookup.findVarHandle(Counter.class, "value", int.class);} catch (NoSuchFieldException | IllegalAccessException e) {throw new ExceptionInInitializerError(e);}}public void increment() {VALUE.getAndAdd(this, 1);}public int getValue() {return (int) VALUE.get(this);}
}public class VarHandleExample {public static void main(String[] args) {Counter counter = new Counter();counter.increment();System.out.println("Counter value: " + counter.getValue());}
}

七十二、Java 中的 Lambda 表达式和方法引用的作用域

72.1 Lambda 表达式的作用域

Lambda 表达式可以访问外部的局部变量、实例变量和静态变量。但对于局部变量,必须是 final 或事实上的 final 变量(即变量赋值后不再改变)。

72.2 示例代码

import java.util.function.Consumer;public class LambdaScopeExample {private int instanceVar = 10;private static int staticVar = 20;public void testLambdaScope() {int localVar = 30; // 事实上的 final 变量Consumer<Integer> consumer = (num) -> {System.out.println("Instance variable: " + instanceVar);System.out.println("Static variable: " + staticVar);System.out.println("Local variable: " + localVar);System.out.println("Parameter: " + num);};consumer.accept(40);}public static void main(String[] args) {LambdaScopeExample example = new LambdaScopeExample();example.testLambdaScope();}
}

72.3 方法引用的作用域

方法引用的作用域规则与 Lambda 表达式类似,同样遵循对局部变量的 final 或事实上 final 的要求。

这些 Java 基础知识涵盖了编程范式、国际化、高级反射机制以及 Lambda 作用域等方面,能帮助你进一步深入理解和运用 Java 语言。

七十三、Java 中的 ComparatorComparable 接口

73.1 Comparable 接口

概述

Comparable 接口位于 java.lang 包下,它只有一个抽象方法 compareTo(T o),用于定义对象之间的自然排序规则。实现该接口的类的对象可以进行比较和排序,像 StringInteger 等类都实现了 Comparable 接口。

示例代码

class Student implements Comparable<Student> {private int id;private String name;public Student(int id, String name) {this.id = id;this.name = name;}@Overridepublic int compareTo(Student other) {return Integer.compare(this.id, other.id);}@Overridepublic String toString() {return "Student{id=" + id + ", name='" + name + "'}";}
}import java.util.ArrayList;
import java.util.Collections;
import java.util.List;public class ComparableExample {public static void main(String[] args) {List<Student> students = new ArrayList<>();students.add(new Student(3, "Alice"));students.add(new Student(1, "Bob"));students.add(new Student(2, "Charlie"));Collections.sort(students);for (Student student : students) {System.out.println(student);}}
}

73.2 Comparator 接口

概述

Comparator 接口位于 java.util 包下,用于定义对象的自定义排序规则。当类没有实现 Comparable 接口,或者需要多种不同的排序方式时,可以使用 Comparator 接口。

示例代码

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;class Book {private String title;private int price;public Book(String title, int price) {this.title = title;this.price = price;}public String getTitle() {return title;}public int getPrice() {return price;}@Overridepublic String toString() {return "Book{title='" + title + "', price=" + price + "}";}
}public class ComparatorExample {public static void main(String[] args) {List<Book> books = new ArrayList<>();books.add(new Book("Java Programming", 50));books.add(new Book("Python Basics", 30));books.add(new Book("C++ Advanced", 80));// 按价格排序Comparator<Book> priceComparator = Comparator.comparingInt(Book::getPrice);Collections.sort(books, priceComparator);System.out.println("Sorted by price:");for (Book book : books) {System.out.println(book);}// 按标题排序Comparator<Book> titleComparator = Comparator.comparing(Book::getTitle);Collections.sort(books, titleComparator);System.out.println("Sorted by title:");for (Book book : books) {System.out.println(book);}}
}

七十四、Java 中的反射与类加载

74.1 通过反射获取类的注解信息

概述

利用反射可以在运行时获取类、方法、字段等元素上的注解信息,从而根据注解进行相应的处理。

示例代码

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedElement;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface MyAnnotation {String value();
}@MyAnnotation("Test Class")
class MyAnnotatedClass {// 类的内容
}public class ReflectionAnnotationRetrieval {public static void main(String[] args) {Class<MyAnnotatedClass> clazz = MyAnnotatedClass.class;if (clazz.isAnnotationPresent(MyAnnotation.class)) {MyAnnotation annotation = clazz.getAnnotation(MyAnnotation.class);System.out.println("Annotation value: " + annotation.value());}}
}

74.2 动态加载类

概述

通过 Class.forName() 方法可以在运行时动态加载类,这在很多框架和工具中都有应用,比如 JDBC 驱动的加载。

示例代码

public class DynamicClassLoading {public static void main(String[] args) {try {Class<?> clazz = Class.forName("java.util.ArrayList");System.out.println("Class loaded: " + clazz.getName());} catch (ClassNotFoundException e) {e.printStackTrace();}}
}

七十五、Java 中的异常分类与自定义异常

75.1 异常分类

概述

Java 中的异常分为受检查异常(Checked Exception)和非受检查异常(Unchecked Exception)。受检查异常必须在方法签名中声明或者进行捕获处理,而非受检查异常(如 RuntimeException 及其子类)则不需要。

示例代码

import java.io.FileInputStream;
import java.io.FileNotFoundException;public class ExceptionClassification {public static void main(String[] args) {// 受检查异常示例try {FileInputStream fis = new FileInputStream("nonexistent.txt");} catch (FileNotFoundException e) {System.out.println("File not found: " + e.getMessage());}// 非受检查异常示例int[] arr = {1, 2, 3};try {System.out.println(arr[5]);} catch (ArrayIndexOutOfBoundsException e) {System.out.println("Array index out of bounds: " + e.getMessage());}}
}

75.2 自定义异常

概述

在实际开发中,有时需要根据业务需求自定义异常类,自定义异常类通常继承自 ExceptionRuntimeException

示例代码

class CustomException extends Exception {public CustomException(String message) {super(message);}
}class CustomRuntimeException extends RuntimeException {public CustomRuntimeException(String message) {super(message);}
}public class CustomExceptionExample {public static void main(String[] args) {try {throwCustomCheckedException();} catch (CustomException e) {System.out.println("Custom checked exception: " + e.getMessage());}try {throwCustomRuntimeException();} catch (CustomRuntimeException e) {System.out.println("Custom runtime exception: " + e.getMessage());}}public static void throwCustomCheckedException() throws CustomException {throw new CustomException("This is a custom checked exception.");}public static void throwCustomRuntimeException() {throw new CustomRuntimeException("This is a custom runtime exception.");}
}

七十六、Java 中的流操作进阶

76.1 流的并行处理

概述

Java 流支持并行处理,通过 parallelStream() 方法可以将顺序流转换为并行流,利用多核处理器提高处理效率,但要注意并行处理可能带来的线程安全问题。

示例代码

import java.util.Arrays;
import java.util.List;public class ParallelStreamExample {public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);// 并行流处理long sum = numbers.parallelStream().mapToInt(Integer::intValue).sum();System.out.println("Sum: " + sum);}
}

76.2 流的收集器高级用法

概述

Collectors 类提供了很多强大的收集器,除了常见的 toList()toSet() 等,还可以进行分组、分区、统计等操作。

示例代码

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;class Person {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 AdvancedCollectorsExample {public static void main(String[] args) {List<Person> people = Arrays.asList(new Person("Alice", 25),new Person("Bob", 30),new Person("Charlie", 25));// 按年龄分组Map<Integer, List<Person>> groupedByAge = people.stream().collect(Collectors.groupingBy(Person::getAge));System.out.println("Grouped by age: " + groupedByAge);// 按年龄分区(是否大于 28 岁)Map<Boolean, List<Person>> partitionedByAge = people.stream().collect(Collectors.partitioningBy(person -> person.getAge() > 28));System.out.println("Partitioned by age > 28: " + partitionedByAge);}
}

这些内容进一步丰富了 Java 基础知识体系,涵盖了排序、反射、异常处理和流操作等重要方面,有助于你更全面深入地掌握 Java 编程。

七十七、Java 中的内存模型(JMM)基础

77.1 概述

Java 内存模型(Java Memory Model,JMM)是 Java 虚拟机规范中定义的一种抽象概念,用于屏蔽不同硬件和操作系统的内存访问差异,保证 Java 程序在各种平台下都能达到一致的内存访问效果。它主要定义了线程和主内存之间的抽象关系,以及多线程环境下的可见性、原子性和有序性问题。

77.2 主内存与工作内存

  • 主内存:是所有线程共享的内存区域,存储了对象的实例、静态变量等数据。
  • 工作内存:每个线程都有自己的工作内存,它是主内存的一个副本,线程对变量的所有操作(读取、赋值等)都必须在工作内存中进行,而不能直接操作主内存中的变量。不同线程之间也无法直接访问对方的工作内存。

77.3 可见性问题

在多线程环境下,如果一个线程修改了某个共享变量的值,其他线程可能无法立即看到这个修改,这就是可见性问题。可以使用 volatile 关键字来解决部分可见性问题。

class VisibilityExample {private static volatile boolean flag = false;public static void main(String[] args) {Thread writer = new Thread(() -> {flag = true;System.out.println("Writer thread set flag to true");});Thread reader = new Thread(() -> {while (!flag) {// 等待 flag 变为 true}System.out.println("Reader thread detected flag is true");});reader.start();try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}writer.start();}
}

77.4 原子性问题

原子性是指一个操作是不可中断的,要么全部执行成功,要么全部不执行。Java 中的基本数据类型的读写操作通常是原子性的,但像 i++ 这种复合操作不是原子性的。可以使用 Atomic 类或 synchronized 关键字来保证原子性。

import java.util.concurrent.atomic.AtomicInteger;class AtomicityExample {private static AtomicInteger counter = new AtomicInteger(0);public static void main(String[] args) throws InterruptedException {int threadCount = 10;Thread[] threads = new Thread[threadCount];for (int i = 0; i < threadCount; i++) {threads[i] = new Thread(() -> {for (int j = 0; j < 1000; j++) {counter.incrementAndGet();}});threads[i].start();}for (Thread thread : threads) {thread.join();}System.out.println("Final counter value: " + counter.get());}
}

77.5 有序性问题

在 Java 中,编译器和处理器为了提高性能,可能会对指令进行重排序。但在单线程环境下,重排序不会影响程序的执行结果;在多线程环境下,重排序可能会导致程序出现错误。可以使用 volatile 关键字和 synchronized 关键字来保证有序性。

七十八、Java 中的序列化版本控制的最佳实践

78.1 手动指定 serialVersionUID

在实现 Serializable 接口的类中,手动指定 serialVersionUID 可以避免在类结构发生微小变化时导致反序列化失败。

import java.io.Serializable;class MySerializableClass implements Serializable {private static final long serialVersionUID = 123456789L;private String data;public MySerializableClass(String data) {this.data = data;}public String getData() {return data;}
}

78.2 处理类结构变化

  • 添加字段:如果在类中添加了新的字段,并且希望旧版本的序列化对象仍然可以被反序列化,可以为新字段提供默认值。
import java.io.Serializable;class UpdatedSerializableClass implements Serializable {private static final long serialVersionUID = 123456789L;private String data;private int newField = 0; // 新增字段并提供默认值public UpdatedSerializableClass(String data) {this.data = data;}public String getData() {return data;}public int getNewField() {return newField;}
}
  • 删除字段:删除字段时要谨慎,因为旧版本的序列化对象中可能包含该字段的数据,反序列化时可能会出现问题。可以考虑使用 transient 关键字将字段标记为临时字段,而不是直接删除。
  • 修改字段类型:修改字段类型可能会导致反序列化失败,尽量避免这种操作。如果必须修改,可以考虑提供自定义的 readObjectwriteObject 方法来处理。

七十九、Java 中的集合排序的更多方式

79.1 使用 TreeSetTreeMap 进行自然排序和定制排序

TreeSet

TreeSet 是一个有序的集合,它会根据元素的自然顺序或指定的比较器进行排序。

import java.util.TreeSet;class Person implements Comparable<Person> {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic int compareTo(Person other) {return Integer.compare(this.age, other.age);}@Overridepublic String toString() {return "Person{name='" + name + "', age=" + age + "}";}
}public class TreeSetSortingExample {public static void main(String[] args) {TreeSet<Person> people = new TreeSet<>();people.add(new Person("Alice", 25));people.add(new Person("Bob", 20));people.add(new Person("Charlie", 30));for (Person person : people) {System.out.println(person);}}
}

TreeMap

TreeMap 是一个有序的映射,它会根据键的自然顺序或指定的比较器进行排序。

import java.util.TreeMap;class CustomKey implements Comparable<CustomKey> {private int id;public CustomKey(int id) {this.id = id;}@Overridepublic int compareTo(CustomKey other) {return Integer.compare(this.id, other.id);}@Overridepublic String toString() {return "CustomKey{id=" + id + "}";}
}public class TreeMapSortingExample {public static void main(String[] args) {TreeMap<CustomKey, String> map = new TreeMap<>();map.put(new CustomKey(3), "Value 3");map.put(new CustomKey(1), "Value 1");map.put(new CustomKey(2), "Value 2");for (CustomKey key : map.keySet()) {System.out.println(key + ": " + map.get(key));}}
}

79.2 使用 Collections.sort() 进行自定义排序

除了使用 Comparator 接口,还可以使用 Collections.sort() 方法结合 Lambda 表达式进行自定义排序。

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;class Product {private String name;private double price;public Product(String name, double price) {this.name = name;this.price = price;}public String getName() {return name;}public double getPrice() {return price;}@Overridepublic String toString() {return "Product{name='" + name + "', price=" + price + "}";}
}public class CollectionsSortingExample {public static void main(String[] args) {List<Product> products = new ArrayList<>();products.add(new Product("Laptop", 1000.0));products.add(new Product("Mouse", 20.0));products.add(new Product("Keyboard", 50.0));// 按价格排序Collections.sort(products, (p1, p2) -> Double.compare(p1.getPrice(), p2.getPrice()));for (Product product : products) {System.out.println(product);}}
}

八十、Java 中的 Lambda 表达式与函数式接口的高级应用

80.1 函数式接口的组合

可以将多个函数式接口组合成一个新的函数式接口,以实现更复杂的逻辑。

import java.util.function.Function;public class FunctionalInterfaceComposition {public static void main(String[] args) {Function<Integer, Integer> multiplyByTwo = num -> num * 2;Function<Integer, Integer> addThree = num -> num + 3;// 组合函数Function<Integer, Integer> combined = multiplyByTwo.andThen(addThree);int result = combined.apply(5);System.out.println("Result: " + result);}
}

80.2 方法引用与 Lambda 表达式的结合

方法引用可以和 Lambda 表达式结合使用,使代码更加简洁。

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;class Printer {public static void print(String message) {System.out.println(message);}
}public class MethodReferenceWithLambda {public static void main(String[] args) {List<String> messages = Arrays.asList("Hello", "World", "Java");// 使用方法引用和 Lambda 表达式Consumer<String> printer = Printer::print;messages.forEach(printer);}
}

80.3 延迟执行与惰性求值

Lambda 表达式可以实现延迟执行和惰性求值,只有在需要结果时才进行计算。

import java.util.function.Supplier;public class LazyEvaluation {public static void main(String[] args) {Supplier<Integer> lazyValue = () -> {System.out.println("Calculating value...");return 10 + 20;};// 只有调用 get() 方法时才会执行 Lambda 表达式System.out.println("Before getting value");int value = lazyValue.get();System.out.println("Value: " + value);}
}

这些内容进一步拓展了 Java 基础知识的深度和广度,涉及内存模型、序列化、集合排序以及 Lambda 表达式等多个重要方面,有助于你更全面地掌握 Java 编程的核心要点。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

容器附加存储CAS之OpenEBS快速入门

作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任。 目录一.CAS之OpenEBS存储机制概述1.什么是CAS2.什么是OpenEBS3.OpenEBS数据引擎4.NDM(Node Disk Manager)5.部署OpenEBS的基本流程二.部署OpenEBS 一.CAS之OpenEBS存储机制概述 1.什么是CAS Kubernetes的卷…

【CodeForces训练记录】Codeforces Round 1004 (Div. 2)

训练情况赛后反思 这场太神奇了,都在和出题人对脑电波,全是智慧题 A题 我们考虑进位的情况,例如 9999 之类的,我们发现进位对答案的影响只有 \(x - 9k + 1 = y\),判断 \(k\) 是否存在非负整数解即可点击查看代码 #include <bits/stdc++.h> // #define int long long…

短信验证码爆破

漏洞原理 短信验证码验证时间和次数无限制,存在爆破可能 短信验证码有效期:5~10min,验证码位数4位或6位,纯数字 破解方式:使用枚举逐个尝试 使用BP爆破短信验证码可以先用已有手机号确认验证码位数2.发送验证码后将验证码输入,然后登陆抓包后续和爆破操作一致如果字典太大…

【洛谷P1955】程序自动分析[NOI2015]

今天开始学习并查集 什么是并查集呢?顾名思义,就是动态维护一个方便进行合并和查找的集合 我们采用的是树状结构 也就是说,对于一开始的每个元素 它的爸爸是它自己 然后在输入两个元素的从属关系的时候,通过路径压缩,把它的爸爸直接连到根节点 因为我们只关心这个元素在这…

chorme 系统代理设置

https 需要证书 1.使用BurpSuite导出CA证书,文件导出到本地2. 谷歌浏览器添加证书 谷歌浏览器->设置->搜索"证书"->安全->管理证书->管理从windows导入的证书->受信任的根证书颁发机构->导入第一步的证书3.设置系统代理 windows系统->设置-…

picachu 越权漏洞

1. 水平越权 1.查看提示信息,提供了3个普通用户2. 登陆其中一个账户,并查看个人信息3.根据url 可以看出有用户名信息,尝试在URL中更改其他账户名,发现查看到其他用户的信息4.再次点击查看个人信息按钮,信息更改为已登陆的用户的信息5. 查看源代码发现第27行username 的值是…

windows使用Makefile时自动给可执行文件加上.exe后缀

APP := main在使用makefile的时候,一般通过变量设置自己想要编译出来的可执行文件的名字在windows平台编译出来的可执行文件是需要.exe后缀的识别当前操作系统 通过识别当前的操作系统是什么,从而确定是否添加这个后缀在windows系统中,有这个环境变量说明自己的系统是windows而…

pikachu 验证码绕过 onclient

前端生成的验证码,无论验证码是否正确,都不影响发送到服务器结果(刷新验证码不会通过BP,没有对应的请求出现) 前端验证码逻辑:输入账号密码验证码,如果验证码正确,数据将发送给服务器;如果验证码不正确,数据不会发送给服务器 1.查看页面源代码,发现是前端生成验证码…

图片验证码绕过(验证码不失效) - 使用验证码识别插件

使用BP抓包,抓到的包没有验证码请求添加过滤图片,出现图片验证码请求包添加captcha-killer-modified 插件,识别图片验证码验证码识别服务按照下面链接操作 https://www.cnblogs.com/mr-ryan/p/17812482.html 文档中的ocr_api_server 使用这个链接:https://gitee.com/yijing…

弱口令暴力破解

使用vulhub/tomcat/tomcat8 靶场点击Manager App按钮,提示登陆,输入用户名密码通过BP抓取提交用户名密码的请求报文,获取Authorization信息将Authorization 发送到解码器解码 ,使用Base64 解码成功(一般Base64 编码最后会带= 或者 ==), 解码后知道了发送的密码规则添加Aut…

攻防世界-RE-CatFly

我们将文件拖入虚拟机中运行看到这样的效果 其中上方的数字是不停变化的,下面的次数也在不断的增长。我们猜测这两者是有关联的。 接下来我们进行反编译程序的分析。最上面的字符输出肯定是与printf函数有关,所以我们检索printf在main函数中的调用time(&timer);v13 = 1;v…

Maui 内嵌网页直接调用本机原生功能 Demo

使用 MAUI 制作 H5 套壳程序有以下几个好处:跨平台支持:MAUI (Multi-platform App UI) 允许开发者在多个平台(如 iOS、Android、Windows 和 macOS)上运行应用程序。统一封装的MauiPlus库可以统一调用本机功能,确保在不同平台上有一致的用户体验。访问本地功能:MauiPlus库…