2023年Java核心技术面试第二篇(篇篇万字精讲)

目录

四. 强引用,软引用,弱引用,幻象引用之间的区别?

 1.前言

2.强引用

2.1 强引用赋值为null

2.2 超过了引用的作用域

2.2.1 描述:

2.2.2 作用域内:

2.2.3  不在作用域内:

3. 软引用(SoftReference)

3.1 描述

4. 弱引用(WeakReference)

4.1 解析:

 5. 幻像引用

5.1 描述

5.2 流程图

5.3 解析:

5.3.1 引用队列(ReferenceQueue)的作用主要体现在以下两个方面:

5.3 .2 监控对象的销毁并统计对象的创建和销毁次数

5.3.3 对象清理:

5.4 流程图解析:

5.4.1 强可达(Strongly Reachable)

5.4.2 软可达(Softly Reachable)

5.4.3 弱可达(Weakly Reachable)

5.4.4幻象可达(Phantom Reachable)

5.4.5 最后的状态

五. String,StringBuffer,StringBuilder之间的区别

 1.String

1.1 解析:

1.1.1lmmutable类:

1.1.2 好处:

1.1.3 注意:

1.1.4 字符串操作对应用性能有影响的原因主要包括以下几个方面:

1.1.4.1 内存开销:

1.1.4.2字符串拷贝:

1.1.4.3 时间复杂度:

2. StringBuffer

3. StringBuilder

4. 考点分析:

5.  总结:

5.1 String:

5.1.1 String的创建机理

5.1.2 其运行机制是:

5.1.3 举例:

5.1.4 String的特性

5.1.4.1 不可变

5.1.4.2针对常量池的优化

5.2 StringBuffer/StringBuilder

5.3  应用场景

5.3.1 使用StringBuffer,例如HTTP参数解析与封装

5.3.1.1 多线程环境下使用同步的 StringBuffer 进行字符串拼接的例子

5.3.2 使用 StringBuilder 进行SQL语句拼装和JSON封装的示例:

5.3.2.1 SQL拼接

5.3.2.2 JSON封装


四. 强引用,软引用,弱引用,幻象引用之间的区别?

 1.前言

Java语言中,除了原始数据类型的变量,其他都是引用类型,指向各种不同的对象,理解引用可以帮助掌握Java对象生命周期和JVM内部相关机制

2.强引用

不同引用类型主要体现的是对象不同的可达性(reachable)状态对垃圾收集的影响

强引用("Strong" Reference),即是我们常见的普通对象引用,只要存在强引用指向一个对象,就表明对象还"活着",垃圾收集器不会碰这种对象,对于一个普通的对象,如果没有其他引用关系,只要进行超过了引用的作用域或者将强引用赋值为null,就可以被垃圾回收器收集。

解析内容:

2.1 强引用赋值为null

假设我们有一个Java类"Person"

代码如下:

public class Person {private String name;public Person(String name) {this.name = name;}public String getName() {return name;}
}

现在我们创建一个强引用指向该对象:

Person person = new Person("John");

此时,对象"John"拥有一个强引用person,因此垃圾收集器不会回收该对象。

如果我们将强引用置为null:

person = null;

此时,没有任何强引用指向对象"John",它成为了垃圾对象,可以被垃圾收集器回收。具体的回收时机会根据垃圾收集策略来确定。

2.2 超过了引用的作用域

2.2.1 描述:

当引用超出其作用域时,意味着该引用无法被访问到。在Java中,一个对象的作用域通常是定义它的代码块或方法。

2.2.2 作用域内:

public class ScopeExample {public static void main(String[] args) {Person person; // 在作用域外声明引用{person = new Person("John");System.out.println(person.getName()); // 输出:John}// 在作用域外仍然可以使用person引用System.out.println(person.getName());}
}

2.2.3  不在作用域内:

public class ScopeExample {public static void main(String[] args) {{Person person = new Person("John");System.out.println(person.getName()); // 输出:John}// 此处无法访问person引用,超出了其作用域// System.out.println(person.getName()); }
}

3. 软引用(SoftReference)

3.1 描述

相对于强引用引用弱化一些的引用,可以让对象进行一些垃圾收集,只有当JVM认为内存不足的时候,会尝试进行回收软引用指向的对象。

JVM会确保在抛出OutOfMemoryError之前,进行清理软引用指向的对象。

软引用通常用来实现内存敏感的缓存,如果还有空间内存,可以暂时保留缓存,当内存不足的时候清理掉,保证了使用缓存的同时,不会耗尽内存。

4. 弱引用(WeakReference)

不能使对象豁免垃圾收集,提供一种访问在弱引用状态下对象的途径,构建一种没有特点约束关系,维护一种非维护的映射关系,如果试图获取对象还在,就使用它,否则重现实例化。

4.1 解析:

定义了一个ExpensiveObject类,表示一个耗费资源的对象。通过定义get_object函数和cache字典作为缓存,我们可以使用弱引用来构建非强制性的映射关系。当需要获取对象时,首先检查缓存中是否有对应的弱引用对象,如果存在且未被垃圾回收,则直接返回该对象;否则,重新实例化对象,并将其添加到缓存中。

需要注意的是,由于弱引用并不能阻止对象被垃圾回收,当对象被垃圾回收后,弱引用将返回None。因此,在使用弱引用构建缓存时,需要在适当的时机进行缓存项的更新和清理,以保证缓存数据的正确性和有效性。

import java.lang.ref.WeakReference;class ExpensiveObject {private String name;public ExpensiveObject(String name) {this.name = name;}public String getName() {return name;}
}public class WeakReferenceExample {public static void main(String[] args) {// 缓存示例WeakReference<ExpensiveObject> cache = new WeakReference<>(null);ExpensiveObject obj1 = getOrCreateObject("Example");System.out.println(obj1.getName());  // 输出: ExampleExpensiveObject obj2 = getOrCreateObject("Example");System.out.println(obj2.getName());  // 输出: Example// 因为缓存中已经存在名为"Example"的对象,第二次获取时直接从缓存中获取,并不会重复创建}public static ExpensiveObject getOrCreateObject(String name) {ExpensiveObject obj = null;// 从缓存中获取弱引用对象WeakReference<ExpensiveObject> objRef = cache.get();if (objRef != null) {obj = objRef.get();}if (obj == null) {// 如果缓存中没有对应的对象或对象已经被垃圾回收了,重新创建并缓存obj = new ExpensiveObject(name);cache = new WeakReference<>(obj);}return obj;}
}

 5. 幻像引用

5.1 描述

也叫虚引用,不能通过他访问对象,幻像引用提供了一种确保对象被finalize后,做某些事情的机制,可以用幻象引用监控对象的创建和销毁

5.2 流程图

                                       强引用

5.3 解析:

5.3.1 引用队列(ReferenceQueue)的作用主要体现在以下两个方面:

  1. 监控对象的销毁:通过创建ReferenceQueue<TrackedObject>类型的引用队列referenceQueue,并将幻象引用对象注册到引用队列中:

    phantomReference = new PhantomReference<>(this, referenceQueue);

    TrackedObject对象被垃圾回收器标记为可回收时,对应的幻象引用就会被放入引用队列中。通过检查引用队列中是否存在幻象引用,我们可以得知对象已经被finalize,并且即将被回收。

  2. 统计对象的创建和销毁次数:ObjectTracker类中的trackObjectCreation()trackObjectDestruction()方法用于跟踪对象的创建和销毁次数。在TrackedObject的构造方法中,当对象被创建时,会调用ObjectTracker.trackObjectCreation()方法增加创建次数。而在finalize方法中,会调用destroy()方法,进而调用ObjectTracker.trackObjectDestruction()方法增加销毁次数。

通过结合引用队列、幻象引用和ObjectTracker类,我们可以在程序中监控对象的创建和销毁情况,并获取相应的统计数据。在示例中,通过输出ObjectTracker.getCreatedCount()ObjectTracker.getDestroyedCount(),我们可以分别得到对象的创建次数和销毁次数。

引用队列在该示例中的主要用途是监控对象的销毁并统计对象的创建和销毁次数。

通过引用队列和幻象引用的配合使用,我们可以实现更精确的对象跟踪和资源管理。

循环来检查引用队列中是否有幻象引用。通过调用referenceQueue.poll()方法,我们可以从引用队列中获取幻象引用。如果获取到了幻象引用,则意味着对象已经被finalize,并且即将被回收

5.3 .2 监控对象的销毁并统计对象的创建和销毁次数

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;class ObjectTracker {private static int createdCount = 0;private static int destroyedCount = 0;public static void trackObjectCreation() {createdCount++;}public static void trackObjectDestruction() {destroyedCount++;}public static int getCreatedCount() {return createdCount;}public static int getDestroyedCount() {return destroyedCount;}
}class TrackedObject {private String name;private PhantomReference<TrackedObject> phantomReference;public TrackedObject(String name, ReferenceQueue<TrackedObject> referenceQueue) {this.name = name;phantomReference = new PhantomReference<>(this, referenceQueue);ObjectTracker.trackObjectCreation();}public void destroy() {ObjectTracker.trackObjectDestruction();}
}public class PhantomReferenceMonitoringExample {public static void main(String[] args) throws InterruptedException {ReferenceQueue<TrackedObject> referenceQueue = new ReferenceQueue<>();// 创建对象并跟踪创建次数TrackedObject obj1 = new TrackedObject("Object 1", referenceQueue);TrackedObject obj2 = new TrackedObject("Object 2", referenceQueue);System.out.println("Created count: " + ObjectTracker.getCreatedCount());  // 输出: Created count: 2// 销毁对象并跟踪销毁次数obj1.destroy();obj2.destroy();// 清理引用队列,判断是否存在幻象引用PhantomReference<?> phantomRef;while ((phantomRef = (PhantomReference<?>) referenceQueue.poll()) != null) {System.out.println("Object finalized and ready for destruction: " + phantomRef);}System.out.println("Destroyed count: " + ObjectTracker.getDestroyedCount());  // 输出: Destroyed count: 2}
}

5.3.3 对象清理:

定义了一个ExpensiveObject类,其中重写了finalize方法,在对象被垃圾回收前会执行该方法。通过创建一个幻象引用PhantomReference并指定相应的引用队列ReferenceQueue,我们可以在程序中检查对象是否已经被 finalize。

在主函数中,模拟进行垃圾回收操作,并等待一段时间以确保垃圾回收完成。然后从引用队列中尝试获取幻象引用所引用的对象,如果对象已经被 finalize,则可以通过引用队列获取到幻象引用,否则对象仍然存在。

幻象引用通常与引用队列结合使用,以便在对象被 finalize 后执行特定的操作

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;class ExpensiveObject {private String name;public ExpensiveObject(String name) {this.name = name;}public String getName() {return name;}@Overrideprotected void finalize() throws Throwable {super.finalize();System.out.println("Object " + name + " is finalized.");}
}public class PhantomReferenceExample {public static void main(String[] args) throws InterruptedException {ReferenceQueue<ExpensiveObject> referenceQueue = new ReferenceQueue<>();PhantomReference<ExpensiveObject> phantomReference = new PhantomReference<>(new ExpensiveObject("Example"), referenceQueue);// 模拟垃圾回收动作System.gc();Thread.sleep(1000);  // 等待垃圾回收完成// 检查是否已经被finalizeif (referenceQueue.poll() != null) {System.out.println("Object has been finalized.");} else {System.out.println("Object still exists.");}}
}

5.4 流程图解析:

5.4.1 强可达(Strongly Reachable)

就是当一个对象可以有一个或多个线程可以不通过各种
引用访问到的情况。比如,我们新创建一个对象,那么创建它的线程对它就是强可达。


5.4.2 软可达(Softly Reachable)

就是当我们只能通过软引用才能访问到对象的状态。


5.4.3 弱可达(Weakly Reachable)

类似前面提到的,就是无法通过强引用或者软引用访问,
只能通过弱引用访问时的状态。这是十分临近 finalize 状态的时机,当弱引用被清除的时
候,就符合 finalize 的条件了。


5.4.4幻象可达(Phantom Reachable)

上面流程图已经很直观了,就是没有强、软、弱引用
关联,并且 finalize 过了,只有幻象引用指向这个对象的时候。

5.4.5 最后的状态

就是不可达(unreachable),意味着对象可以被清除了。

除了幻象引用(因为 get 永远返回 null),如果对象还没有被销毁,都可以通过 get 方法获
取原有对象。这意味着,利用软引用和弱引用,我们可以将访问到的对象,重新指向强引用,
也就是人为的改变了对象的可达性状态

五. String,StringBuffer,StringBuilder之间的区别

 1.String

String是Java语言非常重要的类,提供了构造和管理字符串的各种逻辑。

典型的lmmutable类,被声明成final class,所有属性也都是final,由于不可变性,类似拼接,剪裁字符串等动作,都会产生新的String对象。

由于字符串操作的普遍性,所以相关操作的效率往往对应用性能有明细的影响。

1.1 解析:

1.1.1lmmutable类:

Immutable 类是指在对象创建后,其状态无法被修改的类。换句话说,Immutable 类的实例一旦创建就不能被改变。对于 String 类来说,它被设计为 Immutable 类,意味着一旦创建了一个 String 对象,其中包含的字符序列就不能被改变。

1.1.2 好处:

  1. 线程安全:由于 String 类是不可变的,多线程环境下可以保证对象内容的不变性,从而避免了同步操作。
  2. 缓存利用:由于字符串常量是不可变的,因此可以被缓存起来,提高程序的性能和效率。
  3. 安全性:String 对象作为方法参数时,不会被修改,保证了数据的安全性。

1.1.3 注意:

虽然 String 对象本身是不可变的,但是通过反射等手段可以绕过限制,直接修改对象的内部状态。所以在涉及到安全性要求较高的场景中,还是需要额外的措施来保证对象的不可变性。

1.1.4 字符串操作对应用性能有影响的原因主要包括以下几个方面:

1.1.4.1 内存开销:

由于 String 类是不可变的,每次对字符串进行拼接、剪裁等操作都会创建一个新的字符串对象。这就导致了频繁的内存分配和释放,增加了垃圾回收的压力,消耗了额外的内存空间。

1.1.4.2字符串拷贝:

在字符串拼接或者剪裁时,通常涉及到将多个字符串合并为一个新的字符串,或者从原字符串中截取一部分形成新的字符串。这些操作都需要将原始字符串的内容复制到新的字符串对象中,如果字符串长度较大或者操作频繁,将会产生大量的内存拷贝操作,降低了性能。

1.1.4.3 时间复杂度:

某些字符串操作的时间复杂度较高,例如字符串拼接操作的时间复杂度为 O(n^2),其中 n 为字符串的长度。当需要拼接大量的字符串时,操作的时间复杂度会呈现出指数级增长,导致性能下降

2. StringBuffer

解决拼接产生太多中间对象的问题而提供的一个类,可以使用append或者add方法,将字符串添加到已有序列的末尾或者指定位置。

Stringbuffer本质是一个线程安全的可修改字符序列,保证了线程安全,但是也带来了额外的性能开销,所以除非有线程安全的需要,不然还是采用StringBuilder

3. StringBuilder

Java1.5新增加的,在能力上面和StringBuffer没有本质区别,去掉了线程安全的部分,有效的减小了开销,绝大部分情况下字符串拼接的首选。

4. 考点分析:

应用开发离不开操作字符串,理解字符串的设计和实现以及相关工具,拼接类的使用,对于写出高质量代码很有帮助。

5.  总结:

5.1 String:

5.1.1 String的创建机理


由于String在Java世界中使用过于频繁,Java为了避免在一个系统中产生大量的String对象,
引入了字符串常量池。

5.1.2 其运行机制是:

创建一个字符串时,首先检查池中是否有值相同的字符串对象,如果有则不需要创建直接从池中刚查找到的对象引用;如果没有则新建字符串对象,返回对象引用,并且将新创建的对象放入池中。但是,通过new方法创建的String对象是不检查字符串池的,而是直接在堆区或栈区创建一个新的对象,也不会把对象放入池中。

上述原则只适用于通过直接量给String对象引用赋值的情况。


5.1.3 举例:

String str1 = "123"; //通过直接量赋值方式,放入字符串常量池
String str2 = new String(“123”);//通过new方式赋值方式,不放入字符串常量池
注意:String提供了inter()方法。调用该方法时,如果常量池中包括了一个等于此String对象
的字符串(由equals方法确定),则返回池中的字符串。否则,将此String对象添加到池中,
并且返回此池中对象的引用

5.1.4 String的特性


5.1.4.1 不可变

指String对象一旦生成,则不能再对它进行改变。不可变的主要作用在于当一
个对象需要被多线程共享,并且访问频繁时,可以省略同步和锁等待的时间,从而大幅度提
高系统性能。不可变模式是一个可以提高多线程程序的性能,降低多线程程序复杂度的设计
模式。


5.1.4.2针对常量池的优化

当2个String对象拥有相同的值时,他们只引用常量池中的同一个拷
贝。当同一个字符串反复出现时,这个技术可以大幅度节省内存空间

5.2 StringBuffer/StringBuilder


StringBuffer和StringBuilder都实现了AbstractStringBuilder抽象类,拥有几乎一致对外提供的
调用接口。

其底层在内存中的存储方式与String相同,都是以一个有序的字符序列(char类型
的数组)进行存储,不同点是StringBuffer/StringBuilder对象的值是可以改变的,并且值改变
以后,对象引用不会发生改变;两者对象在构造过程中,首先按照默认大小申请一个字符数
组,由于会不断加入新数据,当超过默认大小后,会创建一个更大的数组,并将原先的数组
内容复制过来,再丢弃旧的数组。因此,对于较大对象的扩容会涉及大量的内存复制操作,
如果能够预先评估大小,可提升性能。
唯一需要注意的是:StringBuffer是线程安全的,但是StringBuilder是线程不安全的。

StringBuffer类中方法定义前面都会有synchronize关键字。

因此,StringBuffer的性能要远低于StringBuilder。


5.3  应用场景


在字符串内容不经常发生变化的业务场景优先使用String类。

例如:常量声明、少量的字符串拼接操作等。如果有大量的字符串内容拼接,避免使用String与String之间的“+”操作,因为这样会产生大量无用的中间对象,耗费空间且执行效率低下(新建对象、回收对象花费大量时间)
在频繁进行字符串的运算(如拼接、替换、删除等)并且运行在多线程环境下

5.3.1 使用StringBuffer,例如HTTP参数解析与封装

5.3.1.1 多线程环境下使用同步的 StringBuffer 进行字符串拼接的例子

创建了两个线程 thread1thread2 分别向 StringBuffer 对象 stringBuffer 中追加字符 "A" 和 "B",每个线程追加1000次。由于 StringBuffer 是线程安全的,我们使用 synchronized 关键字对 stringBuffer 进行同步处理,确保每个线程在访问和修改 stringBuffer 时的互斥性。

通过启动两个线程并等待它们执行完成,最后输出 stringBuffer 的长度,可以观察到最终拼接的字符串长度为 2000,证明在多线程环境下使用同步的 StringBuffer 进行字符串拼接是安全和可靠的。

public class ThreadSafeStringBufferExample {public static void main(String[] args) {final StringBuffer stringBuffer = new StringBuffer();// 创建两个线程进行字符串拼接Thread thread1 = new Thread(() -> {for (int i = 0; i < 1000; i++) {synchronized (stringBuffer) {stringBuffer.append("A");}}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 1000; i++) {synchronized (stringBuffer) {stringBuffer.append("B");}}});// 启动线程thread1.start();thread2.start();// 等待线程执行完成try {thread1.join();thread2.join();} catch (InterruptedException e) {e.printStackTrace();}// 输出最终字符串长度System.out.println("Final string length: " + stringBuffer.length());}
}


在频繁进行字符串的运算(如拼接、替换、删除等),并且运行在单线程环境下

建议使用StringBuilder,例如SQL语句拼装、JSON封装等。

SQL语句拼装和JSON封装,建议使用非线程安全的 StringBuilder 类来进行字符串拼接操作。StringBuilder 的性能比线程安全的 StringBuffer 更好,因为它不需要进行同步处理。

5.3.2 使用 StringBuilder 进行SQL语句拼装和JSON封装的示例:

5.3.2.1 SQL拼接

创建了一个 StringBuilder 对象 sql,并使用连续的 append() 方法将 SQL 语句的各个部分拼接起来,包括表名、列名和列值。最后,通过调用 toString() 方法将 StringBuilder 转换为字符串并输出。

public class SQLStatementExample {public static void main(String[] args) {StringBuilder sql = new StringBuilder();String tableName = "users";String columnName = "name";String columnValue = "John Doe";sql.append("SELECT * FROM ").append(tableName).append(" WHERE ").append(columnName).append(" = '").append(columnValue).append("'");String query = sql.toString();System.out.println(query);}
}

输出:

SELECT * FROM users WHERE name = 'John Doe'

使用 StringBuilder 进行 SQL 语句的动态拼装。通过使用非线程安全的 StringBuilder,可以避免多余的同步开销,提高字符串拼接的效率和性能。

5.3.2.2 JSON封装

创建了一个 StringBuilder 对象 json,用于存储 JSON 数据。然后,使用 JSONObjectJSONArray 类来构建 JSON 结构,并将其转换为字符串形式。最后,通过调用 toString() 方法将 StringBuilder 转换为字符串并输出。

import org.json.JSONArray;
import org.json.JSONObject;public class JSONExample {public static void main(String[] args) {StringBuilder json = new StringBuilder();// 创建一个 JSONObject 对象并设置键值对JSONObject person = new JSONObject();person.put("name", "John Doe");person.put("age", 30);person.put("isStudent", false);// 创建一个 JSONArray 对象并添加元素JSONArray hobbies = new JSONArray();hobbies.put("reading");hobbies.put("coding");hobbies.put("gaming");// 将 JSONArray 添加到 JSONObject 中person.put("hobbies", hobbies);// 将 JSONObject 转换为字符串json.append(person.toString());String jsonString = json.toString();System.out.println(jsonString);}
}

输出:

{"name":"John Doe","age":30,"isStudent":false,"hobbies":["reading","coding","gaming"]}

使用 StringBuilder 进行 JSON 数据的封装。通过使用非线程安全的 StringBuilder,可以避免多余的同步开销,提高字符串拼接的效率和性能。

请注意,在多线程环境下进行字符串拼接操作时,如果存在并发访问和修改的情况,建议使用线程安全的 StringBuffer 或采用适当的同步机制来保证数据的一致性和线程安全性。

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

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

相关文章

华为云classroom赋能--Toolkit系列插件DevSecOps助力开发者提速

一、前言 DevOps的概念想必大家都不陌生&#xff0c;它是一组过程、方法与系统的统称&#xff0c;通过它可以对交付速率、协作效率、部署频率速率、质量、安全和可靠性等进行提升改善。相比传统的软件开发模式&#xff0c;它是一种工作方式和文化的转变&#xff0c;把开发者和…

C++笔记之注册的含义

C笔记之注册的含义 code review! 文章目录 C笔记之注册的含义1.注册对象到Qt的信号槽系统中2.注册函数到Qt的元对象系统中元对象系统例1例2 3.注册自定义类型到C STL容器中4.将函数指针传递给另一个类&#xff0c;注册回调函数class ICallback存在的意义例1&#xff0c;用于说…

Python Opencv实践 - 图像中值滤波

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/pomeranian.png", cv.IMREAD_COLOR) print(img.shape) pixel_count img.shape[0] * img.shape[1] print(pixel_count)#为图像添加椒盐噪声 #参考资料&#xf…

Java中异常的详细讲解与细节讨论

用一个代码引出异常为什么要使用异常 代码&#xff1a; public static void main(Sting args[]){int n1 1;int n2 0;System.out.println(n1/n2);//这里会抛ArihmaticException,因为除数不能为0,若未用异常处理机制则程序直接结束&#xff0c;后面的代码将不执行。这样很不好…

windows ipv4 多ip地址设置,默认网关跃点和自动跃点是什么意思?(跃点数)

文章目录 Windows中的IPv4多IP地址设置以及默认网关跃点和自动跃点的含义引言IPv4和IPv6&#xff1a;简介多IP地址设置&#xff1a;Windows环境中的实现默认网关跃点&#xff1a;概念和作用自动跃点&#xff1a;何时使用&#xff1f;关于“跃点数”如何确定应该设置多少跃点数&…

我的创作纪念日(C++修仙练气期总结)

分享自己最喜欢的一首歌&#xff1a;空想フォレスト—伊東歌詞太郎 机缘 现在想想自己在CSDN创作的原因&#xff0c;一开始其实就是想着拿着博客当做自己的学习笔记&#xff0c;笔记嘛&#xff0c;随便写写&#xff0c;自己看得懂就ok了的态度凸(艹皿艹 )。也是用来作为自己学习…

vue3+element下拉多选框组件

<!-- 下拉多选 --> <template><div class"select-checked"><el-select v-model"selected" :class"{ all: optionsAll, hidden: selectedOptions.data.length < 2 }" multipleplaceholder"请选择" :popper-app…

vite 项目搭建

1. 创建 vite 项目 npm create vite@latest 2. 安装sass/less ( 一般我使用sass ) cnpm add -D sasscnpm add -D less 3. 自动导入 两个插件 使用之后,不用导入vue中hook reactive ref cnpm install -D unplugin-vue-components unplugin-auto-import 在 vite.config.…

STM32设置为I2C从机模式(HAL库版本)

STM32设置为I2C从机模式&#xff08;HAL库版本&#xff09; 目录 STM32设置为I2C从机模式&#xff08;HAL库版本&#xff09;前言1 硬件连接2 软件编程2.1 步骤分解2.2 测试用例 3 运行测试3.1 I2C连续写入3.2 I2C连续读取3.3 I2C单次读写测试 4 总结 前言 我之前出过一篇关于…

Claude 2 国内镜像站

Claudeai是什么&#xff1f; Claude 2被称为ChatGPT最强劲的竞争对手&#xff0c;支持100K上下文对话&#xff0c;并且可以同时和5个文档进行对话&#xff0c;不过国内目前无法正常实用的&#xff0c;而claudeai是一个Claude 2 国内镜像站&#xff0c;并且免翻可用&#xff0…

实验三 HBase1.2.6安装及配置

系列文章目录 文章目录 系列文章目录前言一、HBase1.2.6的安装二、HBase1.2.6的配置2.1 单机模式配置2.2 伪分布式模式配置 总结参考 前言 在安装HBase1.2.6之前&#xff0c;需要安装好hadoop2.7.6。 本篇文章参考&#xff1a;HBase2.2.2安装和编程实践指南 一、HBase1.2.6的安…

Android---- 一个完整的小项目(消防app)

前言&#xff1a; 针对不同群体的需求&#xff0c;想着应该拓展写方向。医疗app很受大家喜欢&#xff0c;就打算顺手写个消防app&#xff0c;里面基础框架还是挺简洁 规整的。登陆注册和本地数据库写的便于大家理解。是广大学子的毕设首选啊&#xff01; 此app主要为了传递 消防…

代码随想录打卡—day24—【回溯】— 基础最新8.20+8.22

1 理论基础 回溯法也可以叫做回溯搜索法&#xff0c;它是一种搜索的方式。回溯算法——回溯和递归是相辅相成的。回溯法的效率&#xff0c;回溯法其实就是暴力查找&#xff0c;并不是什么高效的算法。回溯法解决的问题都可以抽象为树形结构&#xff08;N叉树&#xff09; 1.1…

redis 7高级篇1 redis的单线程与多线程

一 redis单线程与多线程 1.1 redis单线程&多线程 1.redis的单线程 redis单线程主要是指Redis的网络IO和键值对读写是由一个线程来完成的&#xff0c;Redis在处理客户端的请求时包括获取 (socket 读)、解析、执行、内容返回 (socket 写) 等都由一个顺序串行的主线程处理…

【第三阶段】kotlin语言的内置函数let

1.使用普通方法对集合的第一个元素相加 fun main() {//使用普通方法对集合的第一个元素相加var list listOf(1,2,3,4,5)var value1list.first()var resultvalue1value1println(result) }执行结果 2.使用let内置函数对集合的第一个元素相加 package Stage3fun main() {//使用…

Android进阶之路 - 去除EditText内边距

正如题名&#xff0c;在Android中的EditText是自带内边距的&#xff0c;常规而言设置背景为null即可&#xff0c;但是因为使用了并不熟悉的声明式框架&#xff0c;本是几分钟解决的事儿&#xff0c;却花费了小半天~ 简单的需求&#xff0c;相关blog Android进阶之路 - 去除Edi…

探索智能文字识别:技术、应用与发展前景

探索智能文字识别&#xff1a;技术、应用与发展前景 前言一张图全览大赛作品解读随心记你不对我对小结 智能文字识别体系化解读图像预处理文字定位和分割文字区域识别图像校正字体识别和匹配结果后处理小结 如何应对复杂场景下挑战复杂场景应对方法小结 人才时代对人才要求合合…

MyBatis快速入门以及环境搭建和CRUD的实现

目录 前言 一、MyBatis简介 1.MyBatis是什么 2.MyBatis的特点 3.mybatis的作用 4.MyBatis的应用场景 5.MyBatis优缺点 二、相关概念 1.ORM概述 2.常见的ORM框架 3.什么是持久层框架 三、MyBatis的工作原理 1.框架交互 2.工作原理 ​编辑 四、MyBatis环境搭建 1…

Linux Kernel 4.12 或将新增优化分析工具

到 7 月初&#xff0c;Linux Kernel 4.12 预计将为修复所有安全漏洞而奠定基础&#xff0c;另外新增的是一个分析工具&#xff0c;对于开发者优化启动时间时会有所帮助。 新的「个别任务统一模型」&#xff08;Per-Task Consistency Model&#xff09;为主要核心实时修补&#…

软件开发之低代码平台实践

一、低代码、零代码、纯代码定义 低代码开发平台使企业在不编写大量代码的情况下快速创建复杂应用程序。与传统的纯代码开发相比&#xff0c;低代码开发能够大大减少开发周期&#xff0c;并降低技术门槛&#xff0c;使得开发过程更加高效。而零代码开发更进一步简化了开发过程&…