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

Java基础概念汇总

JavaEE

  • Java基础概念面试题详解
    • 1. Java的特点是什么?
    • 2. Java和C++的区别有哪些?
    • 3. 什么是JDK、JRE和JVM?它们之间有什么关系?
    • 4. Java是编译型语言还是解释型语言?
    • 5. Java如何实现跨平台?
  • 数据类型与变量面试题详解
    • 1. Java有哪些基本数据类型?
    • 2. `int`和`Integer`有什么区别?
    • 3. 什么是自动装箱和拆箱?
    • 4. `String`、`StringBuilder`和`StringBuffer`的区别?
    • 5. `==`和`equals()`的区别?
  • 面向对象编程(OOP)面试题详解
    • 1. 面向对象的四大特性是什么?
    • 2. 什么是类和对象?
    • 3. 重载(Overload)和重写(Override)的区别?
    • 4. 抽象类和接口的区别?
    • 5. 什么是多态?如何实现多态?
    • 6. 构造方法(Constructor)的特点和作用?
    • 7. this和super关键字的区别?
    • 8. 什么是静态变量和静态方法?
    • 9. final、finally和finalize的区别?
  • 异常处理面试题详解
    • 1. Java异常体系结构是怎样的?
    • 2. Error和Exception的区别?
    • 3. 受检异常和非受检异常的区别?
    • 4. try-catch-finally的执行顺序?
    • 5. throw和throws的区别?
  • 集合框架面试题详解
    • 1. Java集合框架的主要接口和类有哪些?
    • 2. List、Set和Map的区别?
    • 3. ArrayList和LinkedList的区别?
    • 4. HashMap的工作原理?
    • 5. HashMap和HashTable的区别?
    • 6. ConcurrentHashMap如何保证线程安全?
      • Java 7 及之前的 ConcurrentHashMap 实现
      • Java 8 及之后的 ConcurrentHashMap 实现
      • 重要内部类变化
      • 并发控制机制对比
      • 为什么Java 8要重新设计?
      • 典型使用场景建议
  • 多线程面试题详解
    • 1. 线程和进程的区别?
    • 2. 创建线程的几种方式?
    • 3. Runnable和Callable的区别?
    • 4. 线程的生命周期(状态)有哪些?
    • 5. sleep()和wait()的区别?
    • 6. synchronized关键字的用法?
    • 7. volatile关键字的作用?
    • 8. 什么是线程池?为什么要用线程池?
  • IO与NIO面试题详解
    • 1. Java IO流分为哪几种?
    • 2. 字节流和字符流的区别?
    • 3. BIO、NIO和AIO的区别?
    • 4. NIO的核心组件有哪些?
  • 反射与泛型面试题详解
    • 1. 什么是反射?反射的应用场景?
    • 2. 如何获取Class对象?
    • 3. 什么是泛型?泛型擦除是什么意思?
  • Java 8新特性面试题详解
    • 1. Lambda表达式的作用?
    • 2. Stream API的常用方法有哪些?
    • 3. 什么是函数式接口?常见的函数式接口有哪些?
    • 4. Optional类的作用?
  • JVM基础面试题详解
    • 1. JVM内存结构是怎样的?
    • 2. 什么是垃圾回收(GC)?常见的垃圾回收算法有哪些?
    • 3. 强引用、软引用、弱引用和虚引用的区别?
    • 4. 类加载过程是怎样的?
  • Java Stream 补充面试题详解
    • 1. Stream 的中间操作和终止操作有什么区别?
    • 2. 并行流(Parallel Stream)使用时要注意什么?
    • 3. Stream 和 Collection 的区别?
    • 4. 常用的 Stream 收集器(Collectors)有哪些?
    • 5. Stream 中的 findFirst() 和 findAny() 有什么区别?
    • 6. Stream 的 flatMap() 和 map() 有什么区别?
    • 7. 如何用 Stream 处理大文件?
    • 8. Stream 的 peek() 和 forEach() 有什么区别?
    • 9. 如何自定义 Collector?
    • 10. Stream 的 reduce() 方法如何使用?
  • Java 其他高频面试题补充
    • 1. Java 模块化系统(Java 9+)
    • 2. 记录类型(Record, Java 14+)
    • 3. 密封类(Sealed Class, Java 15+)
    • 4. 模式匹配(Java 16+)
    • 5. 虚拟线程(Virtual Thread, Java 19+)
    • 6. 响应式编程(Reactive Streams)
    • 7. Java 原生内存访问(Java 16+)
    • 8. 协程库比较
    • 9. 微基准测试(JMH)
    • 10. 代码安全实践
    • 11. JVM 性能调优
    • 12. 现代Java开发实践

Java基础概念面试题详解

1. Java的特点是什么?

Java的主要特点包括:

  • 面向对象:完全遵循OOP原则(封装、继承、多态)
  • 平台无关性:通过"Write Once, Run Anywhere"机制实现
  • 健壮性
    • 强类型检查
    • 自动内存管理(垃圾回收机制)
    • 异常处理机制
  • 安全性
    • 字节码验证
    • 无指针运算
    • 安全管理器
  • 多线程支持:内置Thread类
  • 分布式支持:完善的网络库(java.net包)
  • 动态性:反射机制支持运行时类型检查

2. Java和C++的区别有哪些?

特性JavaC++
内存管理自动垃圾回收手动new/delete
指针无显式指针支持指针操作
多重继承通过接口实现直接支持
平台依赖性跨平台(JVM)平台相关
运行速度相对较慢(JIT优化)直接编译为机器码
异常处理强制处理受检异常无异常类型限制
标准库丰富的集合框架STL
运算符重载不支持支持
预处理器支持#define等

3. 什么是JDK、JRE和JVM?它们之间有什么关系?

JVM (Java Virtual Machine)

  • 字节码执行引擎
  • 包含类加载器、执行引擎、运行时数据区等
  • 不同平台有不同实现(Windows/Linux/Mac)

JRE (Java Runtime Environment)

  • = JVM + 核心类库(如java.lang, java.util等)
  • 只能运行Java程序

JDK (Java Development Kit)

  • = JRE + 开发工具(javac, javadoc, jdb等)
  • 包含完整的Java开发环境

关系图示:
JDK ⊃ JRE ⊃ JVM

4. Java是编译型语言还是解释型语言?

Java采用混合模式

  1. 编译阶段

    • 源码(.java) → 字节码(.class)
    • 使用javac编译器
    • 生成平台无关的中间代码
  2. 执行阶段

    • 解释执行:JVM逐行解释字节码
    • JIT编译(Just-In-Time):
      • 热点代码会被编译为本地机器码
      • 显著提升性能(如HotSpot VM)

典型执行流程:
.java → (javac) → .class → (JVM) → 机器码

5. Java如何实现跨平台?

跨平台实现原理

  1. 统一中间格式

    • 编译生成标准字节码(.class文件)
    • 字节码与具体硬件/OS无关
  2. JVM适配层

    • 各平台提供对应的JVM实现
    • JVM负责将字节码转换为本地指令
  3. 分层抽象

    • 硬件层:x86/ARM等
    • 系统层:Windows/Linux/macOS
    • JVM层:统一字节码接口
    • 应用层:Java程序

关键组件:

  • 类加载器(加载字节码)
  • 字节码验证器(安全检查)
  • 解释器/JIT编译器(执行优化)

示例说明:
Windows平台:.class → windows-jvm → x86指令
Linux平台:同样的.class → linux-jvm → ARM指令

数据类型与变量面试题详解

1. Java有哪些基本数据类型?

Java的8种基本数据类型:

类型大小默认值取值范围包装类
byte1字节0-128 ~ 127Byte
short2字节0-32768 ~ 32767Short
int4字节0-2³¹ ~ 2³¹-1Integer
long8字节0L-2⁶³ ~ 2⁶³-1Long
float4字节0.0f±1.4E-45 ~ ±3.4E38(6-7位有效数字)Float
double8字节0.0d±4.9E-324 ~ ±1.7E308(15位有效数字)Double
char2字节‘\u0000’0 ~ 65535(Unicode字符)Character
boolean未定义falsetrue/falseBoolean

注意:boolean在JVM层面用int(32位)或byte(8位)实现

2. intInteger有什么区别?

