Java 进阶-全面解析
目录
异常处理
集合框架
List 集合
Set 集合
Map 集合
文件与字符集
IO 流
多线程
通过继承Thread类创建线程
通过实现Runnable接口创建线程
线程同步示例
线程通信示例
网络编程
Java 高级技术
反射机制
动态代理
注解
异常处理
在 Java 编程的过程中,异常处理是保障程序稳健运行的关键环节。异常主要分为 Checked Exception(受检异常)和 Unchecked Exception(非受检异常)这两大类。
受检异常要求开发者在代码中必须显式地进行处理。以IOException为例,它常常在程序与外部资源进行交互时出现,像从文件读取数据或者建立网络连接这类操作。如果不处理IOException,程序在编译阶段就会报错,强制开发者考虑可能出现的问题并进行妥善处理。这是因为与外部资源交互时存在诸多不确定性,例如文件可能不存在、网络可能中断等,通过强制处理受检异常,能让开发者提前做好应对策略,提升程序的可靠性。
非受检异常,比如NullPointerException(空指针异常)和ArrayIndexOutOfBoundsException(数组越界异常),大多是由于编程逻辑上的失误导致的。编译器不会强制要求处理这类异常,但一旦它们在程序运行时出现,往往会致使程序崩溃。例如,当代码尝试访问一个null对象的方法或属性时,就会抛出NullPointerException。这类异常通常意味着代码中存在潜在的逻辑错误,需要开发者仔细排查和修复。
异常处理主要通过try-catch-finally块来实现。在try块中,放置的是可能会抛出异常的代码。当try块中的代码抛出异常时,程序流程会立即跳转到对应的catch块。每个catch块专门用于捕获并处理特定类型的异常。例如:
try {FileReader fileReader = new FileReader("nonexistent.txt");
} catch (FileNotFoundException e) {System.out.println("文件未找到,请检查路径");
} finally {// 这里可以关闭资源,即使fileReader为null也需处理,避免空指针异常
}
在上述代码中,try块尝试创建一个FileReader对象来读取名为nonexistent.txt的文件。如果该文件不存在,就会抛出FileNotFoundException异常,此时程序会进入catch块,打印出提示信息。finally块则无论try块中是否发生异常,都会被执行。它通常用于释放资源,比如关闭文件流,确保资源的正确管理,避免资源泄漏。即使try块中由于文件不存在抛出异常,导致fileReader对象未能成功创建(即fileReader为null),在finally块中也需要进行相应的空指针检查,以确保安全地关闭可能存在的资源。
此外,开发者还可以使用throw关键字手动抛出异常,以便在特定的业务逻辑下,主动告知调用者出现了问题。例如,当某个业务规则不满足时,可以手动抛出一个自定义的异常。同时,通过throws声明方法可能抛出的异常,将异常处理的责任交给调用该方法的代码。这样,调用者在调用方法时,就需要明确知道可能会遇到的异常情况,并进行相应的处理。
集合框架
Java 的集合框架为开发者提供了一系列丰富的接口和类,用于高效地存储和操作对象。该框架主要划分为Collection和Map两大体系。
List 集合
List集合的特点是有序且允许元素重复。这意味着元素在集合中的存储顺序与它们被添加的顺序一致,并且可以存在多个相同的元素。在实际应用中,常用的List实现类有ArrayList和LinkedList。
ArrayList是基于数组实现的。数组的特性使得ArrayList在查询元素时具有很高的效率,因为可以通过元素的索引直接访问数组中的对应位置。例如:
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("apple");
arrayList.add("banana");
String element = arrayList.get(0); // 高效获取元素
arrayList.add(1, "cherry"); // 插入元素,可能导致元素移动
在上述代码中,首先创建了一个ArrayList对象,并向其中添加了两个元素"apple"和"banana"。当使用get(0)方法时,可以直接快速地获取到索引为 0 的元素"apple"。这是因为ArrayList内部维护了一个数组,通过索引可以直接定位到数组中对应位置的元素,时间复杂度为 O (1)。然而,当在列表中间位置(如索引为 1 的位置)插入新元素"cherry"时,ArrayList需要将索引 1 及之后的所有元素向后移动一个位置,以腾出空间插入新元素。如果列表中元素数量较多,这种移动操作会消耗较多的时间和资源,导致性能下降。例如,当列表中有大量元素时,每一次插入操作都可能需要移动大量元素,使得插入操作的时间复杂度变为 O (n),其中 n 为列表中元素的数量。
LinkedList则是基于链表结构实现的。链表由一系列节点组成,每个节点包含元素值以及指向下一个节点的引用(在双向链表中还包含指向前一个节点的引用)。这种结构使得LinkedList在进行插入和删除操作时表现出色。因为只需要修改相关节点的引用关系,而不需要像ArrayList那样移动大量元素。例如,在链表中删除一个元素,只需要将该元素前一个节点的next引用指向该元素的下一个节点即可。对于双向链表,还需要将后一个节点的prev引用指向该元素的前一个节点。这种操作的时间复杂度为 O (1),只涉及到对几个节点引用的修改。但在查询元素时,由于链表没有像数组那样的索引直接定位机制,需要从链表的头节点开始,依次遍历每个节点,直到找到目标元素,所以查询效率相对较低。在最坏情况下,查询一个不在链表中的元素需要遍历整个链表,时间复杂度为 O (n)。
Set 集合
Set集合的特性是无序且不允许元素重复。这意味着元素在Set中的存储顺序并非按照添加顺序,并且集合中不会出现两个相同的元素。常见的Set实现类有HashSet和TreeSet。
HashSet是基于哈希表实现的。哈希表利用哈希函数将元素映射到特定的存储位置,这使得插入和查询操作在平均情况下具有 O (1) 的时间复杂度,性能表现非常优秀。为了保证元素的唯一性,HashSet要求存储的元素必须正确重写hashCode()和equals()方法。例如:
HashSet<Integer> hashSet = new HashSet<>();
hashSet.add(1);
hashSet.add(2);
hashSet.add(1); // 重复元素,不会被添加
在这段代码中,首先创建了一个HashSet对象,并向其中添加了两个不同的整数1和2。当再次尝试添加已经存在的元素1时,HashSet会根据元素的哈希码和equals()方法来判断该元素是否已经存在于集合中。哈希函数会根据元素的值计算出一个哈希码,通过哈希码可以快速定位到哈希表中的一个位置。如果该位置已经有元素存在,就需要进一步通过equals()方法来比较两个元素是否相等。如果相等,则认为是重复元素,不会再次添加,从而保证了集合中元素的唯一性。如果元素没有正确重写hashCode()和equals()方法,可能会导致相同的元素被错误地认为是不同的元素,从而破坏集合的唯一性。
TreeSet是基于红黑树实现的。红黑树是一种自平衡的二叉搜索树,这使得TreeSet中的元素会按照一定的顺序排列。默认情况下,TreeSet会按照元素的自然顺序进行排序,例如对于整数类型,就是从小到大排序。同时,也可以通过传入自定义的Comparator接口实现,来指定特定的排序规则。例如,如果要对自定义的对象进行排序,可以实现Comparator接口,在compare()方法中定义对象之间的比较逻辑。这种有序性在需要对元素进行排序遍历的场景中非常有用,例如在统计数据、查找特定范围的元素等操作中。
Map 集合
Map集合用于存储键值对(key - value pairs),其特点是一个键最多只能映射到一个值。在实际开发中,常用的Map实现类有HashMap、TreeMap和LinkedHashMap。
HashMap基于哈希表实现,具有较高的插入和查询效率。与HashSet类似,为了保证键的唯一性,键对象需要正确重写hashCode()和equals()方法。例如:
HashMap<String, Integer> hashMap = new HashMap<>();
hashMap.put("one", 1);
hashMap.put("two", 2);
Integer value = hashMap.get("one");
在上述代码中,创建了一个HashMap对象,并向其中添加了两个键值对,键分别为"one"和"two",对应的值分别为1和2。当使用get("one")方法时,可以快速地根据键"one"获取到对应的值1。HashMap通过哈希函数将键映射到哈希表中的特定位置,插入和查询操作在平均情况下时间复杂度为 O (1)。但如果哈希函数设计不合理,导致大量键映射到同一个位置(即哈希冲突严重),会使得插入和查询操作的性能下降,时间复杂度可能会接近 O (n)。
TreeMap基于红黑树实现,它会对键进行排序。这使得在遍历TreeMap时,键值对会按照键的顺序依次输出。排序方式可以是键的自然顺序,也可以通过自定义的Comparator来指定。这种有序性在需要对键值对进行有序处理的场景中非常有用。例如,在一个存储学生成绩的TreeMap中,以学生姓名作为键,成绩作为值。如果按照学生姓名的字母顺序遍历TreeMap,可以方便地查看成绩的分布情况。
LinkedHashMap继承自HashMap,它在HashMap的基础上,额外维护了一个双向链表来记录元素的插入顺序或者访问顺序。如果希望在遍历集合时,元素的顺序与它们被插入的顺序一致,或者按照访问顺序(最近访问的元素排在前面)进行遍历,LinkedHashMap就是一个很好的选择。例如,在实现一个缓存机制时,可以使用基于访问顺序的LinkedHashMap。当缓存满了需要移除元素时,可以移除最久未被访问的元素(即链表头部的元素),从而保证缓存中始终保留最近使用过的元素。
文件与字符集
在 Java 中,File类主要用于处理文件和目录路径名。通过File类,开发者可以执行一系列操作,如创建新文件、删除文件、重命名文件或目录,以及检查文件或目录的属性。例如:
File file = new File("example.txt");
try {if (file.createNewFile()) {System.out.println("文件创建成功");} else {System.out.println("文件已存在");}
} catch (IOException e) {e.printStackTrace();
}
在这段代码中,首先创建了一个File对象,指向名为example.txt的文件。然后使用createNewFile()方法尝试创建该文件。如果文件成功创建,该方法会返回true,并打印出相应的成功提示信息;如果文件已经存在,则返回false,并打印出文件已存在的提示。如果在创建文件过程中出现输入输出相关的错误,如磁盘空间不足、权限不够等,就会抛出IOException异常,通过catch块捕获并打印异常堆栈信息,以便开发者定位和解决问题。例如,如果磁盘空间已满,createNewFile()方法会抛出IOException,异常信息中会包含与磁盘空间相关的错误描述,帮助开发者快速找到问题所在。
字符集在处理文本数据时起着至关重要的作用。不同的字符集定义了如何将字符编码为字节序列,以及如何将字节序列解码为字符。Java 使用Charset类来表示各种字符集,常见的字符集有 UTF - 8、GBK 等。在读取和写入文本文件时,必须指定正确的字符集,否则可能会出现乱码问题。例如:
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("file.txt"), "UTF - 8"))) {String line;while ((line = reader.readLine()) != null) {System.out.println(line);}
} catch (IOException e) {e.printStackTrace();
}
在上述代码中,使用BufferedReader来读取文件内容。BufferedReader通过InputStreamReader与FileInputStream关联,并且指定了字符集为UTF - 8。这意味着在读取文件时,会按照UTF - 8字符集的规则将文件中的字节数据转换为字符数据。UTF - 8是一种广泛使用的字符集,它可以表示世界上几乎所有的字符,并且具有良好的兼容性和扩展性。如果文件实际采用的字符集与指定的UTF - 8不一致,就可能导致读取的内容出现乱码。例如,如果文件是使用 GBK 字符集编码的,而在读取时指定为UTF - 8,那么原本正确的中文字符可能会显示为乱码。在while循环中,通过readLine()方法逐行读取文件内容,并将每一行打印出来。如果在读取过程中出现输入输出错误,同样会抛出IOException异常,由catch块进行处理。
IO 流
Java 的 IO 流体系分为字节流和字符流,它们为处理输入输出操作提供了不同的方式。
字节流以字节为单位处理数据,非常适合处理二进制数据,如图片、音频、视频等文件。字节流的主要类包括InputStream和OutputStream及其子类。以FileInputStream和FileOutputStream为例:
try (FileInputStream fis = new FileInputStream("source.jpg");FileOutputStream fos = new FileOutputStream("target.jpg")) {int b;while ((b = fis.read()) != -1) {fos.write(b);}
} catch (IOException e) {e.printStackTrace();
}
在这段代码中,首先创建了FileInputStream对象fis,用于从source.jpg文件中读取字节数据;同时创建了FileOutputStream对象fos,用于将读取到的字节数据写入到target.jpg文件中。在while循环中,通过fis.read()方法每次读取一个字节的数据,并将其赋值给变量b。当read()方法返回-1时,表示已经读取到文件末尾。在循环内部,使用fos.write(b)方法将读取到的字节写入到目标文件中。这样就实现了文件的复制操作。如果在读取或写入过程中出现任何输入输出错误,都会抛出IOException异常,由catch块捕获并打印异常信息。例如,如果在读取过程中文件被意外删除,fis.read()方法会抛出IOException,提示文件不存在的错误。
字符流以字符为单位处理数据,更适合处理文本数据。字符流基于Reader和Writer类及其子类,如FileReader和FileWriter。字符流内部会根据指定的字符集进行字节和字符之间的转换。例如:
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {String line;while ((line = reader.readLine()) != null) {System.out.println(line);}
} catch (IOException e) {e.printStackTrace();
}
多线程
多线程技术允许程序同时执行多个任务,这极大地提高了程序的响应性和资源利用率。在 Java 中,创建线程主要有两种方式:继承Thread类和实现Runnable接口。
通过继承Thread类创建线程
class MyThread extends Thread {@Overridepublic void run() {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " 打印: " + i);try {// 线程休眠100毫秒Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}}
}public class ThreadExample {public static void main(String[] args) {MyThread thread = new MyThread();// 启动线程thread.start();for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " 打印: " + i);try {// 线程休眠100毫秒Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}}
}
在上述代码中,首先定义了一个MyThread类,它继承自Thread类。在MyThread类中重写了run()方法,这个方法是线程执行的主体。在run()方法中,通过一个for循环打印出当前线程的名称以及循环变量i的值。每次打印后,线程会调用Thread.sleep(100)方法进入休眠状态 100 毫秒,这模拟了线程执行一些耗时操作的情况。在main方法中,创建了MyThread类的实例thread,然后调用thread.start()方法启动线程。需要注意的是,不能直接调用thread.run()方法,因为这样只是在主线程中普通地调用一个方法,并不会启动一个新的线程。启动线程后,主线程也会执行一个类似的for循环,打印出主线程的相关信息。由于多线程执行的不确定性,主线程和新启动的线程的打印信息可能会交替出现。
通过实现Runnable接口创建线程
class MyRunnable implements Runnable {@Overridepublic void run() {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " 打印: " + i);try {// 线程休眠100毫秒Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}}
}public class RunnableExample {public static void main(String[] args) {MyRunnable myRunnable = new MyRunnable();Thread thread = new Thread(myRunnable);// 启动线程thread.start();for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " 打印: " + i);try {// 线程休眠100毫秒Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}}
}
这种方式中,定义了一个MyRunnable类实现了Runnable接口,在MyRunnable类的run()方法中同样编写了线程的执行逻辑。在main方法中,首先创建了MyRunnable类的实例myRunnable,然后将这个实例作为参数传递给Thread类的构造函数,创建了一个Thread对象thread。最后调用thread.start()方法启动线程。实现Runnable接口相较于继承Thread类更具优势,因为 Java 不支持多重继承,通过实现接口可以避免继承带来的局限性,使得类可以同时实现多个接口,增强了代码的灵活性。
线程同步示例
多线程编程中,线程安全问题是需要重点关注的。当多个线程同时访问共享资源时,如果没有进行适当的同步控制,可能会导致数据不一致等问题。例如,多个线程同时对一个共享的计数器进行增加操作,可能会出现计数不准确的情况。可以使用synchronized关键字来实现线程同步。
class Counter {private int count = 0;public synchronized void increment() {count++;}public int getCount() {return count;}
}class IncrementThread implements Runnable {private Counter counter;public IncrementThread(Counter counter) {this.counter = counter;}@Overridepublic void run() {for (int i = 0; i < 1000; i++) {counter.increment();}}
}public class SynchronizedExample {public static void main(String[] args) throws InterruptedException {Counter counter = new Counter();IncrementThread incrementThread = new IncrementThread(counter);Thread thread1 = new Thread(incrementThread);Thread thread2 = new Thread(incrementThread);thread1.start();thread2.start();thread1.join();thread2.join();System.out.println("最终计数: " + counter.getCount());}
}
线程通信示例
线程通信可以使用
wait()
、notify()
和notifyAll()
方法。
class Message {private String msg;private boolean empty = true;public synchronized String read() {while (empty) {try {wait();} catch (InterruptedException e) {Thread.currentThread().interrupt();}}empty = true;notifyAll();return msg;}public synchronized void write(String msg) {while (!empty) {try {wait();} catch (InterruptedException e) {Thread.currentThread().interrupt();}}empty = false;this.msg = msg;notifyAll();}
}class Reader implements Runnable {private Message message;public Reader(Message message) {this.message = message;}@Overridepublic void run() {for (String latestMessage = message.read(); !"EOF".equals(latestMessage); latestMessage = message.read()) {System.out.println("读取消息: " + latestMessage);}}
}class Writer implements Runnable {private Message message;public Writer(Message message) {this.message = message;}@Overridepublic void run() {String[] messages = {"消息1", "消息2", "消息3", "EOF"};for (String msg : messages) {message.write(msg);System.out.println("写入消息: " + msg);try {Thread.sleep(1000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}
}public class ThreadCommunicationExample {public static void main(String[] args) {Message message = new Message();Thread readerThread = new Thread(new Reader(message));Thread writerThread = new Thread(new Writer(message));readerThread.start();writerThread.start();}
}
上述代码示例展示了创建线程的不同方式、线程同步以及线程通信的基本用法。通过继承
Thread
类和实现Runnable
接口创建线程,使用synchronized
关键字保证线程安全,利用wait()
、notify()
和notifyAll()
方法实现线程间的协作。
网络编程
Java 提供了丰富的网络编程类库,支持 TCP 和 UDP 协议。在 TCP 编程中,通过
Socket
类和ServerSocket
类实现客户端和服务器端的通信。例如,一个简单的 TCP 服务器端:
try (ServerSocket serverSocket = new ServerSocket(8080);Socket socket = serverSocket.accept();BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {String inputLine;while ((inputLine = in.readLine()) != null) {System.out.println("收到客户端消息: " + inputLine);out.println("消息已收到");}
} catch (IOException e) {e.printStackTrace();
}
客户端通过创建Socket
对象连接到服务器:
try (Socket socket = new Socket("localhost", 8080);PrintWriter out = new PrintWriter(socket.getOutputStream(), true);BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {out.println("Hello, Server!");String response = in.readLine();System.out.println("收到服务器响应: " + response);
} catch (IOException e) {e.printStackTrace();
}
UDP 编程则使用
DatagramSocket
类和DatagramPacket
类,适用于对实时性要求较高但对数据准确性要求相对较低的场景,如视频流、音频流传输。
Java 高级技术
反射机制
反射允许程序在运行时获取类的信息,包括类的属性、方法、构造函数等,并可以动态创建对象、调用方法。通过
Class
类及其相关方法实现反射。例如:
try {Class<?> clazz = Class.forName("java.util.Date");Object object = clazz.newInstance();Method method = clazz.getMethod("getTime");long time = (long) method.invoke(object);System.out.println("当前时间毫秒数: " + time);
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {e.printStackTrace();
}
反射在框架开发、动态代理等场景中广泛应用,但由于反射操作绕过了编译器的检查,性能相对较低,应谨慎使用。
动态代理
动态代理是一种在运行时创建代理对象的机制,代理对象可以在不修改目标对象代码的情况下,对目标对象的方法调用进行增强。Java 的动态代理通过
Proxy
类和InvocationHandler
接口实现。例如:
interface HelloService {void sayHello();
}class HelloServiceImpl implements HelloService {@Overridepublic void sayHello() {System.out.println("Hello!");}
}class ProxyHandler implements InvocationHandler {private Object target;public ProxyHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("方法调用前增强");Object result = method.invoke(target, args);System.out.println("方法调用后增强");return result;}
}public class Main {public static void main(String[] args) {HelloService target = new HelloServiceImpl();HelloService proxy = (HelloService) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),new ProxyHandler(target));proxy.sayHello();}
}
动态代理在 AOP(面向切面编程)中起着核心作用,用于实现日志记录、事务管理等横切关注点。
注解
注解是 Java 5.0 引入的一种元数据机制,可以为程序元素(类、方法、字段等)添加额外的信息。注解分为预定义注解(如
@Override
、@Deprecated
、@SuppressWarnings
)和自定义注解。自定义注解需要使用@interface
关键字定义,并且可以通过反射读取注解信息。例如:
@interface MyAnnotation {String value();
}@MyAnnotation("This is a test")
class MyClass {// 类体
}public class Main {public static void main(String[] args) {MyClass myClass = new MyClass();Class<?> clazz = myClass.getClass();MyAnnotation annotation = clazz.getAnnotation(MyAnnotation.class);if (annotation != null) {System.out.println(annotation.value());}}
}
注解在框架开发中被大量使用,用于配置、代码生成等场景,提高了代码的可读性和可维护性。
通过对上述 Java 基础进阶知识的深入学习和实践,能够显著提升 Java 编程能力,为开发复杂、高效的 Java 应用程序奠定坚实基础。
=================Java基础知识到此完结=================
至此结束——
我是禹曦a
期待与你的下次相遇!!!
相关文章:
Java 进阶-全面解析
目录 异常处理 集合框架 List 集合 Set 集合 Map 集合 文件与字符集 IO 流 多线程 通过继承Thread类创建线程 通过实现Runnable接口创建线程 线程同步示例 线程通信示例 网络编程 Java 高级技术 反射机制 动态代理 注解 异常处理 在 Java …...
mongodb 创建keyfile
在 MongoDB 中,keyFile 是用于副本集成员间内部认证的密钥文件。它是一个包含随机字符串的文件,所有副本集成员必须使用相同的 keyFile 进行通信。以下是创建和配置 keyFile 的详细步骤。 创建 KeyFile 的步骤 1. 生成随机字符串 使用以下命令生成一个…...
工业4.0时代,RK3562工控机为何成为智慧工位首选?
在制造业数字化转型的浪潮中,智慧车间已成为提升生产效率、降低运营成本的关键战场。作为智慧车间的"神经末梢",工位机的智能化程度直接影响着整个生产线的运行效率。RK3562工控机凭借其强大的计算性能、稳定的运行表现和丰富的接口配置&#…...
WPF 资源加载问题:真是 XAML 的锅吗?
你的观察很敏锐!确实,在 WPF 项目中,.cs 文件主要负责逻辑实现,而资源加载的问题通常跟 XAML(以及它背后的 .csproj 配置)关系更大。我会围绕这个观点,用 CSDN 博客风格详细解释一下 .cs、XAML …...
5. 深度剖析:Spring AI项目架构与分层体系全解读
1、前言 前面我们已经可以通过简单的方式集成Spring AI进行快速开发了。授人以鱼不如授人以渔,我们还是需要了解Spring AI的项目结构,以及他的一些核心概念。 2、项目结构 我们将Spring AI代码直接fork到我们自己的仓库中。fork的目的是方便我们为了学…...
2025最新数字化转型国家标准《数字化转型管理参考架构》 正式发布
当前,数字化转型是数字时代企业生存和发展的必答题,其根本任务是价值体系优化、创新和重构。数字生产力的飞速发展不仅引发了生产方式的转变,也深刻改变了企业的业务体系和价值模式。 为进一步引导企业明确数字化转型的主要任务和关键着力点…...
蓝桥杯备赛 Day 20 树基础
![[树的基础概念.png]] 树的遍历 二叉树遍历分类 DFS前序遍历 根节点-左儿子-右儿子 DFS中序遍历 左儿子-根节点-右儿子 DFS后序遍历 左儿子-右儿子-根节点 BFS层序遍历![[树的遍历.png]] 代码: #include <bits/stdc.h>using namespace std; const int N20; i…...
清晰易懂的Jfrog Artifactory 安装与核心使用教程
JFrog Artifactory 是企业级二进制仓库管理工具,支持 Maven、Docker、npm 等 30 包格式。本教程将手把手教你完成 安装、配置、核心操作,并指出企业级部署的避坑要点,助你快速搭建私有仓库! 一、安装 JFrog Artifactory࿰…...
苍穹外卖总结
苍穹外卖学习知识点 整体概括: 学到目前(day10),总体最核心的部分就是CURD各种数据,因为一些接口,前端页面都已经设计好,在实际开发中也应该是这样,重点是在每个不同的业务板块区别出细微不同的业务逻辑 Swagger注解 swagger是一种自动生成接口文档的插件 使用注解,就可以…...
python学智能算法(九)|决策树深入理解
【1】引言 前序学习进程中,初步理解了决策树的各个组成部分,此时将对决策树做整体解读,以期实现深入理解。 各个部分的解读文章链接为: python学智能算法(八)|决策树-CSDN博客 【2】代码 【2.1】完整代…...
HTTP代理:内容分发战场上的「隐形指挥官」
目录 一、技术本质:流量博弈中的「规则改写者」 二、战略价值:内容分发的「四维升级」 三、实战案例:代理技术的「降维打击」 四、未来进化:代理技术的「认知升级」 五、结语:代理技术的「战略觉醒」 在数字内容爆…...
学习笔记(C++篇)--- Day2
1.类的定义 1.1 类的格式 ①class为类的关键字 ②在类的内容中还可以写函数,具体格式请看示例。 ③为了区分成员变量,一般习惯上成员变量会加一个特殊标识(如成员变量前面或者后面加_ 或者 m开头,注意C中这个并不是强制的&#x…...
下载firefox.tar.xz后如何将其加入到Gnome启动器
起因:近期(2025-04-07)发现firefox公布了130.0 版本,可以对pdf文档进行签名了,想试一下,所以卸载了我的Debian12上的firefox-esr,直接下载了新版本的tar.xz 包。 经过一番摸索,实现了将其加入Gn…...
VSCode英文翻译插件:变量命名、翻单词、翻句子
目录 【var-translate】 【Google Translate】 【code-translator】 【其他插件】 【var-translate】 非常推荐,可以提供小驼峰、大驼峰、下划线、中划线、常量等翻译,Windows下快捷键为Ctrl Shift v 可以整句英文翻译,并且支持多个免费…...
快速高效的MCP Severs
通用AI Agent的瓶颈 最近一直在用MCP协议开发通用智能体。 虽然大模型本身请求比较慢,但是还可以接受。 而最让人沮丧的是,工具效率也不高 比如社区的filesystem,每次只能创建一个目录,生成文件时,如果目录不存在&…...
原子化 CSS 的常见实现框架
原子化 CSS 是一种 CSS 架构方法,其核心思想是将样式拆分为最小粒度的单一功能类,每个类仅对应一个具体的样式属性(如颜色、边距、字体大小等),通过组合这些类来构建复杂的界面。这种方式强调代码复用性、维护性和灵活…...
技术速递|使用 GitHub Copilot Agent Mode 进行编程
作者:卢建晖 - 微软高级云技术布道师 翻译/排版:Alan Wang GitHub Copilot 持续发展,从最初的代码补全、生成、优化功能,到通过对话交互提升 AI 代码质量的 GitHub Copilot Chat,再到能够基于项目中多个文件的关联进行…...
Linux系统(Ubuntu和树莓派)的远程操作练习
目录 实验准备一、Ubuntu 下的远程操作二、树莓派下的远程操作三、思考 实验准备 1.双方应保证处于同一个局域网内 2.关闭防火墙 (否则别人将不能 ping 通自己,具体说明请参考:windows-关闭防火墙) 3.配置虚拟机 a.网桥模式配置 查询…...
电脑屏保壁纸怎么设置 桌面壁纸设置方法详解
电脑桌面壁纸作为我们每天面对的第一视觉元素,不仅能够彰显个人品味,还能营造舒适的工作或娱乐氛围。电脑桌面壁纸怎么设置呢?下面本文将为大家介绍Windows和macOS两大主流操作系统中设置电脑桌面壁纸的方法,帮助大家快速设置个性…...
为什么选择Redis?解析核心使用场景与性能优化技巧
解析核心使用场景与性能优化技巧 redis只能能操作字符串,要把Java对象存入redis非关系型数据库,需要用序列化变成字符串,再反序列化成Java对象 not only sql NoSQL非关系型数据库:缓存数据库,只能读取数据࿰…...
Docker中Redis修改密码失效
docker容器中,我们通过docker run命令运行某一容器 这里,我们通过以下命令来进行运行【注意,这里有两个关键点:-d 和--requirepass】 docker run \ --restartalways \ --log-opt max-size100m \ --log-opt max-file2 \ -p 6379:6…...
质数质数筛
1.试除法判定质数–O(sqrt(N)) bool is_prime(int x) {if (x < 2) return false;for (int i 2; i < x / i; i )if (x % i 0)return false;return true; }2.试除法分解质因数–O(logN)~O(sqrt(N)) void divide(int x) {for (int i 2; i < x / i; i )if (x % i …...
VGA接口设计
1.VGA简介 VGA(Video Graphics Array)视频图形阵列接口是一种模拟信号视频传输标准,用于连接计算机主机和显示设备,如显示器、投影仪等。 VGA接口能够传输红、绿、蓝三原色的模拟信号以及同步信号(数字信号),实现计算机图形和视频信号的输出和显示。 尽管数字化显示接口…...
clickhouse注入手法总结
clickhouse 遇到一题clickhouse注入相关的,没有见过,于是来学习clickhouse的使用,并总结相关注入手法。 环境搭建 直接在docker运行 docker pull clickhouse/clickhouse-server docker run -d --name some-clickhouse-server --ulimit n…...
VsCode保存时删除无用的引用
打开设置文件 教程:打开VsCode设置设置里添加 {"editor.codeActionsOnSave": {"source.organizeImports": false, // 禁用默认的整理导入"source.removeUnusedImports": true // 仅删除未使用的导入} }...
轻松Linux-4.进程概念
屋漏偏逢连夜雨,今天就学Linux 话不多说,展示军火 1.认识冯诺依曼体系 冯诺依曼体系其实并不是什么稀罕的东西,我们生活中的笔记本、服务器、计算机等等大多都遵守冯诺依曼体系 非常经典的一张图 我们所认识的计算机,是由一个个…...
畅游Diffusion数字人(21):基于Wan2.1的音频驱动数字人FantasyTalking
畅游Diffusion数字人(0):专栏文章导航 前言:AI数字人是目前视觉AIGC最有希望大规模落地的场景之一。现阶段的商业工具,如字节的OminiHuman-1(即梦大师版)、快手的可灵对口型,虽然效果不错,但是收费昂贵。而开源解决方案…...
CentOS禁用nouveau驱动
1、验证 nouveau 是否在运行 lsmod | grep nouveau如果命令返回结果,说明 nouveau 驱动正在运行。 2、编辑黑名单文件 通过编辑黑名单配置文件来禁用 nouveau 驱动,这样在系统启动时不会加载它。 vi /etc/modprobe.d/blacklist-nouveau.conf修改以下…...
《Operating System Concepts》阅读笔记:p587-p596
《Operating System Concepts》学习第 52 天,p587-p596 总结,总计 10 页。 一、技术总结 1.Recovery (1)consistency checking consistency checking 工具:fsck。 (2)log-structure file system (3)WAFL file system 2.Veritas (1)Ve…...
k8s 1.24.17版本部署(使用Flannel插件)
1.k8s集群环境准备 推荐阅读: https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/install-kubeadm/ 1.1 环境准备 环境准备:硬件配置: 2core 4GB磁盘: 50GB操作系统: Ubuntu 22.04.04 LTSIP和主机名:10.0.0.231 master23110.0.0.232 worker23210.0…...
通信协议详解(十):PSI5 —— 汽车安全传感器的“抗干扰狙击手”
一、PSI5是什么? 一句话秒懂 PSI5就像传感器界的“防弹信使”:在汽车安全系统(如气囊)中,用两根线同时完成供电数据传输,即便车祸时线路受损,仍能确保关键信号准确送达! 基础概念…...
Kafka生产者和消费者:数据管道的核心引擎与智能终端
在分布式系统中,数据的高效流动如同人体的血液循环,而Kafka的生产者(Producer)与消费者(Consumer)正是驱动这一循环的核心组件。它们不仅是Kafka客户端的基本形态,更是构建实时数据生态的基石。…...
特权FPGA之按键消抖
完整代码如下所示: timescale 1ns / 1ps// Company: // Engineer: 特权 // // Create Date: // Design Name: // Module Name: // Project Name: // Target Device: // Tool versions: // Description: // // Dependencies: // // Revision: // …...
实时比分更新系统的搭建
搭建一个实时比分更新系统需要考虑多个技术环节,以下是一个完整的实现方案: 一、系统架构 1.数据获取层 比分数据API接入(如熊猫比分、API-Football等) 网络爬虫(作为备用数据源) 2.数据处理层 …...
【Linux】线程的概念与控制
目录 1. 整体学习思维导图 2. 线程的概念 2.1 基础概念 2.2 Linux下的线程 初步理解: 2. 分页式存储 3.1 页表 3.1.1 页框/页 3.1.2 页表机制 3.1.3 从虚拟地址到物理地址的转换 总结: 3.2 TLB快表 3.3 缺页异常(Page Fault&am…...
K8s 老鸟的配置管理避雷手册
Yining, China 引言 对于这种案例,你们的处理思路是怎么样的呢,是否真正的处理过,如果遇到,你们应该怎么处理。 最后有相关的学习群,有兴趣可以加入。 开始 一、血泪教训:环境变量引发的真实灾难 1.1 …...
飞速(FS)解决方案验证实验室搬迁升级,赋能客户技术服务
飞速(FS)解决方案验证实验室近日顺利完成搬迁升级,标志着飞速(FS)在解决方案可行性验证、质量保障以及定制化需求支持方面迈上新台阶,进一步提升了产品竞争力和客户信任度。 全新升级的实验室定位为技术验证…...
柔性关节双臂机器人奇异摄动鲁棒自适应PD控制
1 双臂机器人动力学模型 对于一个具有多个关节的机器人来说,机器人端动力学子方程及关节驱动电机端动力学子方程为: 以上为推导过程,MATLAB程序已完成,若需要可找我。...
遵循IEC62304YY/T0664:确保医疗器械软件生命周期合规性
一、EC 62304与YY/T 0664的核心定位与关系 IEC 62304(IEC 62304)是国际通用的医疗器械软件生命周期管理标准,适用于所有包含软件的医疗器械(如嵌入式软件、独立软件、移动应用等),其核心目标是确保软件的安…...
Kafka和RocketMQ相比有什么区别?那个更好用?
Kafka和RocketMQ相比有什么区别?那个更好用? Kafka 和 RocketMQ 都是广泛使用的消息队列系统,它们有很多相似之处,但也有一些关键的区别。具体选择哪个更好用,要根据你的应用场景和需求来决定。以下是它们之间的主要区别: 1. …...
空对象模式(Null Object Pattern)在C#中的实现详解
一 、什么是空对象模式 空对象模模是靠”空对孔象式是书丯一种引施丼文行为,行凌,凌万成,个默疤"空象象象象来飞䛿引用用用用电从延盈盈甘仙丿引用用用职从延务在仅代砷易行行 」这种燕式亲如要目的片片 也说媚平父如如 核心思烟 定义一个人 派一个 � 创建…...
【Windows】Win2008服务器SQL服务监控重启脚本
以下是一个用于监控并自动重启 SQL Server 服务的批处理脚本,适用于 Windows Server 2008 和 SQL Server 2012(默认实例): echo off setlocal enabledelayedexpansion:: 配置参数 set SERVICE_NAMEMSSQLSERVER set LOG_FILEC:\SQ…...
Spring MVC 操作会话属性详解(@SessionAttributes 与 @SessionAttribute)
Spring MVC 操作会话属性详解(SessionAttributes 与 SessionAttribute) 1. 核心注解对比 注解作用范围功能SessionAttributes类级别声明控制器中需要持久化的模型属性(存入 HttpSession)SessionAttribute方法参数/返回值显式绑定…...
416. 分割等和子集
416. 分割等和子集 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。 示例 1: 输入:nums [1,5,11,5] 输出:true 解释:数组可以分割成 [1, 5, 5] 和…...
Composer安装Laravel步骤
Composer安装Laravel步骤 要使用 Composer 安装 Laravel,请按照以下步骤操作: 确保已经安装了 Composer。如果还没有安装,请访问 https://getcomposer.org/download/ 下载并安装。 打开命令行或终端。 使用 cd 命令导航到你的项目目录&…...
游戏引擎学习第209天
调整椅子α 昨天,我们实现了将数据输出到调试流中的功能,之前的调试流大多只包含性能分析数据,而现在我们可以将任意数据放入调试流中。 完成这个功能后,我们接下来要做的是收集这些数据并显示出来,这样我们就能有一…...
更新vscode后链接远程服务器出现了报错‘无法建立连接:远程主机不满足运行vscode服务器的先决条件’20250408
更新了vscode之后再链接远程服务器出现了报错,如下: 1. 确认服务器上的库版本 1.1 检查 glibc 版本 在服务器终端运行: ldd --version 最低要求:VS Code 远程开发需要 glibc ≥ 2.28。 1.2 检查 libstdc 版本 在服务器终端运…...
电磁兼容特种测试
并非所有的检测都能在实验室的标准场地中完成。今天,就带大家走进电磁兼容特种测试中需要现场测试的情况,看看哪些场合和设备有着特殊的测试需求。 哪种场合需要现场测试? 大型设备由于物理尺寸或供电功率上的限制,无法在一般…...
PyTorch 基础要点详解:从模型构建到评估
在深度学习领域,PyTorch 作为一款广受欢迎的开源框架,为开发者提供了便捷高效的工具。今天,我们就深入探讨一下 PyTorch 中的几个关键要点:torch.nn.Linear、torch.nn.MSELoss、model.train() 以及 model.eval(),了解它…...
Dockerfile中CMD命令未生效
今天在使用dockerfile构建容器镜像时,最后一步用到CMD命令启动start.sh,但是尝试几遍都未能成功执行脚本。最后查阅得知:Dockerfile中可以有多个cmd指令,但只有最后一个生效,CMD会被docker run之后的参数替换。 CMD会…...