当前位置: 首页 > news >正文

Java基础面试题总结(题目来源JavaGuide)

问题1:Java 中有哪 8 种基本数据类型?它们的默认值和占用的空间大小知道不? 说说这 8 种基本数据类型对 应的包装类型。

在 Java 中,有 8 种基本数据类型(Primitive Types):

基本数据类型关键字默认值占用空间对应的包装类
整数类型
字节型 (byte)byte01 字节 (8 bit)Byte
短整型 (short)short02 字节 (16 bit)Short
整型 (int)int04 字节 (32 bit)Integer
长整型 (long)long0L8 字节 (64 bit)Long
浮点数类型
单精度浮点型 (float)float0.0f4 字节 (32 bit)Float
双精度浮点型 (double)double0.0d8 字节 (64 bit)Double
字符类型
字符型 (char)char\u0000(空字符)2 字节 (16 bit)Character
布尔类型
布尔型 (boolean)booleanfalseJVM 规范未明确大小(通常 1 bit)Boolean

额外说明:

  1. boolean 的存储大小依赖于 JVM 实现,通常使用 1 bit(但实际存储可能会占据 1 字节)。
  2. char 采用 Unicode 编码,所以它占用 2 字节
  3. 包装类(Wrapper Classes)java.lang 包中,提供了基本类型的对象封装,并支持自动装箱(Autoboxing)和拆箱(Unboxing)。

问题2:包装类型的常量池技术了解么?

1. 什么是包装类型的常量池?

Java 的 ByteShortIntegerLongCharacterBoolean 类在一定范围内会缓存对象,避免重复创建,提高性能


2. 包装类常量池的示例

(1) Integer 缓存池

public class WrapperCacheTest {public static void main(String[] args) {Integer a = 127;Integer b = 127;System.out.println(a == b); // true,使用缓存Integer c = 128;Integer d = 128;System.out.println(c == d); // false,超出缓存范围,创建新对象}
}

解析:

  • Integer a = 127;Integer b = 127; 指向同一个缓存对象,所以 a == btrue
  • Integer c = 128;Integer d = 128; 超出缓存范围,创建不同对象,c == dfalse

(2) Boolean 常量池

Boolean bool1 = true;
Boolean bool2 = true;
System.out.println(bool1 == bool2); // true

Boolean 只有 TRUEFALSE 两个缓存对象,所以 bool1 == bool2 始终为 true

(3) Character 缓存池

Character char1 = 127;
Character char2 = 127;
System.out.println(char1 == char2); // trueCharacter char3 = 128;
Character char4 = 128;
System.out.println(char3 == char4); // false

Character 只缓存 0 ~ 127,超出范围会创建新对象。

3. 为什么 FloatDouble 没有缓存池?

Float f1 = 1.0f;
Float f2 = 1.0f;
System.out.println(f1 == f2); // false,每次创建新对象Double d1 = 1.0;
Double d2 = 1.0;
System.out.println(d1 == d2); // false,每次创建新对象
原因
  • 浮点数范围太大,缓存意义不大。
  • 浮点数计算常常涉及小数误差,缓存可能会导致不稳定的行为。

4. valueOf()new 的区别

(1) 使用 valueOf()

Integer x = Integer.valueOf(127);
Integer y = Integer.valueOf(127);
System.out.println(x == y); // true

valueOf() 方法使用缓存池,所以 x == ytrue

(2) 使用 new Integer()

Integer x = new Integer(127);
Integer y = new Integer(127);
System.out.println(x == y); // false

new Integer() 直接创建新对象,不使用缓存,所以 x == yfalse

最佳实践:推荐使用 valueOf(),避免 new 关键字,以减少内存开销。

5. equals() 比较推荐

由于 == 比较的是对象地址,而 equals() 比较的是,建议用 equals() 进行数值比较:

Integer a = 128;
Integer b = 128;
System.out.println(a.equals(b)); // true,比较值,结果正确System.out.println(a == b); // false,比较对象地址,超出缓存范围

6. 总结

包装类缓存范围缓存机制
Byte-128 ~ 127使用缓存
Short-128 ~ 127使用缓存
Integer-128 ~ 127(可扩展)使用缓存,可调整 -XX:AutoBoxCacheMax
Long-128 ~ 127使用缓存
Character0 ~ 127使用缓存
Boolean只有 truefalse使用缓存
Float无缓存每次创建新对象
Double无缓存每次创建新对象

✅ 最佳实践:

  1. 使用 valueOf() 代替 new 关键字。
  2. 使用 equals() 而不是 == 进行值比较。
  3. 了解缓存范围,避免意外的 == 结果。

问题3:为什么要有包装类型?

Java 之所以引入 包装类型(Wrapper Classes),主要是为了让基本数据类型(primitive types)具备对象的特性,方便在面向对象编程(OOP)中使用,同时增强泛型、集合框架等的兼容性。

1. 基本数据类型不是对象

Java 中有 8 种基本数据类型intcharbooleanfloat 等),它们的设计目标是提高性能,但它们不是对象:

int a = 10;
a.toString();  // ❌ 编译错误,int 没有方法
  • 不能直接调用方法。
  • 不能存储在**集合(Collection)**中。
  • 不能作为泛型的类型参数。

2. 包装类弥补了基本类型的不足

Java 提供了 对应的包装类型IntegerDoubleBoolean 等),它们是,可以像对象一样使用:

Integer num = 10;
System.out.println(num.toString()); // ✅ 10
  • 允许基本类型调用方法(比如 toString())。
  • 能够存入 泛型集合(如 ArrayList<Integer>)。
  • 支持 自动装箱/拆箱,让基本类型和对象能无缝转换。

3. 适用于 Java 集合框架

Java 集合(如 ArrayListHashMap只能存储对象,不能存储基本类型:

ArrayList<int> list = new ArrayList<>(); // ❌ 编译错误

必须使用包装类

ArrayList<Integer> list = new ArrayList<>();
list.add(10); // ✅ 自动装箱:int → Integer

原因:Java 泛型(Generics)不支持基本类型,但支持对象。

4. 支持泛型(Generics)

泛型不能直接使用基本类型:

public class Box<T> {private T value;public void set(T value) { this.value = value; }public T get() { return value; }
}Box<int> box = new Box<>(); // ❌ 编译错误

必须使用包装类型

Box<Integer> box = new Box<>();
box.set(100); // ✅ 自动装箱:int → Integer
int num = box.get(); // ✅ 自动拆箱:Integer → int

泛型只能接受对象,所以 int 不能直接用,而 Integer 作为对象可以使用。

5. 具备更多功能

包装类提供了丰富的方法,可以方便地进行类型转换、数学运算等:

String str = "123";
int num = Integer.parseInt(str); // ✅ String → int
double d = Double.parseDouble("3.14"); // ✅ String → double

基本类型无法进行字符串解析,但包装类可以。

6. 适用于多线程中的同步

基本类型是线程不安全的,而包装类(如 AtomicInteger)可以在多线程环境下使用:

AtomicInteger count = new AtomicInteger(0);
count.incrementAndGet(); // ✅ 线程安全的自增

适用于高并发场景

7. 支持 null

基本类型不能存储 null,但包装类型可以:

Integer num = null; // ✅ 合法
int n = null;  // ❌ 编译错误

数据库操作时,某些字段可能为空,包装类更合适。

总结

基本数据类型包装类的作用
不是对象让基本类型具备对象特性
不能存集合支持泛型和集合框架
无方法包装类提供丰富的方法
不支持 null包装类支持 null
非线程安全包装类有线程安全实现

最佳实践

  • 优先使用基本类型(性能更好),只在需要对象时才用包装类。
  • 避免不必要的自动装箱/拆箱,以提高性能。

问题4:什么是自动拆装箱?原理?

自动装箱(Autoboxing)自动拆箱(Unboxing)Java 5 引入的特性,使得基本数据类型(intcharboolean 等)和它们的包装类IntegerCharacterBoolean 等)之间可以自动转换,简化代码编写。