对比维度intInteger
类型基本数据类型包装类对象
内存分配栈内存堆内存
默认值0null
泛型支持不能用于泛型可用于泛型(如List<Integer>
方法支持无对象方法提供parseInt()等工具方法
缓存机制-128~127缓存(IntegerCache
比较方式直接比较值需要用equals()比较值

代码示例:

int a = 100;
Integer b = 100;          // 自动装箱(实际调用Integer.valueOf(100))
Integer c = new Integer(100);  // 显式创建新对象System.out.println(a == b);       // true(自动拆箱比较值)
System.out.println(b == c);       // false(比较对象地址)
System.out.println(b.equals(c));  // true(比较实际值)

3. 什么是自动装箱和拆箱?

自动装箱(Autoboxing)
基本类型 → 包装类型(编译器的语法糖)

int num = 42;
Integer boxedNum = num;  // 等价于 Integer.valueOf(42)

自动拆箱(Unboxing)
包装类型 → 基本类型(编译器的语法糖)

Integer boxedNum = Integer.valueOf(100);
int unboxed = boxedNum;  // 等价于 boxedNum.intValue()

重要特性

  • 缓存机制:-128~127的Integer对象会被缓存
  • 性能影响:循环中频繁装箱拆箱会导致性能问题(创建多余对象)

4. StringStringBuilderStringBuffer的区别?

特性StringStringBuilderStringBuffer
可变性不可变(final char[])可变可变
线程安全天生线程安全非线程安全线程安全(synchronized方法)
性能最低(每次修改创建新对象)最高中等
使用场景常量字符串操作单线程字符串拼接多线程字符串操作

代码示例:

String str = "Hello";
str += " World";  // 创建3个对象("Hello", " World", "Hello World")StringBuilder sb = new StringBuilder();
sb.append("Hello").append(" World");  // 只操作同一个对象StringBuffer sbf = new StringBuffer();
sbf.append("Thread").append("Safe");  // 方法添加synchronized锁

5. ==equals()的区别?

操作符/方法比较内容适用场景
==内存地址比较基本类型比较值,对象比较地址
equals()对象内容比较(可重写)对象的值比较

关键规则

  • 对于基本类型:==比较值
int x = 5, y = 5;System.out.println(x == y);  // true
  • 对于对象类型:==比较内存地址
  String s1 = new String("abc");String s2 = new String("abc");System.out.println(s1 == s2);  // false
  • equals()默认实现与==相同,但可被重写:
  System.out.println(s1.equals(s2));  // true(String类重写了equals)

重要类别的equals实现

  • String:比较字符序列内容
  • Integer:比较int值
  • 自定义类:需重写equals()和hashCode()

面向对象编程(OOP)面试题详解

1. 面向对象的四大特性是什么?

  • 封装(Encapsulation)
    将数据和操作数据的方法绑定在一起,对外隐藏实现细节
    示例:
 public class Person {private String name;  // 私有字段public String getName() {  // 公开方法return this.name;}}
  • 继承(Inheritance)
    子类继承父类的特征和行为,实现代码复用
    示例:
class Animal {}class Dog extends Animal {}  // Dog继承Animal
  • 多态(Polymorphism)
    同一操作作用于不同对象产生不同行为
    实现方式:

    • 方法重写(Override)
    • 接口实现
    • 抽象类和抽象方法
  • 抽象(Abstraction)
    提取关键特征,忽略非本质细节
    实现方式:

    • 抽象类(abstract class)
    • 接口(interface)

2. 什么是类和对象?

类(Class)

  • 对象的蓝图/模板
  • 包含:
    • 属性(字段/成员变量)
    • 行为(方法)
  • 示例:
public class Student {String name;  // 字段void study() {  // 方法System.out.println("Studying...");}
}

对象(Object)

  • 类的具体实例
  • 特点:
    • 占用独立内存空间
    • 包含类定义的所有字段副本
  • 示例:
Student s1 = new Student();  // s1是Student类的对象
s1.name = "张三";
s1.study();

3. 重载(Overload)和重写(Override)的区别?

对比维度重载(Overload)重写(Override)
定义同一类中同名不同参的方法子类重新实现父类方法
参数要求必须修改参数列表必须保持相同参数列表
返回类型可以不同必须相同或为子类
访问修饰符可以不同不能比父类更严格
抛出异常可以不同不能抛出更宽泛的异常
调用时机编译时确定运行时确定

重载示例:

class Calculator {int add(int a, int b) { return a+b; }double add(double a, double b) { return a+b; }  // 重载
}

重写示例:

class Animal {void makeSound() { System.out.println("Animal sound"); }
}
class Cat extends Animal {@Overridevoid makeSound() { System.out.println("Meow"); }  // 重写
}

4. 抽象类和接口的区别?

对比维度抽象类(abstract class)接口(interface)
定义关键字abstractinterface
方法实现可以有具体方法Java 8前只能有抽象方法
字段可以有普通字段默认public static final
构造方法可以有不能有
多继承单继承多实现(implements多个接口)
设计目的代码复用定义规范/契约
默认方法Java 8前无Java 8支持default方法

抽象类示例:

abstract class Shape {abstract void draw();  // 抽象方法void move() {  // 具体方法System.out.println("Moving shape");}
}

接口示例(Java 8+):

interface Drawable {void draw();  // 抽象方法default void print() {  // 默认方法System.out.println("Printing...");}static void help() {  // 静态方法System.out.println("Help info");}
}

5. 什么是多态?如何实现多态?

多态类型

  1. 编译时多态:方法重载
  2. 运行时多态:方法重写

实现方式

  • 继承 + 方法重写
  • 接口实现
  • 抽象类和抽象方法

典型示例:

class Animal {void sound() { System.out.println("Animal sound"); }
}
class Dog extends Animal {@Overridevoid sound() { System.out.println("Bark"); }
}
class Cat extends Animal {@Overridevoid sound() { System.out.println("Meow"); }
}// 测试多态
Animal myAnimal = new Dog();
myAnimal.sound();  // 输出"Bark"(运行时多态)myAnimal = new Cat();
myAnimal.sound();  // 输出"Meow"

6. 构造方法(Constructor)的特点和作用?

特点

  • 方法名与类名相同
  • 无返回类型(连void都没有)
  • 可以重载(多个不同参数的构造方法)
  • 默认提供无参构造(如果没定义任何构造方法)
  • 不能被static/final/abstract修饰

作用

  • 初始化对象状态
  • 为对象字段赋初值
  • 执行必要的启动操作

示例:

public class Person {String name;int age;// 无参构造public Person() {this.name = "Unknown";this.age = 0;}// 带参构造public Person(String name, int age) {this.name = name;this.age = age;}
}// 使用构造方法
Person p1 = new Person();  // 调用无参构造
Person p2 = new Person("Alice", 25);  // 调用带参构造

7. this和super关键字的区别?

对比维度thissuper
指向当前对象实例父类对象引用
用途1. 解决局部变量与字段同名问题
2. 调用本类其他构造方法(this())
1. 访问父类成员
2. 调用父类构造方法(super())
调用限制必须在构造方法第一行必须在子类构造方法第一行

this示例:

class Student {String name;Student(String name) {this.name = name;  // 区分字段和参数}Student() {this("Unknown");  // 调用其他构造方法}
}

super示例:

class Parent {String familyName = "Smith";
}
class Child extends Parent {String fullName;Child(String firstName) {super();  // 调用父类构造方法(可省略)this.fullName = firstName + " " + super.familyName;}
}

8. 什么是静态变量和静态方法?

静态变量(类变量)

  • static修饰
  • 属于类而非对象
  • 所有实例共享同一份拷贝
  • 通过类名.变量名访问

静态方法(类方法)

  • static修饰
  • 不能访问非静态成员
  • 不能使用this/super
  • 通过类名.方法名()调用

示例:

class Counter {static int count = 0;  // 静态变量int instanceCount = 0;  // 实例变量Counter() {count++;instanceCount++;}static void printCount() {  // 静态方法System.out.println("Total count: " + count);// System.out.println(instanceCount);  // 错误!不能访问非静态成员}
}// 使用
Counter c1 = new Counter();
Counter c2 = new Counter();
Counter.printCount();  // 输出"Total count: 2"
System.out.println(c1.instanceCount);  // 输出1

9. final、finally和finalize的区别?

关键字用途作用场景
final修饰符1. 修饰类:不可继承
2. 修饰方法:不可重写
3. 修饰变量:常量(不可修改)
finally异常处理块try-catch-finally结构中,无论是否发生异常都会执行的代码块
finalizeObject类的方法垃圾回收前调用的清理方法(不推荐使用)

final示例:

final class Immutable {  // 不可继承的类final int VALUE = 100;  // 常量final void method() {  // 不可重写的方法// ...}
}

finally示例:

try {// 可能抛出异常的代码
} catch (Exception e) {// 异常处理
} finally {// 一定会执行的代码(如释放资源)System.out.println("Cleanup");
}

finalize示例(已废弃):

@Override
protected void finalize() throws Throwable {try {// 资源清理} finally {super.finalize();}
}

异常处理面试题详解

1. Java异常体系结构是怎样的?

Java异常类的继承体系:

Throwable (所有错误和异常的基类)
├── Error (严重错误,程序无法处理)
│ ├── VirtualMachineError (JVM错误)
│ │ ├── OutOfMemoryError
│ │ └── StackOverflowError
│ └── LinkageError (类链接错误)
└── Exception (可以捕获处理的异常)
├── RuntimeException (运行时异常)
│ ├── NullPointerException
│ ├── IndexOutOfBoundsException
│ └── IllegalArgumentException
└── 其他非运行时异常
├── IOException
│ ├── FileNotFoundException
│ └── EOFException
└── SQLException

关键特点:

  • Error表示系统级错误,通常不应捕获
  • Exception分为检查型异常和非检查型异常
  • 自定义异常应继承ExceptionRuntimeException

2. Error和Exception的区别?

对比维度ErrorException
严重程度严重系统错误程序可处理的异常情况
是否可恢复通常不可恢复多数情况下可以恢复
是否强制捕获不需要捕获检查型异常必须捕获或声明
来源JVM或底层系统资源问题程序逻辑问题或外部条件
典型例子OutOfMemoryErrorNullPointerException
StackOverflowErrorFileNotFoundException

Error示例:

// 递归调用导致栈溢出
public static void infiniteRecursion() {infiniteRecursion();
}
// 调用后会抛出StackOverflowError

Exception示例:

try {FileInputStream fis = new FileInputStream("nonexistent.txt");
} catch (FileNotFoundException e) {System.out.println("文件未找到");
}

3. 受检异常和非受检异常的区别?

对比维度受检异常(Checked Exception)非受检异常(Unchecked Exception)
继承关系继承自Exception但不包括RuntimeException继承自RuntimeException或Error
处理要求必须捕获或声明抛出不强制要求处理
编译检查编译器会检查编译器不检查
设计目的可预期的异常情况程序错误或不可控情况
典型例子IOExceptionNullPointerException
SQLExceptionArrayIndexOutOfBoundsException

受检异常示例:

// 必须处理(捕获或声明throws)
try {Class.forName("com.example.NonExistClass");
} catch (ClassNotFoundException e) {e.printStackTrace();
}

非受检异常示例:

// 可以不处理,但会导致程序终止
String str = null;
System.out.println(str.length());  // 抛出NullPointerException

4. try-catch-finally的执行顺序?

标准执行流程:

  1. 执行try块中的代码
  2. 如果发生异常:
    a. 跳转到匹配的catch块
    b. 执行catch块中的异常处理
  3. 无论是否发生异常:
    a. 都会执行finally块中的代码
  4. 继续执行后续代码

特殊场景:

  • try或catch中有return:先执行finally再return
  • finally中有return:会覆盖try/catch中的return值
  • System.exit():会立即终止程序,不执行finally

执行顺序示例:

public static int testFinally() {try {System.out.println("try block");return 1;} catch (Exception e) {System.out.println("catch block");return 2;} finally {System.out.println("finally block");// return 3;  // 如果取消注释,将返回3而不是1}
}
// 输出顺序:
// try block
// finally block
// 返回值为1

5. throw和throws的区别?

对比维度throwthrows
语法位置方法体内使用方法声明处使用
作用主动抛出异常对象声明方法可能抛出的异常类型
抛出数量每次只能抛出一个异常对象可以声明多个异常类型
处理要求必须显式创建异常对象只是声明,不创建异常对象
使用场景在方法内部抛出具体异常在方法签名中声明可能抛出的异常

throw示例:

public void validateAge(int age) {if (age < 0) {throw new IllegalArgumentException("年龄不能为负数");}
}

throws示例:

public void readFile() throws FileNotFoundException, IOException {FileInputStream fis = new FileInputStream("test.txt");// 其他IO操作
}

组合使用示例:

public void transferMoney(double amount) throws InsufficientBalanceException {if (balance < amount) {throw new InsufficientBalanceException("余额不足");}// 转账逻辑...
}

最佳实践:

  1. 受检异常必须在方法签名中声明
  2. 不要滥用throws声明所有异常
  3. 自定义异常应提供有意义的错误信息
  4. 在catch块中通常应该记录异常日志

集合框架面试题详解

1. Java集合框架的主要接口和类有哪些?

核心接口

  • Collection (所有集合的根接口)
    • List (有序可重复集合)
    • Set (无序不可重复集合)
    • Queue (队列)
  • Map (键值对集合)

常用实现类

  • List实现类:

    • ArrayList (基于动态数组)
    • LinkedList (基于双向链表)
    • Vector (线程安全版ArrayList)
    • Stack (继承自Vector)
  • Set实现类:

    • HashSet (基于HashMap)
    • LinkedHashSet (保持插入顺序)
    • TreeSet (基于红黑树,有序)
  • Map实现类:

    • HashMap (基于哈希表)
    • LinkedHashMap (保持插入顺序)
    • TreeMap (基于红黑树,按键排序)
    • Hashtable (线程安全,已过时)
    • ConcurrentHashMap (线程安全优化版)
  • Queue实现类:

    • PriorityQueue (优先级队列)
    • ArrayDeque (双端队列)

2. List、Set和Map的区别?

特性ListSetMap
元素重复性允许重复元素不允许重复元素Key不允许重复,Value允许重复
有序性保持插入顺序通常无序(HashSet)通常无序(HashMap)
实现基础动态数组/链表基于Map实现哈希表/红黑树
访问方式通过索引访问只能迭代访问通过Key访问Value
典型实现ArrayList, LinkedListHashSet, TreeSetHashMap, TreeMap
null支持允许null元素最多一个null(HashSet)HashMap允许一个null key

3. ArrayList和LinkedList的区别?

对比维度ArrayListLinkedList
底层结构动态数组双向链表
内存占用连续内存,占用较少节点存储,占用更多
访问效率O(1)随机访问O(n)顺序访问
插入删除尾部操作O(1),中间O(n)头尾操作O(1),中间O(n)
扩容机制默认扩容50%无需扩容
适用场景频繁随机访问频繁插入删除

代码示例:

// ArrayList访问示例
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("A");
arrayList.get(0);  // O(1)快速访问// LinkedList插入示例
LinkedList<String> linkedList = new LinkedList<>();
linkedList.addFirst("B");  // O(1)头部插入

4. HashMap的工作原理?

核心机制

  1. 哈希计算

    • 调用key的hashCode()计算哈希值
    • 通过扰动函数减少哈希冲突
    • 公式:index = (n - 1) & hash (n为数组长度)
  2. 存储结构

    • Java 8前:数组+链表
    • Java 8+:数组+链表/红黑树(链表长度>8时转换)
  3. put流程

    • 计算key的hash值
    • 如果数组为空,初始化(默认16)
    • 如果对应位置为空,直接插入
    • 如果存在冲突:
      • 链表:遍历查找,存在则覆盖,否则尾插
      • 红黑树:树形查找插入
    • 超过阈值(默认0.75)则扩容2倍
  4. get流程

    • 计算key的hash值
    • 定位数组下标
    • 遍历链表/红黑树查找

关键参数:

  • 默认容量:16
  • 负载因子:0.75
  • 树化阈值:8
  • 解树化阈值:6

5. HashMap和HashTable的区别?

对比维度HashMapHashTable
线程安全非线程安全线程安全(synchronized方法)
性能更高较低
null支持允许一个null key和多个null值不允许null键值
继承关系继承AbstractMap继承Dictionary
迭代器Fail-FastFail-Safe
初始容量1611
扩容机制2倍扩容2倍+1扩容

HashMap示例:

HashMap<String, Integer> map = new HashMap<>();
map.put(null, 1);  // 允许
map.put("key", null);  // 允许

HashTable示例:

Hashtable<String, Integer> table = new Hashtable<>();
// table.put(null, 1);  // 抛出NullPointerException
// table.put("key", null);  // 抛出NullPointerException

6. ConcurrentHashMap如何保证线程安全?

Java 7 及之前的 ConcurrentHashMap 实现

核心设计

  • 分段锁(Segment)机制
    • 将整个Map分成多个Segment(默认16个)
    • 每个Segment继承ReentrantLock
    • 不同Segment可并发操作

数据结构

static final class Segment<K,V> extends ReentrantLock {transient volatile HashEntry<K,V>[] table;// 其他字段...
}static final class HashEntry<K,V> {final K key;volatile V value;volatile HashEntry<K,V> next;
}

主要特点

  1. 并发度(Concurrency Level)

    • 可指定Segment数量(默认16)
    • 实际并发量受限于Segment数量
  2. 锁粒度

    • 只锁定单个Segment
    • 不同Segment的操作可并行
  3. 读操作

    • 完全无锁(volatile变量保证可见性)
    • 弱一致性迭代器
  4. 扩容

    • 单个Segment独立扩容
    • 不影响其他Segment访问

代码示例

ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("key", 1);  // 只锁定对应Segment

缺点

  1. 内存占用较大(每个Segment都有独立数据结构)
  2. 并发度固定,无法动态扩展
  3. 某些场景下仍存在竞争

Java 8 及之后的 ConcurrentHashMap 实现

核心改进

  • 废弃分段锁,改用:
    • CAS + synchronized 锁单个Node
    • 更细粒度的锁控制

数据结构

  • 数组 + 链表/红黑树(类似HashMap)
  • Node定义:
  static class Node<K,V> implements Map.Entry<K,V> {final int hash;final K key;volatile V val;volatile Node<K,V> next;}

主要优化

  1. 锁粒度更细

    • 只锁定链表头节点/树根节点
    • 并发度理论上等于桶数组大小
  2. CAS操作

    • 无竞争时使用CAS更新
    • 减少锁的使用
  3. 扩容机制

    • 多线程协同扩容
    • 使用ForwardingNode标记迁移状态
  4. 计数机制

    • 采用LongAdder思想
    • 分散计数热点

关键方法实现

  1. putVal()流程

    • 计算hash值
    • 如果表为空则初始化
    • 如果桶为空则CAS插入
    • 如果存在hash冲突:
      • 链表:synchronized锁定头节点
      • 红黑树:锁定树根节点
    • 超过阈值则扩容
  2. get()流程

    • 根据hash定位到桶
    • 遍历链表/红黑树查找
    • 完全无锁(依赖volatile读)

代码示例

ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.computeIfAbsent("key", k -> 1);  // 原子操作

性能对比

操作Java 7Java 8+
低并发put中等(分段锁开销)高(CAS优化)
高并发put中等(受限于并发度)高(更细粒度锁)
get高(无锁)高(无锁)
内存占用较高(分段结构)较低(统一结构)
扩容效率分段独立扩容多线程协同扩容

重要内部类变化

Java 7

  • Segment:继承ReentrantLock
  • HashEntry:链表节点

Java 8

  • Node:基础链表节点
  • TreeNode:红黑树节点
  • TreeBin:红黑树容器
  • ForwardingNode:扩容转发节点
  • ReservationNode:占位节点

并发控制机制对比

Java 7

  • 依赖Segment锁
  • put操作必须获取锁
  • size()方法较复杂(需统计各Segment)

Java 8

  • CAS + synchronized
  • put操作可能无锁(CAS成功时)
  • size()使用CounterCell减少竞争

为什么Java 8要重新设计?

  1. 锁粒度问题

    • Segment数量固定导致并发度受限
    • 实际场景中不同Segment的负载不均衡
  2. 内存占用

    • Segment结构带来额外内存开销
  3. 现代CPU架构

    • CAS操作在多数场景下比锁更高效
    • 减少线程上下文切换
  4. 技术演进

    • JVM对synchronized的优化(偏向锁、轻量级锁)
    • 借鉴了LongAdder的分段计数思想

典型使用场景建议

Java 7版本

  • 读多写少的并发场景
  • 键的hash分布均匀的情况

Java 8+版本

  • 高并发写入场景
  • 数据量大的情况
  • 需要原子复合操作(computeIfAbsent等)

通用最佳实践

  1. 合理设置初始容量(避免频繁扩容)
  2. 避免在遍历时修改Map
  3. 使用并发安全的方法(如computeIfAbsent)
  4. 监控并发性能指标

多线程面试题详解

1. 线程和进程的区别?

对比维度进程线程
资源分配操作系统分配资源的基本单位CPU调度的基本单位
内存空间每个进程有独立内存空间同一进程的线程共享内存
创建开销大(需要分配独立资源)小(共享进程资源)
通信方式管道、消息队列、共享内存等直接读写共享变量
稳定性进程崩溃不影响其他进程线程崩溃可能导致整个进程退出
并发性进程间并发线程间并发
数量限制通常几十个通常数百到数千个

关键点:

  • 进程是程序的一次执行,线程是进程内的执行单元
  • Java中无法直接操作进程,只能通过Runtime.exec()等有限方式

2. 创建线程的几种方式?

1. 继承Thread类

class MyThread extends Thread {@Overridepublic void run() {System.out.println("Thread running");}
}
// 使用
new MyThread().start();

2. 实现Runnable接口

class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("Runnable running");}
}
// 使用
new Thread(new MyRunnable()).start();

3. 实现Callable接口(带返回值)

class MyCallable implements Callable<String> {@Overridepublic String call() throws Exception {return "Callable result";}
}
// 使用
FutureTask<String> task = new FutureTask<>(new MyCallable());
new Thread(task).start();
String result = task.get(); // 获取返回值

4. 使用线程池(推荐)

ExecutorService executor = Executors.newFixedThreadPool(5);
executor.execute(() -> {System.out.println("Pool thread running");
});
executor.shutdown();

3. Runnable和Callable的区别?

对比维度RunnableCallable
返回值
异常处理不能抛出受检异常可以抛出异常
使用场景简单异步任务需要返回结果的任务
引入版本Java 1.0Java 5.0
函数式接口
执行方式Thread或Executor.execute()ExecutorService.submit()

4. 线程的生命周期(状态)有哪些?

Java线程的6种状态(Thread.State枚举):

  1. NEW(新建)

    • 线程被创建但未调用start()
  2. RUNNABLE(可运行)

    • 包括操作系统中的Ready和Running状态
    • 可能正在执行或等待CPU时间片
  3. BLOCKED(阻塞)

    • 等待获取监视器锁(synchronized)
    • 只有这种状态会竞争锁
  4. WAITING(等待)

    • 无限期等待其他线程显式唤醒
    • 通过以下方法进入:
      • Object.wait()
      • Thread.join()
      • LockSupport.park()
  5. TIMED_WAITING(超时等待)

    • 带时间限制的等待
    • 通过以下方法进入:
      • Thread.sleep(long)
      • Object.wait(long)
      • Thread.join(long)
  6. TERMINATED(终止)

    • 线程执行完毕

状态转换图:
NEW → start() → RUNNABLE
RUNNABLE → 获取锁 → BLOCKED
RUNNABLE → wait()/join() → WAITING
RUNNABLE → sleep()/wait(n) → TIMED_WAITING
各种等待状态 → 条件满足 → RUNNABLE
RUNNABLE → 执行完成 → TERMINATED

5. sleep()和wait()的区别?

对比维度sleep()wait()
所属类Thread的静态方法Object的实例方法
锁释放不释放锁释放锁
唤醒条件时间到期notify()/notifyAll()或超时
使用位置任意位置必须在同步块内(持有锁时)
异常处理需要处理InterruptedException需要处理InterruptedException
精度控制支持纳秒参数支持纳秒参数

6. synchronized关键字的用法?

三种使用方式

  1. 实例方法同步
public synchronized void method() {// 锁定当前实例
}
  1. 静态方法同步
public static synchronized void staticMethod() {// 锁定当前类的Class对象
}
  1. 同步代码块
public void block() {synchronized(obj) {  // 锁定指定对象// 临界区代码}
}

锁的特性

  • 可重入性:同一线程可重复获取同一把锁
  • 非公平性:不保证等待线程的获取顺序
  • 独占性:同一时间只有一个线程能持有锁
  • 不可中断性:等待锁的线程不能被中断

锁升级过程(Java 6+优化)
无锁 → 偏向锁 → 轻量级锁(CAS) → 重量级锁

7. volatile关键字的作用?

两大核心作用

  1. 可见性保证

    • 写操作立即刷新到主内存
    • 读操作直接从主内存读取
  2. 禁止指令重排序

    • 通过内存屏障实现
    • 保证happens-before关系

适用场景

  • 状态标志位(如while(!stop))
  • 单例模式的双重检查锁定
  • 一次性安全发布

不适用场景

  • 非原子操作的复合操作(如i++)
  • 需要互斥访问的临界区

示例:

class VolatileExample {private volatile boolean flag = false;public void writer() {flag = true;  // 写操作对其他线程立即可见}public void reader() {while(!flag) {}  // 能及时看到flag变化System.out.println("Flag changed");}
}

8. 什么是线程池?为什么要用线程池?

线程池核心组件

  • 工作线程(Worker):实际执行任务的线程
  • 任务队列(BlockingQueue):存放待执行任务
  • 线程工厂(ThreadFactory):创建新线程
  • 拒绝策略(RejectedExecutionHandler):处理任务过多情况

线程池优势

  1. 降低资源消耗:复用已创建的线程
  2. 提高响应速度:任务到达可直接执行
  3. 提高线程管理性:统一分配、调优和监控
  4. 防止资源耗尽:通过队列和拒绝策略

ThreadPoolExecutor核心参数

public ThreadPoolExecutor(int corePoolSize,      // 核心线程数int maximumPoolSize,  // 最大线程数long keepAliveTime,   // 空闲线程存活时间TimeUnit unit,        // 时间单位BlockingQueue<Runnable> workQueue,  // 任务队列ThreadFactory threadFactory,        // 线程工厂RejectedExecutionHandler handler   // 拒绝策略
)

四种常用线程池

1. newFixedThreadPool:固定大小线程池
2. newCachedThreadPool:可扩容线程池
3. newSingleThreadExecutor:单线程池
4. newScheduledThreadPool:定时任务线程池

执行流程

  1. 提交任务
  2. 如果核心线程未满,创建新线程执行
  3. 如果核心线程已满,加入任务队列
  4. 如果队列已满且线程数未达最大值,创建新线程
  5. 如果队列已满且线程数已达最大值,执行拒绝策略

拒绝策略

  1. AbortPolicy(默认):抛出RejectedExecutionException
  2. CallerRunsPolicy:由调用线程直接执行
  3. DiscardPolicy:直接丢弃任务
  4. DiscardOldestPolicy:丢弃队列最老的任务

示例代码:

ExecutorService pool = Executors.newFixedThreadPool(5);
pool.execute(() -> {System.out.println(Thread.currentThread().getName() + " executing task");
});
pool.shutdown();

IO与NIO面试题详解

1. Java IO流分为哪几种?

按数据流向分类

  • 输入流(InputStream/Reader
  • 输出流(OutputStream/Writer

按数据类型分类

  1. 字节流(8位字节):

    • InputStream(抽象基类)
      • FileInputStream
      • ByteArrayInputStream
      • BufferedInputStream
      • ObjectInputStream
    • OutputStream(抽象基类)
      • FileOutputStream
      • ByteArrayOutputStream
      • BufferedOutputStream
      • ObjectOutputStream
  2. 字符流(16位Unicode):

    • Reader(抽象基类)
      • FileReader
      • CharArrayReader
      • BufferedReader
      • InputStreamReader
    • Writer(抽象基类)
      • FileWriter
      • CharArrayWriter
      • BufferedWriter
      • OutputStreamWriter

按功能分类

  • 节点流(直接操作数据源)
  • 处理流(包装其他流,提供增强功能)

典型类结构:
InputStream
├── FileInputStream
├── FilterInputStream
│ ├── BufferedInputStream
│ └── DataInputStream
└── ObjectInputStream

Reader
├── FileReader
├── BufferedReader
└── InputStreamReader

2. 字节流和字符流的区别?

对比维度字节流字符流
基本单位8位字节16位Unicode字符
处理类型二进制数据(如图片、音频)文本数据
基类InputStream/OutputStreamReader/Writer
缓冲区通常无内置缓冲通常内置缓冲
编码转换不处理编码自动处理字符编码转换
典型场景文件复制、网络数据传输文本文件读写
性能处理二进制更快处理文本更方便

转换流示例:

// 字节流转字符流(指定编码)
InputStreamReader isr = new InputStreamReader(new FileInputStream("file.txt"), "UTF-8");

// 字符流转字节流

OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("file.txt"), "GBK");

3. BIO、NIO和AIO的区别?

对比维度BIO (Blocking IO)NIO (Non-blocking IO)AIO (Asynchronous IO)
IO模型同步阻塞同步非阻塞异步非阻塞
数据准备线程阻塞等待数据就绪轮询检查数据就绪状态OS通知数据就绪
处理方式面向流(Stream)面向缓冲区(Buffer)面向事件和回调
线程开销每个连接需要独立线程单线程处理多连接回调机制减少线程占用
吞吐量低(线程上下文切换开销)高(减少线程数量)最高(无等待时间)
适用场景连接数少的固定架构连接数多且连接时间短连接数多且连接时间长
JDK支持Java 1.0Java 1.4Java 7

BIO示例:

ServerSocket server = new ServerSocket(8080);
while(true) {Socket client = server.accept();  // 阻塞new Thread(() -> handleClient(client)).start();
}

NIO示例:

Selector selector = Selector.open();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ);
while(true) {int ready = selector.select();  // 非阻塞Set<SelectionKey> keys = selector.selectedKeys();// 处理就绪的通道
}

4. NIO的核心组件有哪些?

1. Buffer(缓冲区)

  • 数据容器,提供结构化访问
  • 核心实现类:
    • ByteBuffer(最常用)
    • CharBuffer
    • IntBuffer
    • 等基本类型Buffer
  • 重要属性:
    • capacity(容量)
    • position(当前位置)
    • limit(读写限制)
    • mark(标记位置)

2. Channel(通道)

  • 双向数据传输管道
  • 主要实现:
    • FileChannel(文件IO)
    • SocketChannel(TCP)
    • ServerSocketChannel(TCP服务端)
    • DatagramChannel(UDP)
  • 特点:
    • 可异步读写
    • 必须配合Buffer使用

3. Selector(选择器)

  • 多路复用器,单线程管理多个Channel
  • 核心方法:
    • open():创建Selector
    • select():监控注册的Channel
    • selectedKeys():获取就绪的SelectionKey集合
  • 事件类型:
    • OP_ACCEPT:连接接受
    • OP_CONNECT:连接就绪
    • OP_READ:读就绪
    • OP_WRITE:写就绪

4. Charset(字符集)

  • 处理字符编码/解码
  • 常用字符集:
    • StandardCharsets.UTF_8
    • StandardCharsets.ISO_8859_1
    • StandardCharsets.US_ASCII

NIO文件复制示例:

FileChannel inChannel = new FileInputStream("source.txt").getChannel();
FileChannel outChannel = new FileOutputStream("target.txt").getChannel();ByteBuffer buffer = ByteBuffer.allocate(1024);
while(inChannel.read(buffer) != -1) {buffer.flip();  // 切换为读模式outChannel.write(buffer);buffer.clear(); // 清空缓冲区
}

NIO网络编程示例:

Selector selector = Selector.open();
ServerSocketChannel server = ServerSocketChannel.open();
server.bind(new InetSocketAddress(8080));
server.configureBlocking(false);
server.register(selector, SelectionKey.OP_ACCEPT);while(true) {selector.select();Set<SelectionKey> keys = selector.selectedKeys();Iterator<SelectionKey> iter = keys.iterator();while(iter.hasNext()) {SelectionKey key = iter.next();if(key.isAcceptable()) {// 处理新连接SocketChannel client = server.accept();client.configureBlocking(false);client.register(selector, SelectionKey.OP_READ);} else if(key.isReadable()) {// 处理读事件SocketChannel client = (SocketChannel) key.channel();ByteBuffer buffer = ByteBuffer.allocate(1024);client.read(buffer);// 处理数据...}iter.remove();}
}

反射与泛型面试题详解

1. 什么是反射?反射的应用场景?

反射(Reflection)定义

  • 在运行时动态获取类的完整结构信息
  • 动态操作类属性、方法和构造器
  • 核心类:ClassFieldMethodConstructor

主要功能

  1. 运行时获取类的修饰符、父类、接口、注解等信息
  2. 运行时构造任意类的对象
  3. 运行时调用任意对象的方法
  4. 运行时访问/修改字段值(包括private字段)
  5. 动态创建和操作数组

应用场景

  • 框架开发(Spring的IoC容器)
  • 动态代理(AOP实现)
  • 注解处理器
  • 通用工具类(如BeanUtils)
  • 序列化/反序列化
  • IDE的代码提示

示例代码
// 获取类信息
Class<?> clazz = Class.forName(“java.lang.String”);
Field[] fields = clazz.getDeclaredFields();

// 创建实例
Constructor<?> constructor = clazz.getConstructor(String.class);
Object str = constructor.newInstance(“Hello”);

// 调用方法
Method method = clazz.getMethod(“length”);
int len = (int) method.invoke(str);

2. 如何获取Class对象?

4种获取方式

  1. 类名.class(最安全高效)
    Class stringClass = String.class;

  2. 对象.getClass()
    String s = “”;
    Class<?> clazz = s.getClass();

  3. Class.forName()(最灵活)
    Class<?> clazz = Class.forName(“java.lang.String”);

  4. 类加载器.loadClass()
    Class<?> clazz = MyClass.class.getClassLoader().loadClass(“com.example.MyClass”);

区别对比

方式是否初始化类适用场景
类名.class编译时已知类名
getClass()已有对象实例
Class.forName()动态加载类(如JDBC驱动)
ClassLoader.loadClass()需要控制类加载过程

3. 什么是泛型?泛型擦除是什么意思?

泛型(Generics)定义

  • 参数化类型,将类型作为参数
  • 主要作用:
    • 类型安全(编译时检查)
    • 消除强制类型转换
    • 代码复用(通用算法)

泛型擦除(Type Erasure)

  • Java编译器在编译时去除泛型类型信息
  • 运行时只保留原始类型(Raw Type)
  • 所有泛型类型最终都会被替换为Object或上界类型

擦除规则

  1. 无界泛型:List<T>List
  2. 有界泛型:List<T extends Number>List<Number>
  3. 泛型方法:类型参数会被擦除到第一个边界

示例说明
// 编译前
List list = new ArrayList<>();
list.add(“hello”);
String s = list.get(0);

// 编译后(擦除后)
List list = new ArrayList();
list.add(“hello”);
String s = (String) list.get(0); // 强制转换

Java 8新特性面试题详解

1. Lambda表达式的作用?

核心作用

  • 简化匿名内部类的写法
  • 实现函数式编程风格
  • 使代码更简洁、可读性更强

语法结构
(parameters) -> expression

(parameters) -> { statements; }

特点

  1. 可选类型声明:编译器可推断参数类型
  2. 可选参数圆括号:单参数时可省略
  3. 可选大括号:单条语句时可省略
  4. 可选return关键字:单条表达式时自动返回

使用示例

// 替代匿名类
Runnable r1 = new Runnable() {@Overridepublic void run() {System.out.println("Old way");}
};Runnable r2 = () -> System.out.println("Lambda way");// 集合操作
list.forEach(item -> System.out.println(item));

2. Stream API的常用方法有哪些?

常用中间操作

  • filter(Predicate):过滤元素
  • map(Function):元素转换
  • flatMap(Function):扁平化流
  • distinct():去重
  • sorted():排序
  • peek(Consumer):查看元素但不修改

常用终端操作

  • forEach(Consumer):遍历
  • collect(Collector):转换为集合
  • toArray():转换为数组
  • reduce():归约操作
  • count():计数
  • anyMatch()/allMatch()/noneMatch():匹配检查
  • findFirst()/findAny():查找元素

示例代码

List<String> result = list.stream().filter(s -> s.length() > 3).map(String::toUpperCase).sorted().collect(Collectors.toList());long count = list.stream().distinct().count();

3. 什么是函数式接口?常见的函数式接口有哪些?

函数式接口定义

  • 只有一个抽象方法的接口
  • 可用@FunctionalInterface注解标记
  • Lambda表达式的目标类型

四大核心函数式接口

  1. Consumer

    • 消费型:接受输入无返回
    • 方法:void accept(T t)
    • 示例:list.forEach(System.out::println)
  2. Supplier

    • 供给型:无输入有返回
    • 方法:T get()
    • 示例:() -> new Random().nextInt()
  3. Function<T,R>

    • 函数型:接受T返回R
    • 方法:R apply(T t)
    • 示例:String::length
  4. Predicate

    • 断言型:接受T返回boolean
    • 方法:boolean test(T t)
    • 示例:s -> s.startsWith("A")

其他常用接口

  • UnaryOperator<T>:一元操作(继承Function)
  • BinaryOperator<T>:二元操作
  • BiFunction<T,U,R>:双参数函数
  • BiConsumer<T,U>:双参数消费者

4. Optional类的作用?

设计目的

  • 优雅处理null值问题
  • 避免NullPointerException
  • 明确表示"值可能不存在"的语义

核心方法

  1. 创建:

    • Optional.of(value)(非null值)
    • Optional.ofNullable(value)(可null值)
    • Optional.empty()(空实例)
  2. 值处理:

    • get():获取值(不安全)
    • orElse(default):获取值或默认值
    • orElseGet(supplier):获取值或计算默认值
    • orElseThrow(exceptionSupplier):获取值或抛异常
  3. 条件处理:

    • isPresent():判断值是否存在
    • ifPresent(consumer):值存在时执行操作
    • filter(predicate):过滤值
    • map(function):值转换

使用示例

// 传统null检查
if(user != null) {Address address = user.getAddress();if(address != null) {return address.getStreet();}
}
return "unknown";// Optional方式
return Optional.ofNullable(user).map(User::getAddress).map(Address::getStreet).orElse("unknown");

最佳实践

  1. 不要用Optional作为方法参数
  2. 不要用Optional.get()而不检查isPresent()
  3. 优先使用orElse/orElseGet替代get()
  4. 集合返回空集合而非Optional

JVM基础面试题详解

1. JVM内存结构是怎样的?

JVM内存主要分区

  1. 程序计数器(PC Register)

    • 线程私有
    • 记录当前线程执行的字节码行号
    • 唯一不会OOM的区域
  2. Java虚拟机栈(Java Stack)

    • 线程私有
    • 存储栈帧(方法调用的局部变量、操作数栈等)
    • 可能抛出StackOverflowError/OutOfMemoryError
  3. 本地方法栈(Native Stack)

    • 线程私有
    • 为Native方法服务
  4. 堆(Heap)

    • 线程共享
    • 存储对象实例和数组
    • GC主要工作区域
    • 分代设计(新生代/老年代)
  5. 方法区(Method Area)

    • 线程共享
    • 存储类信息、常量、静态变量等
    • JDK8后由元空间(Metaspace)实现
  6. 运行时常量池(Runtime Constant Pool)

    • 方法区的一部分
    • 存储编译期生成的字面量和符号引用

内存结构图示
[JVM内存结构]
线程私有区:

  • 程序计数器
  • Java栈
  • 本地方法栈

线程共享区:

  • 方法区
    • 运行时常量池

2. 什么是垃圾回收(GC)?常见的垃圾回收算法有哪些?

GC核心概念

  • 自动管理堆内存
  • 识别并回收不再使用的对象
  • 防止内存泄漏

判断对象可回收的算法

  1. 引用计数法

    • 对象被引用时计数器+1
    • 为0时回收
    • 问题:循环引用无法处理
  2. 可达性分析(主流)

    • 从GC Roots对象开始遍历引用链
    • 不可达对象判定为可回收
    • GC Roots包括:
      • 虚拟机栈引用的对象
      • 方法区静态属性引用的对象
      • 方法区常量引用的对象
      • Native方法引用的对象

垃圾回收算法

  1. 标记-清除(Mark-Sweep)

    • 步骤:标记可回收对象 → 清除
    • 问题:内存碎片
  2. 复制算法(Copying)

    • 将存活对象复制到另一半空间
    • 适用场景:新生代(Edem:Survivor=8:1)
    • 优点:无碎片
    • 缺点:空间利用率低
  3. 标记-整理(Mark-Compact)

    • 步骤:标记 → 存活对象向一端移动 → 清理边界
    • 适用场景:老年代
    • 优点:无碎片
    • 缺点:移动成本高
  4. 分代收集(Generational Collection)

    • 新生代:复制算法
    • 老年代:标记-清除/标记-整理
    • 现代JVM主流策略

GC触发条件

  • Minor GC:Eden区满
  • Full GC:
    • 老年代空间不足
    • 方法区空间不足
    • System.gc()调用

3. 强引用、软引用、弱引用和虚引用的区别?

引用类型回收时机用途实现类
强引用永不回收(即使OOM)普通对象引用默认
软引用内存不足时回收内存敏感缓存SoftReference
弱引用下次GC时回收规范映射/临时缓存WeakReference
虚引用随时可能回收对象回收跟踪PhantomReference

代码示例

// 强引用
Object obj = new Object();// 软引用
SoftReference<Object> softRef = new SoftReference<>(new Object());// 弱引用
WeakReference<Object> weakRef = new WeakReference<>(new Object());// 虚引用
ReferenceQueue<Object> queue = new ReferenceQueue<>();
PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), queue);

引用队列(ReferenceQueue)

  • 配合软/弱/虚引用使用
  • 被引用对象回收后,引用对象入队
  • 用于执行后续清理操作

4. 类加载过程是怎样的?

类加载的生命周期

  1. 加载(Loading)
  2. 验证(Verification)
  3. 准备(Preparation)
  4. 解析(Resolution)
  5. 初始化(Initialization)
  6. 使用(Using)
  7. 卸载(Unloading)

详细过程

  1. 加载

    • 通过全限定名获取二进制字节流
    • 将字节流转化为方法区的运行时数据结构
    • 在堆中生成Class对象作为访问入口
  2. 验证

    • 文件格式验证(魔数等)
    • 元数据验证(语义分析)
    • 字节码验证(StackMapTable)
    • 符号引用验证
  3. 准备

    • 为类变量(static)分配内存
    • 设置初始值(零值)
    • final static变量直接赋实际值
  4. 解析

    • 将符号引用转为直接引用
    • 类/接口解析
    • 字段解析
    • 方法解析
  5. 初始化

    • 执行类构造器()
    • 父类先初始化
    • 线程安全执行

类加载器

  1. 启动类加载器(Bootstrap)

    • 加载JAVA_HOME/lib下的核心类
    • 由C++实现,无Java对应类
  2. 扩展类加载器(Extension)

    • 加载JAVA_HOME/lib/ext下的类
    • Java实现,sun.misc.Launcher$ExtClassLoader
  3. 应用类加载器(Application)

    • 加载classpath下的类
    • Java实现,sun.misc.Launcher$AppClassLoader
  4. 自定义类加载器

    • 继承ClassLoader实现

双亲委派模型

  1. 子加载器先委托父加载器加载
  2. 父加载器无法完成时子加载器尝试
  3. 防止核心类被篡改
  4. 避免重复加载

打破双亲委派的场景

  • SPI服务加载(如JDBC)
  • OSGi模块化
  • 热部署实现

类初始化触发条件

  1. new/getstatic/putstatic/invokestatic指令
  2. 反射调用
  3. 初始化子类时父类未初始化
  4. 主类(包含main()的类)
  5. MethodHandle调用

Java Stream 补充面试题详解

1. Stream 的中间操作和终止操作有什么区别?

特性中间操作终止操作
返回值返回新Stream返回非Stream结果或void
执行时机延迟执行(lazy)触发实际计算
可链式调用
示例filter(), map()collect(), forEach()

重要特点

  • 一个Stream只能有一个终止操作
  • 中间操作可以多个连续调用
  • 没有终止操作时,中间操作不会执行

2. 并行流(Parallel Stream)使用时要注意什么?

使用方式

List<Integer> numbers = Arrays.asList(1, 2, 3);
numbers.parallelStream().forEach(System.out::println);

注意事项

  1. 线程安全

    • 确保共享变量是线程安全的
    • 避免在lambda中修改外部状态
  2. 性能考量

    • 数据量小时可能比串行流更慢
    • 适合CPU密集型操作
    • 不适合IO密集型操作
  3. 顺序问题

    • forEachOrdered()保证顺序
    • 某些操作(如findAny)在并行流中行为不同
  4. 资源控制

    • 默认使用ForkJoinPool.commonPool()
    • 可自定义线程池:
      ForkJoinPool customPool = new ForkJoinPool(4);
      customPool.submit(() -> list.parallelStream().forEach(…));

3. Stream 和 Collection 的区别?

维度StreamCollection
数据存储不存储数据存储所有元素
数据处理函数式操作命令式操作
遍历次数一次性(用完即闭)可多次遍历
延迟执行支持不支持
并行处理原生支持需手动实现
内存占用通常更低存储全部数据

4. 常用的 Stream 收集器(Collectors)有哪些?

常用静态方法

  1. toList():收集为List
    List list = stream.collect(Collectors.toList());

  2. toSet():收集为Set
    Set set = stream.collect(Collectors.toSet());

  3. toMap():收集为Map
    Map<String, Integer> map = stream.collect(
    Collectors.toMap(Function.identity(), String::length));

  4. groupingBy():分组
    Map<Integer, List> group = stream.collect(
    Collectors.groupingBy(String::length));

  5. partitioningBy():分区
    Map<Boolean, List> partition = stream.collect(
    Collectors.partitioningBy(s -> s.length() > 3));

  6. joining():字符串连接
    String joined = stream.collect(Collectors.joining(", "));

  7. summarizingInt():统计汇总
    IntSummaryStatistics stats = stream.collect(
    Collectors.summarizingInt(String::length));

5. Stream 中的 findFirst() 和 findAny() 有什么区别?

方法行为并行流表现
findFirst()返回第一个元素(按相遇顺序)保证返回流中第一个元素
findAny()返回任意元素可能返回任意匹配元素

使用场景

  • 需要确定性的结果:用findFirst()
  • 只需要任意匹配项且不关心顺序:用findAny()(并行流性能更好)

6. Stream 的 flatMap() 和 map() 有什么区别?

map()

  • 一对一的元素转换
  • 不会改变流中元素数量
  • 示例:
  List<String> words = Arrays.asList("Hello", "World");List<Integer> lengths = words.stream().map(String::length)  // ["Hello", "World"] → [5, 5].collect(Collectors.toList());

flatMap()

  • 一对多的元素转换
  • 将嵌套流"扁平化"为一个流
  • 示例:
  List<List<String>> listOfLists = Arrays.asList(Arrays.asList("a", "b"),Arrays.asList("c", "d"));List<String> flatList = listOfLists.stream().flatMap(List::stream)  // [["a","b"],["c","d"]] → ["a","b","c","d"].collect(Collectors.toList());

7. 如何用 Stream 处理大文件?

高效读取大文件示例

try (Stream<String> lines = Files.lines(Paths.get("large.txt"))) {List<String> result = lines.filter(line -> line.contains("keyword")).limit(1000).collect(Collectors.toList());
}

优势

  • Files.lines()不会一次性加载整个文件
  • 流式处理保持低内存占用
  • 可配合limit()控制处理量

8. Stream 的 peek() 和 forEach() 有什么区别?

方法返回类型用途是否触发计算
peek()Stream调试/观察元素(中间操作)
forEach()void执行副作用(终止操作)

peek()示例

List<String> collected = Stream.of("a", "b", "c").peek(System.out::println)  // 调试用.map(String::toUpperCase).collect(Collectors.toList());

forEach()示例

Stream.of("a", "b", "c").forEach(System.out::println);  // 实际消费流

9. 如何自定义 Collector?

实现 Collector 接口

Collector<String, List<String>, List<String>> toListIgnoreCase = Collector.of(ArrayList::new,                  // supplier(list, str) -> list.add(str.toLowerCase()),  // accumulator(list1, list2) -> {              // combinerlist1.addAll(list2);return list1;},Collector.Characteristics.IDENTITY_FINISH);List<String> result = stream.collect(toListIgnoreCase);

核心参数

  1. Supplier:创建结果容器
  2. Accumulator:将元素添加到容器
  3. Combiner:合并两个容器(并行流用)
  4. Finisher:最终转换(可选)
  5. Characteristics:收集器特性

10. Stream 的 reduce() 方法如何使用?

三种形式

  1. 基本形式:
Optional<T> reduce(BinaryOperator<T> accumulator)Optional<Integer> sum = Stream.of(1, 2, 3).reduce((a, b) -> a + b);
  1. 带初始值:
T reduce(T identity, BinaryOperator<T> accumulator)int sum = Stream.of(1, 2, 3).reduce(0, (a, b) -> a + b);
  1. 复杂形式(并行流用):
<U> U reduce(U identity,BiFunction<U,? super T,U> accumulator,BinaryOperator<U> combiner)int sum = Stream.of(1, 2, 3).reduce(0,(partialSum, num) -> partialSum + num,Integer::sum);

使用场景

  • 聚合计算(求和、求积等)
  • 复杂对象构建
  • 替代某些collect()操作

Java 其他高频面试题补充

1. Java 模块化系统(Java 9+)

关键概念

  • module-info.java:模块描述文件
  • 模块路径 vs 类路径
  • 访问控制规则:
    • requires:声明依赖
    • exports:公开包
    • opens:反射开放包

面试问题

  • 模块化解决了什么问题?
  • 如何迁移传统项目到模块化系统?
  • requires staticrequires transitive的区别?

2. 记录类型(Record, Java 14+)

特点

  • 不可变数据载体
  • 自动生成:构造器、访问器、equals()、hashCode()、toString()

示例
public record Point(int x, int y) {}

面试问题

  • Record 和传统类的区别?
  • 如何自定义 Record 的方法?
  • Record 能否继承其他类?

3. 密封类(Sealed Class, Java 15+)

特点

  • 限制哪些类可以继承自己
  • 通过permits关键字指定子类

示例
public sealed class Shape
permits Circle, Square, Rectangle {…}

面试问题

  • 密封类的设计目的是什么?
  • 密封类与final类的区别?
  • 如何与Record结合使用?

4. 模式匹配(Java 16+)

instanceof 模式匹配
if (obj instanceof String str) {
System.out.println(str.length());
}

switch 表达式增强
return switch (day) {
case MONDAY, FRIDAY -> “工作日”;
case SATURDAY, SUNDAY -> “周末”;
default -> throw new IllegalArgumentException();
};

面试问题

  • 模式匹配如何简化代码?
  • switch表达式与传统switch的区别?
  • 什么情况下会抛出MatchError?

5. 虚拟线程(Virtual Thread, Java 19+)

特点

  • 轻量级线程(协程)
  • 由JVM调度,非OS线程
  • 高吞吐量(支持百万级线程)

使用方式
Thread.startVirtualThread(() -> {
System.out.println(“Virtual thread running”);
});

面试问题

  • 虚拟线程与传统线程的区别?
  • 什么场景适合使用虚拟线程?
  • 如何避免虚拟线程的pin操作?

6. 响应式编程(Reactive Streams)

核心接口

  • Publisher
  • Subscriber
  • Subscription
  • Processor<T,R>

面试问题

  • 背压(Backpressure)是什么?
  • 如何实现冷热数据流?
  • Reactor 和 RxJava 的主要区别?

7. Java 原生内存访问(Java 16+)

Foreign Function & Memory API

  • 替代JNI的更安全方式
  • 直接操作堆外内存

示例
try (MemorySegment segment = MemorySegment.allocateNative(100)) {
segment.set(ValueLayout.JAVA_INT, 0, 42);
}

面试问题

  • 为什么需要新的内存访问API?
  • MemorySegment 和 ByteBuffer 的区别?
  • 如何防止使用原生API导致的内存泄漏?

8. 协程库比较

库名特点适用场景
Quasar字节码增强传统Java项目
Kilim轻量级简单协程需求
Project LoomJVM原生支持(虚拟线程)Java 19+项目

面试问题

  • 协程与线程的本质区别?
  • 如何在Java 8项目中使用协程?
  • 协程的栈结构如何实现?

9. 微基准测试(JMH)

典型问题

  • 如何正确测量Java方法性能?
  • JMH 如何避免JIT优化干扰?
  • @BenchmarkMode 的几种模式区别?
  • 什么是死代码消除(Dead Code Elimination)?

10. 代码安全实践

重点领域

  1. 反序列化漏洞防护

    • 使用白名单控制可反序列化类
    • 替代方案:JSON/Protocol Buffers
  2. 密码学安全

    • 避免使用弱算法(MD5/SHA1)
    • 正确使用初始化向量(IV)
  3. 内存安全

    • 敏感数据及时清零(char[]处理密码)
    • 防止时序攻击

面试问题

  • 如何安全存储用户密码?
  • 为什么推荐使用BCrypt而不是SHA系列?
  • Java 的 SecureRandom 实现原理?

11. JVM 性能调优

常用工具

  1. 命令行工具:
    • jps, jstat, jstack, jmap
  2. 图形化工具:
    • VisualVM, JConsole
  3. 高级工具:
    • Async Profiler, JFR(Java Flight Recorder)

调优参数

  • 堆内存:-Xms, -Xmx
  • 元空间:-XX:MetaspaceSize
  • GC选择:-XX:+UseG1GC
  • 日志输出:-Xlog:gc*

面试问题

  • 如何分析OOM问题?
  • G1 和 ZGC 的适用场景区别?
  • 如何诊断线程死锁?

12. 现代Java开发实践

热点话题

  1. 不可变设计:

    • Record 的使用
    • 防御性拷贝
  2. 空值处理:

    • Optional 最佳实践
    • 静态分析工具(@NonNull)
  3. 并发模式:

    • CompletableFuture 组合
    • 反应式编程

面试问题

  • 为什么提倡不可变对象?
  • Optional.flatMap() 和 map() 的区别?
  • 如何设计无锁数据结构?

相关文章:

Java基础概念汇总

JavaEE Java基础概念面试题详解1. Java的特点是什么&#xff1f;2. Java和C的区别有哪些&#xff1f;3. 什么是JDK、JRE和JVM&#xff1f;它们之间有什么关系&#xff1f;4. Java是编译型语言还是解释型语言&#xff1f;5. Java如何实现跨平台&#xff1f; 数据类型与变量面试题…...

【服务端】使用conda虚拟环境部署Django项目

写在开头 为了与客户端的Deep search配合&#xff0c;需要整一个后台管理来保存和管理deep search的数据资料。选择前端框架Vue-Vben-Admin Django后台服务来实现这个项目。 废话结束&#xff0c;从零开始。。。。 一、环境搭建 1. 安装 Anaconda 下载 Anaconda&#xff1…...

基于Pycatia的智能孔特征识别技术:无参模型圆心自动化提取方案

引言 本文介绍了一种基于Pycatia二次开发的无参数模型孔特征识别技术&#xff0c;通过拓扑分析与几何特征检测双验证机制&#xff0c;实现圆形孔边线的精准识别及圆心坐标自动化生成。该方案可有效解决逆向工程、质量检测等场景下非参数化模型的孔位分析难题&#xff0c;提升三…...

cpu 比较低,load 比较高怎么解决

当系统出现 CPU 使用率低但 Load Average(系统负载)高 的情况时,通常意味着系统资源瓶颈不在 CPU,而可能出现在其他环节(如 I/O 等待、锁竞争、大量进程排队等)。以下是排查和解决问题的详细步骤: 一、理解 Load Average 的含义 Linux 系统的 Load Average 表示 单位时…...

qt QQuaternion详解

1. 概述 QQuaternion 是 Qt 中用于表示三维空间中旋转的四元数类。它包含一个标量部分和一个三维向量部分&#xff0c;可以用来表示旋转操作。四元数在计算机图形学中广泛用于平滑的旋转和插值。 2. 重要方法 默认构造函数 QQuaternion::QQuaternion(); // 构造单位四元数 (1…...

伊利工业旅游4.0,近距离感受高品质的魅力

3月24日&#xff0c;在2025年第112届全国糖酒会&#xff08;简称春糖&#xff09;前夕&#xff0c;伊利集团“可感知高品质探寻荟”活动在成都召开&#xff0c;记者走进伊利在西南地区最大的乳制品生产基地—邛崃工厂&#xff0c;零距离见证液态奶、酸奶、冷饮等乳制品的诞生&a…...

前端面经分享(25/03/26)

北京一家做AI解决方案的公司&#xff0c;技术一面&#xff0c;15k-20k&#xff0c;要求3-5年 你们React项目里路由模式用的什么React里class组件和function组件都用过吗常用Hook&#xff0c;解释一下他们的作用useEffect第二个参数填空数组和不填有什么区别React组件通信的常用…...

unity实现图片查看器有限制的移动缩放功能

需求 unity实现键盘wasd键控制图片的移动&#xff0c;图片长度未超出屏幕不能移动&#xff0c;宽度未超出屏幕不能移动。jk键控制图片的缩放&#xff0c;缩放有限制 using UnityEngine;public class ImageController : MonoBehaviour {[Header("移动设置")]public f…...

STM32基础教程——输入捕获模式测量PWM频率

目录 前言 技术实现 原理图 连线图 代码实现 内容要点 PWM基本结构 开启外设时钟 配置GPIO端口 配置时基单元 初始化输出比较单元 输出比较通道重映射 输入捕获功能初始化 计算捕获PWM的频率 实验结果 问题记录 前言 IC&#xff08;Input Capture&#xff09;输…...

【redis】集群 如何搭建集群详解

文章目录 集群搭建1. 创建目录和配置2. 编写 docker-compose.yml完整配置文件 3. 启动容器4. 构建集群超时 集群搭建 基于 docker 在我们云服务器上搭建出一个 redis 集群出来 当前节点&#xff0c;主要是因为我们只有一个云服务器&#xff0c;搞分布式系统&#xff0c;就比较…...

Linux应用:线程基础

线程介绍 进程是程序在操作系统里的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的一个执行单元&#xff0c;是 CPU 调度和分派的基本单位。一个进程可以包含多个线程&#xff0c;这些线程共享进程的资源&#xff0c;如内存空间、文…...

力扣HOT100之普通数组:238. 除自身以外数组的乘积

这道题不能使用除法&#xff0c;我第一时间想到用前缀表和后缀表来解决&#xff0c;假设数组nums的长度为n&#xff0c;我们直接定义前缀表pre和后缀表suf&#xff0c;其中pre[i] pre[i - 1] * nums[i - 1] nums[0] * nums[1] * ... * nums[i - 1] &#xff0c;而suf[j] suf…...

PHP回调后门小总结

目录 1.call_user_func 函数说明 蚁剑连接 2.数组操作造成的单参数回调后门 array_filter 函数说明 蚁剑连接 array_map 函数说明 蚁剑连接 3.二参数回调函数 uasort 函数说明 uksort array_reduce array_udiff 蚁剑连接 4.三参数的回调后门 array_walk 函数说…...

《深度剖析SQL数据类型转换:隐式与显式的奥秘》

在SQL的世界里&#xff0c;数据类型转换是一个基础且关键的操作&#xff0c;它贯穿于数据库开发、管理与数据分析的各个环节。数据类型转换分为隐式转换和显式转换&#xff0c;二者各有特点与应用场景&#xff0c;深刻理解它们对于编写高效、稳定的SQL代码至关重要。 一、数据…...

通过TIM+DMA Burst 实现STM32输出变频且不同脉冲数量的PWM波形

Burst介绍&#xff1a; DMA控制器可以生成单次传输或增量突发传输&#xff0c;传输的节拍数为4、8或16。 为了确保数据一致性&#xff0c;构成突发传输的每组传输都是不可分割的&#xff1a;AHB传输被锁定&#xff0c;AHB总线矩阵的仲裁器在突发传输序列期间不会撤销DMA主设备…...

多线程 --- 多线程编程

在写代码的时候&#xff0c;可以使用多进程进行并发编程&#xff08;在Java中&#xff0c;不太推荐&#xff0c;很多很多关于进程相关的API&#xff0c;在Java标准库中&#xff0c;都没有提供&#xff09;&#xff0c;也可以使用多线程进行并发编程&#xff08;系统提供了多线程…...

利用新一代雷达传感器增强ADAS系统的检测和计算(TI文档)

摘要 德州仪器 (TI) 的新一代雷达传感器AWR2E44P和AWR2944P推动了TI的ADAS雷达产品系列发展&#xff0c;专注于提 高性能以满足严格的 NCAP&#xff08;新车评估计划&#xff09;和 FMVSS&#xff08;联邦机动车辆安全标准&#xff09;自动驾驶和安全法规。这些雷 达器件为 AWR…...

前端工程化开篇

前端发展史梳理&#xff1a; 最早的html&#xff0c;css&#xff0c;js是前端三剑客&#xff0c;足以实现所有的前端开发任务&#xff0c;但是呢&#xff0c;一个简单的前端交互效果可能就需要一大堆的代码去实现。 后来呢&#xff0c;有了前端库jQuery&#xff0c;他可以使前…...

Android 问真八字-v2.1.7[看八字APP]

Android 问真八字 链接&#xff1a;https://pan.xunlei.com/s/VOMMuCVQRQrM2vRsHj14SsO0A1?pwdavzw# Android 问真八字-v2.1.7[看八字APP]...

go - grpc入门

前期准备 工具安装及使用 grpc开发 编写proto文件 proto文件是符合Protocol Buffers语言规范的数据交换协议文件&#xff0c;就像以前WebService定义服务时使用的XML文件。现在一般都是用proto3了&#xff0c;这里创建一个名为 hello.proto 的文件&#xff0c;放到项目的pr…...

Linux操作系统配置本地yum源和定时任务

操作系统环境&#xff1a;CentOS 7.2 本地yum源配置 1.挂载镜像 mount /dev/cdrom /mnt/cdrom 2.备份原yum配置 mv /etc/yum.repos.d /etc/yum.repos.d.bak 3.创建本地yum源配置文件 mkdir /etc/yum.repos.d vi /etc/yum.repos.d/CentOS-local.repo 添加内容&#xff1a; #本…...

【活动回顾】StarRocks Singapore Meetup #2 @Shopee

3 月 13 日&#xff0c;StarRocks 社区在新加坡成功举办了第二场 Meetup 活动&#xff0c;主题为“Empowering Customer-Facing Analytics”。本次活动在 Shopee 新加坡办公室举行&#xff0c;吸引了来自 Shopee、Grab 和 Pinterest 的专家讲师以及 50 多位参会者。大家围绕电商…...

优选算法——双指针专题

本章先分享关于优选算法的双指针的思路&#xff1a; 主要是以题目来展示常见使用双指针的思路。 ps: 双指针做法&#xff1a;不要被表面所迷惑&#xff0c;它其实是通过用一个数组的下标来充当指针 数组分两块&#xff1a;是⾮常常⻅的⼀种题型&#xff0c;主要就是根据⼀种…...

深度解析:TOML、XML、YAML及其他配置/数据格式对比

深度解析&#xff1a;TOML、XML、YAML及其他配置/数据格式对比 在软件开发和系统配置中&#xff0c;选择合适的配置或数据格式至关重要。本文将对比 TOML、XML、YAML 等常见格式&#xff0c;梳理它们的核心特性、适用场景及区别&#xff0c;并扩展介绍其他类似格式&#xff0c…...

冗余技术:堆叠技术+链路聚合

目录 前言 一.堆叠技术概述 二.堆叠技术原理 三.堆叠系统登录 四.堆叠合并/分裂 4.1 堆叠双主检测机制&#xff08;MAD&#xff09; 五.链路聚合技术概述 六.链路聚合模式 前言 在硬件加速与数据爆炸时代&#xff0c;堆叠技术通过模块化分层设计&#xff0c;实现资源动…...

存储服务器是指什么

今天小编主要来为大家介绍存储服务器主要是指什么&#xff0c;存储服务器与传统的物理服务器和云服务器是不同的&#xff0c;其是为了特定的目标所设计的&#xff0c;在硬件配置方式上也有着一定的区别&#xff0c;存储空间会根据需求的不同而改变。 存储服务器中一般会配备大容…...

文件上传绕过的小点总结(8)

16.apache解析漏洞条件竞争 class MyUpload{.................. var $cls_arr_ext_accepted array(".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",&q…...

设计模式-结构型模式-外观模式

概述 外观模式 : Facade Pattern : 是一种 结构型设计模式. 它为复杂子系统提供一个简化的统一接口&#xff0c;使得客户端无需直接与子系统的各个组件交互&#xff0c;从而降低系统的耦合性。 核心思想 统一接口&#xff1a;将多个子系统的复杂操作封装到一个“外观类”中&…...

DeepSeek 本地部署指南

文章目录 DeepSeek 本地部署指南一、前言二、部署前的准备工作2.1 硬件要求2.2 软件环境 三、模型下载四、本地部署步骤4.1 检查硬件加速支持4.2 部署模型4.3 优化部署 五、常见问题及解决方法5.1 内存不足5.2 模型下载失败5.3 GPU 无法使用 六、总结 DeepSeek 本地部署指南 一…...

Windows Server 2025 使用 IIS 搭建 ASP.NET 3.5 网站

开启远程桌面 参考文章Windows server开启远程桌面教程打开服务管理器。ECS 配置安全组&#xff0c;开启 3389Telnet 验证网络联通性 telnet x.x.x.x 338安装 Windows App&#xff0c;登录验证 安装 ASP.NET 3.5 1.参考文章Windows Server 2012安装 .NET Framework 3.5和 Wi…...

python每日十题(12)

根据字典的索引方式可知&#xff0c;d.get( egg ,no this food)索引的是字典第一层&#xff0c;但是第一层只有键food&#xff0c;没有键egg&#xff0c;故索引不出值&#xff0c;输出的是“no this food ”。 外层for循环是将a[0][1,2,3],a[1][4,5,6],a[2][7,8,9]依次赋给变量…...

Podman 学习总结

Podman 概述 什么是 Podman&#xff1f; Podman&#xff08;Pod Manager&#xff09;是一个开源的容器管理工具&#xff0c;类似于 Docker&#xff0c;可以用于拉取、运行、管理容器镜像。Podman 采用 无守护进程****&#xff08;Daemonless&#xff09; 的架构&#xff0c;使…...

作业14 (2023-05-22_const修饰指针)

第1题/共5题【单选题】 C程序常见的错误分类不包含:( ) A.编译错误 B.链接错误 C.栈溢出 D.运行时错误 回答正确 答案解析: 栈溢出是运行时错误的一种,因此C程序不会将栈溢出错误单独列出来,栈溢出包含在运行时错误中。 因此:选择C 第2题/共5题【单选题】 以下关于…...

Qt 线程和 QObjects

线程和 QObjects QThread 继承于 QObject。 它发出信号来指示线程开始或结束执行&#xff0c;并提供一些插槽。 更有趣的是&#xff0c;QObjects 可以在多个线程中使用&#xff0c;发出信号以调用其他线程中的插槽&#xff0c;并向 "生活 "在其他线程中的对象发布事件…...

cocos creator 笔记-路边花草

版本&#xff1a;3.8.5 实现目标&#xff1a;给3d道路生成路边景观花草 在场景下创建一个节点&#xff0c;我这里种植两种花草模型&#xff0c;兰花和菊花&#xff0c;所以分别在节点下另创建两个节点&#xff0c;为了静态合批。 1.将花草模型分别拖入场景中&#xff0c;制作…...

基于SpringBoot+Vue3实现的宠物领养管理平台功能十六

一、前言介绍&#xff1a; 1.1 项目摘要 随着社会经济的发展和人们生活水平的提高&#xff0c;越来越多的人开始关注并参与到宠物领养中。宠物已经成为许多家庭的重要成员&#xff0c;人们对于宠物的关爱和照顾也日益增加。然而&#xff0c;传统的宠物领养流程存在诸多不便&a…...

MOSN(Modular Open Smart Network)-05-MOSN 平滑升级原理解析

前言 大家好&#xff0c;我是老马。 sofastack 其实出来很久了&#xff0c;第一次应该是在 2022 年左右开始关注&#xff0c;但是一直没有深入研究。 最近想学习一下 SOFA 对于生态的设计和思考。 sofaboot 系列 SOFAStack-00-sofa 技术栈概览 MOSN&#xff08;Modular O…...

数据仓库pinia中,getter和actions有什么区别

将计算逻辑放在 getters 还是 actions 里&#xff0c;取决于具体的使用场景和需求&#xff0c;下面详细分析放在 getters 中的优势以及和 actions 的区别&#xff0c;以说明是否有必要放在 getters 里&#xff1a; 1. getters 的优势 缓存特性 getters 具有类似 Vue 计算属性…...

RoMA: 基于Mamba的遥感基础模型, 已开源, 首次验证mamba的scaling能力

Time: 2025-03-27T15:27:00 github: 链接 HuggingFace: 链接 摘要 近年来&#xff0c;自监督学习在视觉 Transformer&#xff08;ViT&#xff09;方面的进展推动了遥感&#xff08;RS&#xff09;基础模型的突破。然而&#xff0c;自注意力机制的二次复杂度给可扩展性带来了…...

蓝桥杯(电子类)嵌入式第十一届设计与开发科目模拟试题

一、功能概览 二、分模块实现 1、按键 新建interrupt.h和interrupt.c写中断的代码&#xff08;写法学习来自定时器-按键单击_哔哩哔哩_bilibili&#xff09; #ifndef __INTERRUPT_H #define __INTERRUPT_H#include "main.h" #include "stdbool.h"struct…...

CMLINK APN 手动设置

以下是针对 CMLINK 的 APN设置 的详细指南&#xff0c;基于常见配置需求&#xff1a; CMLINK APN 手动设置参数 参数项值说明名称CMLINK (自定义)任意命名&#xff08;如 CMLINK、CM Internet 等&#xff09;&#xff0c;建议使用ASCII字符&#xff0c;无特殊符号。APNcm.com …...

排序--快排--非递归法

一&#xff0c;引言 快排不管是hoare法还是指针法以及挖坑法&#xff0c;最终都是利用函数递归进行实现的&#xff0c;但是只要是函数递归就会有栈溢出的风险&#xff0c;为此本篇文章讲解快排的非递归法。 二&#xff0c;代码逻辑 首先要了解为什么会使用递归进行调用&…...

02 相机标定相关坐标系

标定相关坐标系 一共四个坐标系 图像像素坐标系: u-v,图像左上角为原点图像物理坐标系: x-y,图像中心为原点...

数学建模:MATLAB卷积神经网络

一、简述 卷积神经网络是一种处理具有网格结构数据的深度学习模型&#xff0c;由输入层、卷积层、池化层、全连接层、输出层组成。 输出层&#xff1a;将图像转换为其对应的由像素值构成的二维矩阵&#xff0c;并存储二维矩阵 卷积层&#xff1a;提取图像的底层特征&#xf…...

Android读写权限分析

Android系统使用的是Linux内核&#xff0c;所以Android系统沿用了linux系统的那一套文件读写权限。 目录 1&#xff0c;权限解读1.1&#xff0c;权限分为三种类型&#xff1a;1.2&#xff0c;权限针对的三类对象&#xff1a;1.3&#xff0c;文件和目录的权限区别1.3.1&#xf…...

计算机网络基础:量子通信技术在网络中的应用前景

计算机网络基础:量子通信技术在网络中的应用前景 一、前言二、量子通信技术基础2.1 量子通信的基本概念2.2 量子通信的主要原理2.2.1 量子密钥分发(QKD)原理2.2.2 量子隐形传态原理三、量子通信技术的特点3.1 绝对安全性3.2 超高通信速率潜力3.3 抗干扰能力强四、量子通信技…...

【算法学习计划】贪心算法(上)

目录 前言&#xff08;什么是贪心&#xff09; leetcode 860.柠檬水找零 leetcode 2208.将数组和减半的最少操作次数 leetcode 179.最大数 leetcode 376.摆动序列 leetcode 300.最长递增子序列 leetcode 334.递增的三元子序列 leetcode 674.最长连续递增序列 leetcode …...

Linux 目录结构(文件系统结构)示例说明

在Linux操作系统中&#xff0c;文件系统的结构是理解系统性能及管理的重要基础。每个目录都有它的特定用途&#xff0c;这使得系统管理更加清晰和高效。本文将带您逐步了解每一个重要目录及其功能。 1. 根目录 / 根目录是Linux文件系统的起点&#xff0c;所有文件和目录均从此…...

Linux下的socket演示程序2

server.cpp #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h>#define SER_PORT 8888 //服务器端口号 #define SER_IP "10.148.4.168" //服…...

TiDB与Doris实操对比:深度剖析数据库选型要点

TiDB与Doris实操对比&#xff1a;深度剖析数据库选型要点 宝子们&#xff0c;在大数据处理的广阔天地里&#xff0c;TiDB和Doris都是备受瞩目的数据库解决方案。它们各自有着独特的优势和适用场景&#xff0c;对于我们开发者来说&#xff0c;深入了解它们的实操特性&#xff0…...