1. 自动装箱(Autoboxing)

把基本数据类型 自动转换成 对应的包装类对象

Integer num = 10;  // 相当于 Integer num = Integer.valueOf(10);
  • 10int 类型,自动转换为 Integer 对象。
  • 底层调用 Integer.valueOf(int) 方法,如果在 -128 ~ 127 之间,会使用缓存池,否则创建新对象。

2. 自动拆箱(Unboxing)

把包装类对象 自动转换成 基本数据类型

Integer num = 10;  // 自动装箱
int a = num;       // 自动拆箱,相当于 int a = num.intValue();
  • numInteger 对象,自动转换成 int 类型。
  • 底层调用 num.intValue() 方法

3. 自动装箱/拆箱的使用示例

public class AutoBoxingDemo {public static void main(String[] args) {// 自动装箱:基本类型 → 包装类Integer a = 100; // 相当于 Integer a = Integer.valueOf(100);// 自动拆箱:包装类 → 基本类型int b = a; // 相当于 int b = a.intValue();// 自动装箱 + 计算 + 自动拆箱Integer c = 200;int d = c + 300; // c 先自动拆箱,再加 300,最后结果赋值给 int 类型的 d// 直接存入集合ArrayList<Integer> list = new ArrayList<>();list.add(10); // 自动装箱// 取出时自动拆箱int e = list.get(0);System.out.println("b = " + b); // 100System.out.println("d = " + d); // 500System.out.println("e = " + e); // 10}
}

问题5:遇到过自动拆箱引发的 NPE 问题吗?

1. 自动拆箱导致 NullPointerException 的示例

(1) null 赋值给基本类型

public class UnboxingNPE {public static void main(String[] args) {Integer num = null; // num 为空int value = num;    // 自动拆箱:num.intValue(),导致 NPESystem.out.println(value);}
}

原因

  • int value = num; 触发自动拆箱,本质上调用了 num.intValue()
  • 由于 numnull,调用 intValue() 抛出 NullPointerException

2. 真实场景中的 NPE

(1) 集合取值时自动拆箱

import java.util.*;public class UnboxingNPE {public static void main(String[] args) {Map<String, Integer> scores = new HashMap<>();scores.put("Alice", 95);scores.put("Bob", null); // Bob 没有分数int bobScore = scores.get("Bob"); // NPE: null 不能拆箱成 intSystem.out.println("Bob's score: " + bobScore);}
}

原因

  • scores.get("Bob") 返回 null,然后 int bobScore = null; 触发自动拆箱,抛出 NullPointerException

解决方案

方式 1:手动检查 null

Integer bobScore = scores.get("Bob");
int score = (bobScore != null) ? bobScore : 0; // 避免 NPE

方式 2:使用 getOrDefault()

int bobScore = scores.getOrDefault("Bob", 0); // 直接提供默认值

(2) 数据库查询结果可能为 null

public class UnboxingNPE {public static Integer getUserAgeFromDB() {return null; // 模拟数据库查询不到数据}public static void main(String[] args) {int age = getUserAgeFromDB(); // NPESystem.out.println("User age: " + age);}
}

解决方案

  • 使用 Optional 处理 null
Optional<Integer> ageOpt = Optional.ofNullable(getUserAgeFromDB());
int age = ageOpt.orElse(0); // 如果为空,默认值 0

3. 避免自动拆箱 NPE 的最佳实践

方法示例优点
手动 null 检查(num != null) ? num : 0直接避免 NPE
使用 getOrDefault()map.getOrDefault("key", 0)适用于 Map
使用 OptionalOptional.ofNullable(val).orElse(0)更优雅的 null 处理
避免包装类用于计算int sum = 0; 代替 Integer sum = 0;避免不必要的拆装箱

总结

  • 自动拆箱会导致 NullPointerException,如果变量可能为 null,一定要做 null 检查!
  • 使用 getOrDefault()Optional 等方法来避免 NPE
  • 避免在计算时使用 Integer 等包装类,尽量使用基本类型。

问题6:String、StringBuffer 和 StringBuilder 的区别是什么? String 为什么是不可变的?

1. StringStringBufferStringBuilder 的区别

在 Java 中,StringStringBufferStringBuilder 都是用于表示字符串的类,但它们的可变性、线程安全性和性能不同。

特性String (不可变)StringBuffer (可变 & 线程安全)StringBuilder (可变 & 非线程安全)
可变性不可变 (final char[])可变 (char[] 数组)可变 (char[] 数组)
线程安全性线程安全线程安全 (同步 synchronized)非线程安全
性能(每次修改都会创建新对象)较慢(线程安全的同步开销)最快(无同步机制)
适用场景少量字符串处理(如字符串常量、少量拼接)多线程环境(字符串频繁修改)单线程高性能需求(字符串频繁修改)

2. 为什么 String 是不可变的?

String 在 Java 中是 不可变对象(Immutable),一旦创建就不能修改。这是由于以下几个原因:

(1) String 内部使用 final char[] 存储数据

查看 String 类的源码:

public final class String implements java.io.Serializable, Comparable<String> {private final char value[];
}
  • valuefinal 类型的 字符数组 (char[]),所以它的引用不能被修改。
  • 不可变String 类不提供修改 char[] 内容的方法,如 setCharAt(),只能通过创建新对象改变值。

(2) 线程安全

由于 String 不可变,所以它天然是线程安全的,多个线程可以安全地共享同一个 String 对象,而不用加锁

例如:

String str1 = "Hello";
String str2 = str1; // 共享同一个对象

由于 str1 是不可变的,str2 也不会因为 str1 的改变而受到影响。

(3) String 常量池优化

在 Java 中,String 对象会存储在字符串常量池(String Pool)中,避免重复创建:

String s1 = "Hello";
String s2 = "Hello";
System.out.println(s1 == s2); // true, 指向同一个对象
  • s1s2 指向的是同一个字符串常量池对象,而不会新建对象,减少内存占用。

如果 String 是可变的,这个优化就会导致数据混乱

s1.toUpperCase(); // 如果 String 可变,s2 也会被改变,破坏了安全性!

(4) hashCode() 设计

  • String 是不可变的,所以它的 hashCode() 在创建时就计算好并缓存,提高了 Hash 相关操作(如 HashMap)的性能:
public int hashCode() {int h = hash;if (h == 0 && value.length > 0) {for (char val : value) {h = 31 * h + val;}hash = h;}return h;
}

由于 hashCode 不变,String 可以安全地作为 HashMapkey,不必担心 key 被修改导致哈希值变化。

3. StringBufferStringBuilder 的区别

StringBufferStringBuilder 都是 可变的字符串类,但它们的主要区别是线程安全性

(1) StringBuffer 是线程安全的

  • StringBuffer 方法使用 synchronized 关键字,保证线程安全:
public synchronized StringBuffer append(String str) { ... }
  • 适用于多线程环境,但由于同步锁的存在,性能比 StringBuilder 低。

示例:

StringBuffer sb = new StringBuffer("Hello");
sb.append(" World");
System.out.println(sb); // Hello World

(2) StringBuilder 是非线程安全的

  • StringBuilder 没有同步机制,所以性能更高,适用于单线程环境:
public StringBuilder append(String str) { ... } // 无 synchronized
  • 单线程环境推荐使用 StringBuilder,比 StringBuffer 更快。

示例:

StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");
System.out.println(sb); // Hello World

4. 何时使用 StringStringBufferStringBuilder

需求推荐使用原因
少量字符串拼接String代码简洁,性能影响不大
大量字符串拼接(单线程)StringBuilder最高性能,无同步开销
大量字符串拼接(多线程)StringBuffer线程安全,防止并发问题

5. 关键总结

  1. String 是不可变的,存储在字符串常量池中,适用于少量字符串操作
  2. StringBuffer 是线程安全的,使用 synchronized,适用于多线程环境
  3. StringBuilder 是非线程安全的,但性能最好,适用于单线程高性能场景
  4. 推荐:
    • 少量拼接用 String(简洁)。
    • 单线程高性能用 StringBuilder
    • 多线程环境用 StringBuffer

问题7:重载和重写的区别?

重载(Overloading)重写(Overriding) 是 Java 中**多态(Polymorphism)**的重要表现形式。它们的主要区别如下:

方法重载(Overloading)方法重写(Overriding)
定义同一个类中,方法名相同,参数列表不同(参数个数或类型不同)父类和子类之间,方法名、参数列表都相同,子类对父类的方法进行重新实现
方法名必须相同必须相同
参数列表必须不同(参数类型、数量或顺序)必须相同
返回值可以不同必须相同或是父类返回值的子类(协变返回类型)
访问修饰符可以不同不能更严格,但可以更宽松
抛出异常可以不同不能抛出比父类更大的异常(可以抛出更小的或不抛出异常)
发生范围同一个类内部子类继承父类后
是否依赖继承不需要继承必须有继承关系
调用方式通过方法签名的不同,在编译时决定调用哪个方法(静态绑定,编译期多态通过子类对象调用,运行时决定调用哪个方法(动态绑定,运行期多态

 问题8:== 和 equals() 的区别

在 Java 中,==equals() 都可以用来比较对象,但它们的本质、适用范围和行为有所不同。

比较项==(引用/值比较)equals()(对象内容比较)
比较方式比较内存地址(引用)比较对象的内容(可重写)
适用范围基本数据类型引用类型只能用于对象
默认行为对于对象,默认比较地址Object 类的 equals() 方法)需要重写 equals() 方法以比较内容
适用于基本数据类型的值比较引用是否相同判断两个对象是否逻辑相等

1. == 的行为

(1) 用于基本数据类型

对于 基本数据类型intdoublecharboolean 等),== 直接比较值

int a = 10;
int b = 10;
System.out.println(a == b); // true,值相等

(2) 用于引用类型

对于 引用类型(对象),== 比较的是 对象在内存中的地址(是否指向同一对象):

String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2); // false,不是同一个对象

虽然 s1s2 的内容相同,但它们指向不同的内存地址,所以 == 返回 false

(3) == 在字符串常量池中的行为

Java 的 字符串常量池 机制会让相同的字符串共享内存

String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2); // true,指向相同的字符串池对象

但如果用 new 关键字创建字符串:

String s1 = new String("hello");
String s2 = "hello";
System.out.println(s1 == s2); // false,s1 在堆中,s2 在字符串池

2. equals() 的行为

(1) Object 类的默认 equals()

Java 中所有类默认继承 Object,其 equals() 方法默认也是比较内存地址

class Person {}
public class Test {public static void main(String[] args) {Person p1 = new Person();Person p2 = new Person();System.out.println(p1.equals(p2)); // false,不同对象}
}

== 行为相同。

2) String 类重写了 equals()

String 类重写了 equals(),改为比较字符串的内容

String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1.equals(s2)); // true,比较的是内容

尽管 s1s2 指向不同的对象,但 equals() 比较的是字符内容,所以返回 true

3) 自定义类重写 equals()

如果想让 自定义类 按内容比较,需要重写 equals()

class Person {String name;Person(String name) {this.name = name;}@Overridepublic boolean equals(Object obj) {if (this == obj) return true; // 判断是否是同一对象if (obj == null || getClass() != obj.getClass()) return false;Person person = (Person) obj;return this.name.equals(person.name); // 按 name 比较}
}public class Test {public static void main(String[] args) {Person p1 = new Person("Alice");Person p2 = new Person("Alice");System.out.println(p1.equals(p2)); // true,内容相同}
}

这里 p1p2 是不同对象,但 equals() 被重写为比较 name,所以返回 true

3. == vs equals() 总结

比较项==equals()
基本数据类型比较值不能用
对象引用比较地址默认比较地址,但可重写
String

比较地址

比较内容(已重写)
可否重写不可重写可重写,按需求自定义逻辑
适用场景判断是否为同一对象判断对象内容是否相等

4. 推荐使用方式

1.基本数据类型用 ==

int a = 100;
int b = 100;
System.out.println(a == b); // true

2.引用类型判断是否为同一个对象用 ==

String s1 = "hello";
String s2 = new String("hello");
System.out.println(s1 == s2); // false,不是同一个对象

3.判断对象内容是否相等用 equals()

String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1.equals(s2)); // true,内容相同

4.对于自定义对象,重写 equals() 方法

class Person {String name;@Overridepublic boolean equals(Object obj) { ... }
}

 问题9:Java 反射?反射有什么优点/缺点?你是怎么理解反射的(为什么框架需要反射)?

Java 反射(Reflection)概述

Java 反射是 Java 提供的一种强大功能,它允许我们在运行时 动态地获取类的信息(如类的方法、字段、构造方法等),并对它们进行操作。通过反射,我们可以 动态地创建对象、调用方法、访问属性,甚至可以在运行时加载类。

反射的基本概念

  1. Class:Java 中所有类的元数据都由 Class 类表示。通过 Class 类,你可以获得类的构造方法、字段、方法等信息。
  2. Method:通过反射可以获取类的所有方法并执行它们。
  3. Field:通过反射可以访问类的字段。
  4. Constructor:通过反射可以创建类的实例。

常用反射操作示例

import java.lang.reflect.*;class Person {private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}public void sayHello() {System.out.println("Hello, my name is " + name);}private void privateMethod() {System.out.println("This is a private method.");}
}public class ReflectionExample {public static void main(String[] args) throws Exception {// 获取类的 Class 对象Class<?> clazz = Class.forName("Person");// 获取构造方法并创建实例Constructor<?> constructor = clazz.getConstructor(String.class, int.class);Object person = constructor.newInstance("Alice", 25);// 调用方法Method method = clazz.getMethod("sayHello");method.invoke(person);// 获取私有方法并调用Method privateMethod = clazz.getDeclaredMethod("privateMethod");privateMethod.setAccessible(true); // 设置可访问privateMethod.invoke(person);}
}

输出

Hello, my name is Alice
This is a private method.

在这个例子中,我们使用反射:

  • 获取类的 Class 对象
  • 通过构造方法创建对象
  • 调用公开方法 sayHello
  • 调用私有方法 privateMethod,并通过 setAccessible(true) 让私有方法可以被访问。

反射的优点

  1. 动态性

    • 反射允许你在运行时 动态地加载类动态地创建对象,以及 动态地调用方法,这让程序可以非常灵活地应对不同的情况。
    • 例如,Spring 框架使用反射来根据配置文件 自动注入依赖,而不需要在代码中硬编码类。
  2. 灵活性

    • 通过反射,你可以访问类的私有方法和字段,甚至是 访问不存在的类成员,这使得在某些场景下,开发者可以灵活处理一些特殊情况。
  3. 框架和库的开发

    • 框架和库(例如 Hibernate、Spring、JUnit)通过反射来实现灵活的功能。通过反射,框架可以在运行时了解类的信息并做出相应的处理,而无需显式地了解每个类。
  4. 与遗留代码的兼容性

    • 使用反射可以访问没有源代码的类,例如,在 Java 库中使用的第三方库或组件,反射可以帮助在运行时动态地调用和修改类成员。

反射的缺点

  1. 性能开销

    • 反射操作通常比直接调用方法慢得多,因为它会绕过编译时的类型检查。每次反射都会涉及到一些额外的计算(如查找方法、创建实例等),因此 性能开销较大
    • 对于需要频繁调用的代码,反射可能会导致性能瓶颈。
  2. 安全性问题

    • 反射可以访问类的私有成员,这可能会暴露 敏感数据 或者 破坏类的封装性,带来 安全隐患。因此,反射有时会被禁用,尤其是在安全敏感的应用中
  3. 代码可读性和可维护性差

    • 使用反射的代码不如普通的面向对象代码清晰和易于理解。因为你不能通过直接查看代码或接口来确定一个类的行为,反射代码可能会变得难以调试和维护
  4. 错误较难发现

    • 反射的代码通常在编译时无法捕获错误,错误通常会在运行时出现,这使得 调试变得困难
    • 例如,反射可能会尝试调用不存在的方法,或者访问不存在的字段,这些问题通常只有在程序运行时才能被发现。

为什么框架需要反射

许多框架(如 Spring、Hibernate)依赖反射来实现灵活的配置和动态行为。反射为框架提供了以下几方面的优势:

  1. 依赖注入

    • Spring 框架通过反射来实现 依赖注入。当应用启动时,Spring 容器会通过反射获取各个类的构造方法、属性等信息,然后根据配置自动为类注入所需的依赖。
  2. 动态代理

    • 在 AOP(面向切面编程)中,Spring 使用反射技术生成 动态代理类,通过代理对象的反射,拦截目标方法的执行,实现诸如日志记录、事务控制等功能。
  3. ORM(对象关系映射)

    • Hibernate 等 ORM 框架通过反射来将 数据库表映射成 Java 对象,并实现自动的持久化操作。通过反射,Hibernate 可以动态地从类中获取字段信息,将数据持久化到数据库。
  4. 配置和扩展性

    • 反射为框架提供了 高度的扩展性,使得框架可以在运行时动态地加载不同的类或组件,而不需要在编译时知道所有的细节。比如,插件式框架可以通过反射动态加载和调用外部插件。

总结

  • 反射是 Java 提供的一种强大机制,可以在运行时动态地获取类的信息并操作它们。
  • 反射的优点包括 动态性、灵活性,尤其适用于框架开发和与遗留代码的兼容。
  • 然而,反射也有一些缺点,主要是 性能开销、代码可维护性差、潜在的安全隐患
  • 框架需要反射,主要是为了提供 灵活的依赖注入、动态代理、对象关系映射 等功能,以便在运行时根据需求灵活调整。

问题10:谈谈对 Java 注解的理解,解决了什么问题?

Java 注解概述

Java 注解是一种提供元数据的机制,用于向代码中添加额外的信息,通常通过反射等方式进行处理。它本身不直接影响程序执行,但可以提供对代码的附加信息,用于编译检查、代码生成、运行时处理等。

注解解决的问题

  1. 简化代码和配置: 注解帮助减少配置文件或硬编码,提升开发效率。比如在 Spring 中使用 @Autowired 注解自动注入依赖。

  2. 提高可读性: 注解使得代码自文档化,开发者能通过注解清晰地知道代码的意图。例如,@Override 注解标明方法是覆盖父类方法。

  3. 自动化处理: 通过注解和反射,框架能够自动化处理某些功能,如 Spring 框架通过 @RequestMapping 处理 HTTP 请求。

  4. 验证和编译时检查: 使用注解可以进行数据验证或编译时检查,比如 @NotNull 注解确保字段或参数不为 null

注解的常见用途

  • 依赖注入(Spring 中使用 @Autowired 自动注入)。
  • ORM 映射(Hibernate 使用 @Entity 注解映射类到数据库表)。
  • Web 请求映射(Spring MVC 使用 @RequestMapping 映射 URL)。
  • 验证(Hibernate Validator 使用 @NotNull@Size 等注解)。

优缺点

优点

  • 简化配置和代码,减少硬编码。
  • 提高代码可读性和维护性。
  • 自动化处理,减少重复代码。

缺点

  • 性能开销:反射和注解处理可能影响性能。
  • 调试困难:注解的实际作用通常由框架处理,调试较为复杂。

问题11:内部类了解吗?匿名内部类了解吗?

内部类(Inner Class)概述

Java 中的 内部类 是指在一个类的内部定义的类。内部类能够访问外部类的成员(包括私有成员),并且可以通过外部类的实例创建。

内部类的类型

1.成员内部类: 定义在外部类的成员位置,可以访问外部类的所有成员(包括私有成员)。

class Outer {private String name = "Outer class";class Inner {public void display() {System.out.println(name); // 可以访问外部类的私有成员}}
}

2.静态内部类: 使用 static 修饰的内部类,它不能访问外部类的非静态成员,必须通过外部类的类名来访问。静态内部类的实例可以独立于外部类的实例存在。

class Outer {private static String message = "Static Inner Class";static class StaticInner {public void show() {System.out.println(message); // 只能访问外部类的静态成员}}
}

3.局部内部类: 定义在方法内部的类,通常是局部变量的一部分。它只能在方法内部使用。

class Outer {public void outerMethod() {class LocalInner {public void display() {System.out.println("Local inner class");}}LocalInner local = new LocalInner();local.display();}
}

4.匿名内部类: 是没有名字的内部类,通常用于简化代码,特别是在事件监听器和回调中常用。匿名内部类的语法通常是直接在创建对象的同时定义类,省去了定义内部类的步骤。

匿名内部类

匿名内部类是 没有类名 的内部类,它通过继承一个类或实现一个接口来创建一个新的类实例。通常,匿名内部类用于需要创建类的实例并立即使用的场景,尤其是在接口的回调方法、事件监听器等情况下。

匿名内部类的语法

ClassName obj = new ClassName() {// 重写类的方法@Overridepublic void method() {System.out.println("Method implemented in anonymous class");}
};

使用匿名内部类的例子

1.实现接口

interface Greeting {void greet(String name);
}public class AnonymousInnerClassExample {public static void main(String[] args) {// 匿名内部类实现接口Greeting greeting = new Greeting() {@Overridepublic void greet(String name) {System.out.println("Hello, " + name);}};greeting.greet("Alice");}
}

2.继承类

class Animal {void sound() {System.out.println("Animal makes sound");}
}public class AnonymousInnerClassExample {public static void main(String[] args) {// 匿名内部类继承类Animal animal = new Animal() {@Overridevoid sound() {System.out.println("Dog barks");}};animal.sound();}
}

匿名内部类的特点

  1. 简洁性:它可以让你在创建对象的同时定义类,而不需要显式地定义一个新类。
  2. 不能有构造器:匿名内部类没有名称,因此不能定义构造器。
  3. 只能继承一个类或实现一个接口:匿名内部类必须继承一个类或者实现一个接口,不能多重继承。
  4. 常用于事件监听:在 GUI 编程中,匿名内部类常用来实现事件监听器等。

问题12:BIO,NIO,AIO 有什么区别? 

BIO(Blocking I/O)、NIO(Non-blocking I/O)和 AIO(Asynchronous I/O)是 Java 中三种不同的 I/O 模型,它们主要的区别在于 I/O 操作的阻塞特性和异步处理的能力。下面是它们的详细对比:


1. BIO(Blocking I/O)

特点:

  • 阻塞式 I/O:每次 I/O 操作(读取或写入)都会阻塞当前线程,直到操作完成。
  • 每个 I/O 操作都需要一个线程来完成,当请求很多时,可能会创建大量线程,造成性能瓶颈。

流程:

  1. 客户端发起连接请求。
  2. 服务器接受连接请求,分配一个线程进行处理。
  3. 该线程在 I/O 操作时会被阻塞,直到完成操作(读或写)。

优缺点:

  • 优点:实现简单、直观,适合小规模并发或单线程应用。
  • 缺点:性能较差,线程过多时会导致高开销,限制了系统的并发处理能力。

适用场景:适用于连接数较少、并发量不高的传统应用。


2. NIO(Non-blocking I/O)

特点:

  • 非阻塞 I/O:引入了 SelectorChannel 等概念,允许多个 I/O 操作共享一个或多个线程,避免每个连接占用一个线程。线程不会因 I/O 操作而阻塞,线程可以在等待 I/O 完成的同时做其他事情。
  • 事件驱动:NIO 使用非阻塞模式,线程可以轮询 (polling) 检查 I/O 操作是否完成,通过 Selector 来监听多个通道(Channel)的 I/O 状态。

流程:

  1. 客户端发起连接请求。
  2. 服务器通过 Selector 监听多个通道(Channel)上的 I/O 事件,线程不会被阻塞,而是轮询所有通道。
  3. 一旦某个通道的 I/O 操作准备好,线程就会处理相应的操作。

优缺点:

  • 优点:支持高并发,使用少量线程就能处理大量连接。
  • 缺点:编程复杂,处理多个连接时需要编写较为复杂的代码(如 SelectorChannel)。

适用场景:适用于高并发应用,如 Web 服务器、聊天服务器等。


3. AIO(Asynchronous I/O)

特点:

  • 异步 I/O:在 AIO 中,I/O 操作的执行完全是异步的,线程不需要等待 I/O 完成。I/O 请求会通过操作系统内核来处理,操作系统会在完成 I/O 操作时通知应用程序。
  • 线程发出 I/O 请求后,立即返回,I/O 操作在后台完成。当 I/O 完成时,操作系统会通过回调函数通知应用程序。

流程:

  1. 客户端发起连接请求。
  2. 服务器通过异步接口发出 I/O 请求。
  3. 当 I/O 操作完成时,操作系统通过回调函数通知服务器。

优缺点:

  • 优点:高效,能够利用操作系统的异步 I/O 支持,减少了应用层的线程等待时间,极大提高了并发处理能力。
  • 缺点:实现较为复杂,底层需要支持异步 I/O,且需要操作系统的支持(如 Linux 的 epoll 或 Windows 的 IOCP)。

适用场景:适用于大规模、高并发、低延迟的应用,特别是需要大量并发连接而不希望使用过多线程的场景。


总结对比

特性BIO(阻塞 I/O)NIO(非阻塞 I/O)AIO(异步 I/O)
阻塞方式阻塞式操作非阻塞操作完全异步,不阻塞线程
线程模型每个连接一个线程一个线程处理多个连接,通过轮询(Selector通过操作系统异步处理,通知回调
性能性能较差,连接数多时会消耗大量线程性能较好,支持高并发性能最好,几乎不依赖线程阻塞
编程复杂度简单易懂,代码直观编程复杂,需要使用 SelectorChannel编程复杂,操作系统支持,通常通过回调处理
适用场景低并发、传统应用高并发、大量连接的场景超高并发、低延迟、大规模并发连接的应用

总结

  • BIO 适用于低并发场景,简单易懂,但性能较差。
  • NIO 适用于中到高并发场景,能高效利用少量线程处理大量连接,但编程复杂。
  • AIO 提供最好的性能,适用于极高并发的场景,但实现复杂并依赖操作系统的异步支持。

不同的 I/O 模型适用于不同的应用需求,选择合适的模型能有效提升程序性能。

相关文章:

Java基础面试题总结(题目来源JavaGuide)

问题1&#xff1a;Java 中有哪 8 种基本数据类型&#xff1f;它们的默认值和占用的空间大小知道不&#xff1f; 说说这 8 种基本数据类型对 应的包装类型。 在 Java 中&#xff0c;有 8 种基本数据类型&#xff08;Primitive Types&#xff09;&#xff1a; 基本数据类型关键…...

CSS(快速入门)

欢迎大家来到我的博客~欢迎大家对我的博客提出指导&#xff0c;有错误的地方会改进的哦~点击这里了解更多内容 目录 一、什么是CSS?二、基本语法规范三、CSS选择器3.1 标签选择器3.2 id选择器3.3 class选择器3.4 通配符选择器3.5 复合选择器 四、常用CSS样式4.1 color4.2 font…...

架构技能(六):软件设计(下)

我们知道&#xff0c;软件设计包括软件的整体架构设计和模块的详细设计。 在上一篇文章&#xff08;见 《架构技能&#xff08;五&#xff09;&#xff1a;软件设计&#xff08;上&#xff09;》&#xff09;谈了软件的整体架构设计&#xff0c;今天聊一下模块的详细设计。 模…...

2. Java-MarkDown文件解析-工具类

2. Java-MarkDown文件解析-工具类 1. 思路 读取markdown文件的内容&#xff0c;根据markdown的语法进行各个类型语法的解析。引入工具类 commonmark 和 commonmark-ext-gfm-tables进行markdown语法解析。 2. 工具类 pom.xml <!-- commonmark 解析markdown --> <d…...

OpenEuler学习笔记(十五):在OpenEuler上搭建Java运行环境

一、在OpenEuler上搭建Java运行环境 在OpenEuler上搭建Java运行环境可以通过以下几种常见方式&#xff0c;下面分别介绍基于包管理器安装OpenJDK和手动安装Oracle JDK的步骤。 使用包管理器安装OpenJDK OpenJDK是Java开发工具包的开源实现&#xff0c;在OpenEuler上可以方便…...

【Rust自学】15.4. Drop trait:告别手动清理,释放即安全

喜欢的话别忘了点赞、收藏加关注哦&#xff08;加关注即可阅读全文&#xff09;&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 15.4.1. Drop trait的意义 类型如果实现了Drop trait&#xff0c;就可以让程序员自定义当值…...

深入探讨Web应用开发:从前端到后端的全栈实践

在数字化时代&#xff0c;Web应用已成为连接用户与服务的关键桥梁。无论是电商平台、社交媒体&#xff0c;还是企业内部管理系统&#xff0c;Web应用都扮演着不可或缺的角色。本文将深入探讨Web应用开发的全栈实践&#xff0c;从前端的用户体验设计到后端的数据处理与存储&…...

4.贪心算法

贪心 贪心算法&#xff08;Greedy Algorithms&#xff09;是 C 等编程语言中常用的一种算法策略。 定义 贪心算法是指在对问题求解时&#xff0c;总是做出在当前看来是最好的选择。也就是说&#xff0c;不从整体最优上加以考虑&#xff0c;算法得到的是在某种意义上的局部最…...

js笔记(黑马程序员)

&#xff08;Web APIs day4&#xff09; 一、日期对象 1.实例化 在代码中发现了 new 关键字时&#xff0c;一般将这个操作称为实例化 创建一个时间对象并获取时间// 1&#xff0e;得到当前时间 2.日期对象方法 因为日期对象返回的数据我们不能直接使用&#xff0c;所以需…...

LangChain:使用表达式语言优化提示词链

在 LangChain 里&#xff0c;LCEL 即 LangChain Expression Language&#xff08;LangChain 表达式语言&#xff09;&#xff0c;本文为你详细介绍它的定义、作用、优势并举例说明&#xff0c;从简单示例到复杂组合示例&#xff0c;让你快速掌握LCEL表达式语言使用技巧。 定义 …...

Python 有用的资源

Python 有用的资源 引言 Python 作为一种强大的编程语言,因其简洁明了的语法和丰富的库资源,在数据分析、人工智能、网络开发等领域拥有广泛的应用。对于初学者和专业人士来说,掌握一些有用的Python资源可以大大提高编程效率。本文将为您介绍一些实用的Python资源,帮助您…...

汽车蓝牙钥匙定位仿真小程序

此需求来自于粉丝的真实需求,假期没事,牛刀小试。 一、项目背景 如今,智能车钥匙和移动端定位技术已经相当普及。为了探索蓝牙 Beacon 在短距离定位场景下的可行性,我们搭建了一个简易原型:利用 UniApp 在移动端采集蓝牙信标的 RSSI(信号强度),通过三边定位算法估算钥…...

项目开发实践——基于SpringBoot+Vue3实现的在线考试系统(九)(完结篇)

文章目录 一、成绩查询模块实现1、学生成绩查询功能实现1.1 页面设计1.2 前端页面实现1.3 后端功能实现2、成绩分段查询功能实现2.1 页面设计2.2 前端页面实现2.3 后端功能实现二、试卷练习模块实现三、我的分数模块实现1、 页面设计2、 前端页面实现3、 后端功能实现四、交流区…...

python学opencv|读取图像(四十九)原理探究:使用cv2.bitwise()系列函数实现图像按位运算

【0】基础定义 按位与运算&#xff1a;两个等长度二进制数上下对齐&#xff0c;全1取1&#xff0c;其余取0。 按位或运算&#xff1a;两个等长度二进制数上下对齐&#xff0c;有1取1&#xff0c;其余取0。 按位异或运算&#xff1a; 两个等长度二进制数上下对齐&#xff0c;相…...

electron打包客户端在rk3588上支持h265硬解

目录 前言 chromium是如何支持h265硬解 electron/chromium第一次编译 electron/chromium第二次编译 前言 我们的客户端程序是用electron打包的前端程序&#xff0c;其在rk3588主机上的linux环境运行。之前使用客户端查看h264编码的视频直播是没有问题的&#xff0c;但视频源…...

MyBatis 缓存机制详解

目录 一、什么是缓存&#xff1f; 1. 什么是缓存&#xff1f; 2. 为什么使用缓存&#xff1f; 3. 什么样的数据适合使用缓存&#xff1f; 二、MyBatis 缓存机制 1. 一级缓存&#xff08;也叫本地缓存&#xff09; 2. 一级缓存失效的情况 3. 二级缓存 4. 二级缓存失效的…...

【后端开发】字节跳动青训营Cloudwego脚手架

Cloudwego脚手架使用 cwgo脚手架 cwgo脚手架 安装的命令&#xff1a; GOPROXYhttps://goproxy.cn/,direct go install github.com/cloudwego/cwgolatest依赖thriftgo的安装&#xff1a; go install github.com/cloudwego/thriftgolatest编辑echo.thrift文件用于生成项目&…...

数据结构选讲 (更新中)

参考 smWCDay7 数据结构选讲2 by yyc 。 可能会补充的&#xff1a; AT_cf17_final_j TreeMST 的 F2 Boruvka算法 目录 AT_cf17_final_j Tree MST AT_cf17_final_j Tree MST link 题意 给定一棵 n n n 个点的树&#xff0c;点有点权 w i w_i wi​&#xff0c;边有边权。建立…...

springboot 简化 spring开发

什么是自动配置&#xff1f; 简单概念&#xff1a; Spring Boot 自动配置是一种 “约定优于配置” 的做法。根据项目类路径&#xff08;classpath&#xff09;上存在的依赖、配置文件中的某些属性&#xff0c;Spring Boot 会自动为常见场景创建并配置相关 Bean&#xff0c;省…...

Yolo11 + OCR 营业执照识别+信息抽取(预期后续改用其他ocr更简单,推理预计使用onnxruntim加速,分c++和python两种方式部署)

目录 一 数据集制作 1 labelimg的安装与使用 2 标注方式 3 数据集制作 二 模型训练 三 使用Yolo11 + OCR 实现“营业执照”信息解析完整方案 1 cutLinesforcode.py 2 getBusinessLicenseContentPart.py 3 getPartWords.py 4 pdfTojpg.py 5 main.py 本项目可用于毕业…...

机器学习day3

自定义数据集使用框架的线性回归方法对其进行拟合 import matplotlib.pyplot as plt import torch import numpy as np # 1.散点输入 # 1、散点输入 # 定义输入数据 data [[-0.5, 7.7], [1.8, 98.5], [0.9, 57.8], [0.4, 39.2], [-1.4, -15.7], [-1.4, -37.3], [-1.8, -49.1]…...

C基础寒假练习(3)

一、求数组中的第二大值 #include <stdio.h> int main() {int arr[] {12, 35, 1, 10, 34, 1};int size sizeof(arr) / sizeof(arr[0]);if (size < 2) {printf("数组元素不足两个\n");return 0;}int first -2147483648, second -2147483648; // 使用IN…...

星际战争模拟系统:新月的编程之道

星际战争模拟系统&#xff1a;新月的编程之道 作为一名在 25 世纪星际时代成长起来的科学家和军事战略家&#xff0c;我对编程和人工智能的热爱始于童年。我的父亲是一位著名的物理学家&#xff0c;母亲是一位杰出的生物工程师。在他们的影响下&#xff0c;我从小就对科学和技术…...

【Redis】 String 类型的介绍和常用命令

1. 介绍 Redis 中的 key 都是字符串类型Redis 中存储字符串是完全按照二进制流的形式保存的&#xff0c;所以 Redis 是不处理字符集编码的问题&#xff0c;客户端传入的命令中使用的是什么编码就采用什么编码&#xff0c;使得 Redis 能够处理各种类型的数据&#xff0c;包括文…...

U盘打开提示格式化:深度解析与数据恢复全攻略

在数字化时代&#xff0c;U盘作为便捷的数据存储和传输工具&#xff0c;广泛应用于各个领域。然而&#xff0c;当我们满怀期待地插入U盘&#xff0c;却遭遇“U盘打开提示格式化”的尴尬局面时&#xff0c;那份焦虑与无助感油然而生。本文将全面剖析U盘打开提示格式化的原因、应…...

vue2在线生成二维码

亲情提示&#xff1a;如果可以让后端生成就让后端生成 实在不行再前端解决&#xff08;分享方法只是为了让你快点下班 不是为了让你能者多劳&#xff09; 创建 npm install qrcodejs2 pnpm install qrcodejs2 <div ref"qrcode" id"myQrCode" class&…...

Linux中的几个基本指令(二)

文章目录 1、cp指令例一&#xff1a;例二&#xff1a;例三&#xff1a;例四&#xff1a;例五&#xff1a; 2、mv 指令例一&#xff1a;例二&#xff1a; 3、cat指令例一&#xff1a; 4、tac指令5、which指令6、date指令时间戳&#xff1a;7、zip指令 今天我们继续学习Linux下的…...

基于Springboot的健身房管理系统【附源码】

基于Springboot的健身房管理系统 效果如下&#xff1a; 系统登陆页面 管理员主页面 器材类型管理页面 健身房管理页面 教练管理页面 用户管理页面 个人信息页面 课程管理页面 研究背景 随着健康意识的不断增强和人们生活水平的提高&#xff0c;健身房已经成为了现代城市中不…...

【HarmonyOS之旅】基于ArkTS开发(三) -> 兼容JS的类Web开发(一)

目录 1 -> 概述 1.1 -> 整体架构 2 -> 文件组织 2.1 -> 目录结构 2.2 -> 文件访问规则 2.3 -> 媒体文件格式 3 -> js标签配置 3.1 -> pages 3.2 -> window 3.3 -> 示例 4 -> app.js 4.1 -> 应用生命周期 4.2 -> 应用对象6…...

Spring Boot多环境配置实践指南

在开发Spring Boot应用时&#xff0c;我们常常需要根据不同的运行环境&#xff08;如开发环境、测试环境和生产环境&#xff09;来配置不同的参数。Spring Boot提供了非常灵活的多环境配置机制&#xff0c;通过使用profile-specific properties文件&#xff0c;我们可以轻松地管…...

知识图谱质量评估:构建高质量语义网络的关键

目录 前言1. 知识图谱质量评估的必要性2. 知识图谱质量评估的核心维度2.1 数据层面2.2 结构层面2.3 语义层面2.4 性能层面 3. 知识图谱质量评估的方法3.1 定量评估方法3.2 定性评估方法 4. 知识图谱质量优化建议结语 前言 随着大数据和人工智能技术的飞速发展&#xff0c;知识…...

< OS 有关 > Android 手机 SSH 客户端 app: connectBot

connectBot 开源且功能齐全的SSH客户端,界面简洁,支持证书密钥。 下载量超 500万 方便在 Android 手机上&#xff0c;连接 SSH 服务器&#xff0c;去运行命令。 Fail2ban 12小时内抓获的 IP ~ ~ ~ ~ rootjpn:~# sudo fail2ban-client status sshd Status for the jail: sshd …...

Unity游戏(Assault空对地打击)开发(1) 创建项目和选择插件

目录 前言 创建项目 插件导入 地形插件 前言 这是游戏开发第一篇&#xff0c;进行开发准备。 创作不易&#xff0c;欢迎支持。 我的编辑器布局是【Tall】&#xff0c;建议调整为该布局&#xff0c;如下。 创建项目 首先创建一个项目&#xff0c;过程略&#xff0c;名字请勿…...

SpringBoot 日志

目录 一. 日志概述 二. 日志的使用 1. 打印日志 (1) 获取日志对象 (2) 输出要打印的内容 2. 日志框架简介 (1) 门面模式简介 (2) SLF4J 框架简介 3. 日志的格式 4. 日志的级别 5. 日志配置 (1) 配置日志级别 (2) 日志持久化存储 ① 配置日志文件名 ② 配置日志的…...

每日 Java 面试题分享【第 16 天】

欢迎来到每日 Java 面试题分享栏目&#xff01; 订阅专栏&#xff0c;不错过每一天的练习 今日分享 3 道面试题目&#xff01; 评论区复述一遍印象更深刻噢~ 目录 问题一&#xff1a;Java 运行时异常和编译时异常之间的区别是什么&#xff1f;问题二&#xff1a;什么是 Jav…...

《多线程基础之互斥锁》

【互斥锁导读】互斥锁是大家使用最多的线程同步手段&#xff0c;但仅仅知道怎么用还是不够的&#xff1f;比如&#xff1a;面试官问你"互斥锁是属于内核层还是应用层的同步保护机制&#xff1f;性能怎样&#xff1f;"&#xff0c;"频繁加解锁&#xff0c;会有什…...

渲染流程概述

渲染流程包括 CPU应用程序端渲染逻辑 和 GPU渲染管线 一、CPU应用程序端渲染逻辑 剔除操作对物体进行渲染排序打包数据调用Shader SetPassCall 和 Drawcall 1.剔除操作 视椎体剔除 &#xff08;给物体一个包围盒&#xff0c;利用包围盒和摄像机的视椎体进行碰撞检测&#xf…...

Android车机DIY开发之学习篇(七)NDK交叉工具构建

Android车机DIY开发之学习篇(七)NDK交叉工具构建 1.ubuntu安装GCC sudo apt-get update sudo apt-get install gcc g sudo gcc --version sudo g --version 2.测试GCC VSCODE中新建Hello.c编译 #include <stdio.h> int main(void) { printf(“Hello, this is a progr…...

c++ map/multimap容器 学习笔记

1 map的基本概念 简介&#xff1a; map中所有的元素都是pair pair中第一个元素是key&#xff08;键&#xff09;&#xff0c;第二个元素是value&#xff08;值&#xff09; 所有元素都会根据元素的键值自动排序。本质&#xff1a; map/multimap 属于关联式容器&#xff0c;底…...

计算机网络之计算机网络体系结构

一、定义与概述 计算机网络体系结构是计算机网络及其部件所应该完成功能的精确定义&#xff0c;这些功能由何种硬件或软件完成是遵循这种体系结构的。体系结构是抽象的&#xff0c;实现是具体的&#xff0c;是运行在计算机软件和硬件之上的。 二、主流模型 目前&#xff0c;…...

研发的立足之本到底是啥?

0 你的问题&#xff0c;我知道&#xff01; 本文深入T型图“竖线”的立足之本&#xff1a;专业技术 技术赋能业务能力。研发在学习投入精力最多&#xff0c;也误区最多。 某粉丝感发展遇到瓶颈&#xff0c;项目都会做&#xff0c;但觉无提升&#xff0c;想跳槽。于是&#x…...

最优化问题 - 内点法

以下是一种循序推理的方式&#xff0c;来帮助你从基础概念出发&#xff0c;理解 内点法&#xff08;Interior-Point Method, IPM&#xff09; 是什么、为什么要用它&#xff0c;以及它是如何工作的。 1. 问题起点&#xff1a;带不等式约束的优化 假设你有一个带不等式约束的优…...

Vue5---

目录 一、学习目标 1.自定义指令 2.插槽 3.综合案例&#xff1a;商品列表 4.路由入门 二、自定义指令 1.指令介绍 2.自定义指令 3.自定义指令的语法 三、自定义指令-指令的值 1.需求 2.语法 3.代码示例 五、插槽-默认插槽 1.作用 2.需求 4.使用插槽的基本语法…...

Helm Chart 实战指南

Helm 是 Kubernetes 的包管理工具,而 Helm Chart 是 Helm 的核心概念,用于定义、安装和升级 Kubernetes 应用。本文将带你从零开始,通过实战演练,掌握 Helm Chart 的创建、配置和部署,帮助你高效管理 Kubernetes 应用。 1. 环境准备 在开始之前,确保你已经具备以下环境:…...

如何写一篇高质量的提示词?

不管是产品经理还是使用AI工具的用户&#xff0c;很多时候的烦恼是如何写提示词&#xff0c;我觉得写提示词就是在梳理思路&#xff0c;下边是一个提示词的结果&#xff0c;OpenAI 的总裁 Greg Brockman 曾转发过这个结构。 这种结构可以创建一个清晰、简洁、可执行的提示&…...

系统架构设计师教材:信息系统及信息安全

信息系统 信息系统的5个基本功能&#xff1a;输入、存储、处理、输出和控制。信息系统的生命周期分为4个阶段&#xff0c;即产生阶段、开发阶段、运行阶段和消亡阶段。 信息系统建设原则 1. 高层管理人员介入原则&#xff1a;只有高层管理人员才能知道企业究竟需要什么样的信…...

在Windows系统中本地部署属于自己的大语言模型(Ollama + open-webui + deepseek-r1)

文章目录 1 在Windows系统中安装Ollama&#xff0c;并成功启动&#xff1b;2 非docker方式安装open-webui3下载并部署模型deepseek-r1 Ollama Ollama 是一个命令行工具&#xff0c;用于管理和运行机器学习模型。它简化了模型的下载与部署&#xff0c;支持跨平台使用&#xff0c…...

使用Redis生成全局唯一ID示例

全局ID生成器,一种在分布式系统下用来生成全局唯一ID的工具,一般满足一下要求特性 1.唯一性 2.高性能 3.安全性 4.递增性 5.高可用 Component public class RedisIdWorker {/*** 定义一个开始的时间戳(秒级)* param args*/private static final long BEGIN_TIMESTAMP 16…...

【llm对话系统】 LLM 大模型推理python实现:vLLM 框架

在 LLM 的应用中&#xff0c;推理 (Inference) 阶段至关重要。它指的是利用训练好的 LLM 模型&#xff0c;根据输入 (Prompt) 生成文本的过程。然而&#xff0c;LLM 的推理速度往往较慢&#xff0c;尤其是在处理长序列或高并发请求时&#xff0c;效率瓶颈尤为突出。 为了解决这…...

16.Word:石油化工设备技术❗【28】

目录 题目 NO1.2 NO3 NO4 题目 NO1.2 F12&#xff1a;另存为将“Word素材.docx”文件另存为“Word. docx”&#xff08;“docx”为文件扩展名&#xff09; 光标来到表格上方→插入→形状→新建画布→单击选中→格式→高度/宽度&#xff08;格式→大小对话框→取消勾选✔锁定…...