☰
JavaSE知识点总结
2026/9/27 6:54:09 网站建设 项目流程

文章目录

        • 1、intern()方法
        • 2、try...catch...finally
        • 3、hashCode和equals的关系
        • 4、什么是反射,反射有什么缺点?
        • 5、BIO(同步阻塞)、NIO(同步非阻塞)、AIO(异步非阻塞)的区别
        • 6、**面向对象的理解?**
        • 7、什么是抽象类?
        • 8、什么是接口?
        • 9、抽象类和接口的区别?
        • 10、什么是泛型?
        • 11、异常
        • 12、注解
        • 13、反射
        • 14、static和final的区别?以及分别存储在JVM的哪个区域?
        • 15、Linux的五种IO模型
        • 16、Reactor线程模型详解
        • 17、IO零拷贝
1、intern()方法

“ab”.intern():这个方法会首先检查字符串常量池中是否有”ab”这个字符串,如果存在则返回这个字符串常量池中的引用,否则就将这个字符串在堆中的引用添加到字符串常量池中,然后返回这个常量常量池中字符串的引用。以下代码是在jdk1.8中测试,jdk1.6会有所不同。

publicstaticvoidmain(String[]args){// 创建2个对象,一个String对象在堆中,一个String常量在常量池Strings=newString("2");// 判断s是否在常量池中,存在则返回常量池中对象的引用,此时intern指向常量池中的对象Stringintern=s.intern();// s2字符串在常量池中,所以返回常量池中的对象引用Strings2="2";// s:为堆中对象 s2:为常量池对象 所以:falseSystem.out.println(s==s2);// false// intern和s2都是指向常量池中的字符串,所以:trueSystem.out.println(intern==s2);// trueSystem.out.println(s==intern);//falseSystem.out.println("------------------------");// 创建4个对象:堆中"33","3","3"对象,常量池:"3"对象Strings3=newString("3")+newString("3");// 判断s3是否在常量池中,不存在则将s3加入常量池中,并且常量池中保存的是s3的引用,返回常量池中对象的引用,此时s3和intern2指向同一个对象Stringintern2=s3.intern();// s4字符串在常量池中,所以返回常量池中的对象引用Strings4="33";// s3和intern2和s4指向的是同一个对象System.out.println(s3==s4);// trueSystem.out.println(intern2==s3);// trueSystem.out.println(intern2==s4);// trueSystem.out.println("------------------------");// 创建4个对象:堆中"33","3","3"对象,常量池:"3"对象Strings5=newString("3")+newString("3");// s6字符串不在常量池中,将字符串放入字符串常量池中,此时与堆中的引用不同Strings6="33";// 判断s5是否在常量池中,存在Stringintern3=s5.intern();System.out.println(s5==s6);// falseSystem.out.println(s6==intern3);// trueSystem.out.println(s5==intern3);//false}
2、try…catch…finally

return 先把【要返回的值】保存起来;然后执行 finally;finally 里如果重新 return,会覆盖返回值;finally 仅修改变量不 return,不会改变已经保存好的返回值。

// 返回 40publicstaticintfun(){inta=10;try{System.out.println(a/0);a=20;// return a;}catch(Exceptione){a=30;returna;}finally{a=40;returna;}}
// 返回 30publicstaticintfun(){inta=10;try{System.out.println(a/0);a=20;// return a;}catch(Exceptione){a=30;returna;}finally{a=40;}returna;}
// 返回 30publicstaticintfun(){inta=10;try{System.out.println(a/0);a=20;returna;}catch(Exceptione){a=30;returna;}finally{a=40;}}
3、hashCode和equals的关系

约定:

  1. 如果equals(a,b) == true,那么a.hashCode()必须等于b.hashCode()
  2. 如果a.hashCode() == b.hashCode(),不代表equals(a,b)==true(哈希碰撞)
  3. 如果equals重写了,一定要重写 hashCode,否则破坏约定!

使用Object.hashCode,是根据随机算法生成的hashCode值(hash碰撞),无法保证两个对象equals相等的时候,hashCode也相等。

重写equals时,必须要重写hashCode原因:像一些集合容器map,在进行比较两个对象相等的判定条件是hashcode和equals都相等,所有在重写equals时,必须要重写hashCode,才能保证集合容器的正确使用。

Object 默认 hashCode ():native 方法,生成 identity hash code,存在对象头 mark word,不是内存地址;
Object默认equals():默认==,比较对象地址;

4、什么是反射,反射有什么缺点?

反射是指在程序运行时动态获取类的信息、调用类的方法、访问类的属性等操作能力。在Java中,反射允许程序在运行时检查和操作类、方法、字段等,使得程序可以在运行时动态地创建对象、调用方法、修改属性等。

优点:运行时动态操作类,解耦,实现通用框架,可以访问私有成员
缺点:性能低,破坏封装,编译不校验,问题运行才暴露;

setAccessible(true)是修改访问权限吗?
答案:不是修改源码的 private 修饰符,只是关闭 JDK 的访问权限检查。

5、BIO(同步阻塞)、NIO(同步非阻塞)、AIO(异步非阻塞)的区别
  • 同步:应用线程主动发起 IO 拷贝,将内核数据拷贝到应用内存中(read/write)
  • 异步:内核读完数据从内核到应用内存,才主动回调通知应用
  • 阻塞:调用IO等API时没有数据,线程挂起
  • 非阻塞:没有数据直接返回,不卡线程
    同步异步关键:IO 数据拷贝是谁来做;阻塞非阻塞:调用 API 无数据会不会卡住线程。

BIO 是同步阻塞 IO,一连接一线程。来一个客户端就新建一个线程,线程阻塞在 read,连接多线程爆炸,适合连接数少场景。
NIO 是同步非阻塞 IO,基于多路复用(Linux 底层 epoll)。少量线程监听大量连接,Selector 监听 fd 就绪事件;内核通知就绪后,应用线程自己调用 read 拷贝数据,Netty 底层就是 NIO,适合高并发长连接。
AIO 是异步非阻塞 IO。应用发起读请求直接返回,内核把数据全部拷贝到用户缓冲区后回调通知程序;Linux 原生 AIO 有缺陷,Java 很少落地。

6、面向对象的理解?

面向对象(OOP)是一种编程思想,把程序看作多个对象的交互,面向对象的核心是将现实世界的实体抽象为代码中的’对象’,每个对象包含数据(属性)和操作数据的方法,形成高内聚低耦合的模块。这样设计更符合人类思维方式,让程序结构更清晰。它有四大特性:

  • 封装:将数据和方法封装在类内部,隐藏内部细节,只暴露必要接口,提高安全性和维护性,降低耦合。
  • 继承:子类复用父类代码,建立类之间的层次关系。extends关键字,Java只有单继承,接口可以多实现。
  • 多态:同一接口(行为),不同对象有不同实现,提高代码灵活性、拓展性。extends/implement 都是实现方式。编译时多态:方法重载,运行时多态:方法重写。
  • 抽象:抽取通用规范,只定义方法签名,让子类实现。抽象类(abstract class)、接口(interface)。

面向过程关注怎么做(步骤);面向对象关注谁来做(对象)。

在过往的项目中,面向对象的思想和特性帮助我们:快速响应需求变更、降低代码维护成本、提高代码质量。但我们也要平衡面向对象与其他范式(函数式编程)的优势,防止过度设计,增加系统的复杂度。

7、什么是抽象类?

抽象类是用来捕捉子类通用特性的类,它不能被实例化,只能作为其他类的父类。

抽象类特点:

  • 用abstract关键字声明
  • 可以包含抽象方法和具体方法
  • 可以有构造方法、成员变量
  • 子类继承使用extends
  • 一个类只能继承一个抽象类(单继承)
8、什么是接口?

接口是行为的抽象,定义了一组方法规范,实现类必须遵守这些规范。

接口特点:

  • 用interface关键字声明
  • Java 8之前:只能有抽象方法和常量
  • Java 8+:可以有默认方法、静态方法
  • Java 9+:可以有私有方法
  • 实现类使用implements
  • 一个类可以实现多个接口
9、抽象类和接口的区别?
  1. 设计理念不同:抽象类是’is-a’关系(继承),接口是’has-a’关系(组合)
  2. 单继承 vs 多实现:Java中类只能继承一个父类,但可实现多个接口
  3. 抽象类可以有构造方法和具体实现,早期接口只能有抽象方法
  4. 成员变量方面,抽象类可以是普通变量,接口只能是常量
10、什么是泛型?

Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。

泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。

好处:1.可以将运行期的异常提前到编译期;2.消除强制类型转换;3.提高了类型安全

泛型的三种方式:泛型类,泛型接口,泛型方法

11、异常

Java中所有异常和错误的根类是Throwable,它有两个直接子类:Error和Exception(受检异常 or 非受检异常)。

  1. 定义:异常是程序运行过程中发生的不正常事件,会打断正常的指令流。
  2. 分类:分为受检异常和非受检异常(错误和运行时异常)。
  3. 异常处理机制:try-catch-finally,throw和throws。
  4. 自定义异常:可以通过继承Exception或RuntimeException来创建自定义异常。
  5. 最佳实践:例如,不要吞掉异常,不要使用异常控制流程,使用具体的异常类型等。
  • 常见运行时异常:

    1. NullPointerException
      空指针异常,JAVA8中可用Optional来避免,一般是代码中出现了空对象时,抛出该异常

    2. IndexOutOfBoundsException
      数组下标越界异常,当使用的数组下标超出数组允许范围时,抛出该异常

    3. ClassCastException
      类型转换异常,当试图将对象强制转换为不是实例的子类时,抛出该异常

    4. NumberFormatException
      数字格式化异常,当试图将一个String转换为指定的数字类型,而该字符串确不满足数字类型要求的格式时,抛出该异常

    5. JSONException
      JSON异常,进行JSON格式化操作时出现异常,会抛出该异常

    6. ArithmeticException

      算术异常

  • 常见检查性异常:

    1. SQLException
      SQL异常
    2. IOException
      IO异常,在对流操作时有可能会出现的异常
    3. FileNotFoundException
      找不到某个文件时,会抛出该异常
    4. ClassNotFoundException
      找不到某个类时,会抛出该异常
    5. InterruptedException
      中断异常
12、注解

Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。继承自java.lang.annotation.Annotation。注解本身不影响代码逻辑,但可以通过反射获取注解信息。

packagejava.lang.annotation;publicinterfaceAnnotation{booleanequals(Objectobj);inthashCode();StringtoString();Class<?extendsAnnotation>annotationType();}

内置注解:

  • @Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
  • @Deprecated - 标记过时方法。如果使用该方法,会报编译警告。
  • @SuppressWarnings - 指示编译器去忽略注解中声明的警告。
  • @SafeVarargs - Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。
  • @FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口。
  • @Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次。

自定义注解:

@Documented@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public@interfaceMyAnnotation1{}

元注解:
元注解的作用就是负责注解其他注解,Java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotion类型作说明。

  • @Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
  • @Documented - 标记这些注解是否包含在用户文档中。
  • @Target - 标记这个注解应该是哪种 Java 成员。
  • @Inherited - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)

@Retention 的取值:

publicenumRetentionPolicy{SOURCE,/* Annotation信息仅存在于编译器处理期间,编译器处理完之后就没有该Annotation信息了 */CLASS,/* 编译器将Annotation存储于类对应的.class文件中。默认行为 */RUNTIME/* 编译器将Annotation存储于class文件中,并且可由JVM读入 */}

@Target的取值:

publicenumElementType{TYPE,/* 类、接口(包括注释类型)或枚举声明 */FIELD,/* 字段声明(包括枚举常量) */METHOD,/* 方法声明 */PARAMETER,/* 参数声明 */CONSTRUCTOR,/* 构造方法声明 */LOCAL_VARIABLE,/* 局部变量声明 */ANNOTATION_TYPE,/* 注释类型声明 */PACKAGE/* 包声明 */}

注解的主要价值:

  • 编译检查:如@Override确保正确重写方法
  • 框架配置:如Spring的@Autowired、@Service简化配置
  • 代码生成:如Lombok的@Data自动生成代码
  • 测试标记:如JUnit的@Test
13、反射

反射就是在运行状态能够动态的获取该类的属性和方法,并且能够任意的使用该类的属性和方法,这种动态获取类信息以及动态的调用对象的方法的功能就是反射。它让Java在运行时具有像动态语言一样的特性。

核心功能包括:

  • 动态获取类信息(Class对象)
  • 创建对象(newInstance)
  • 调用方法(invoke)
  • 访问/修改字段(get/set)
  • 处理注解和泛型

关键类:

  • Class:类的元数据入口
  • Field:字段信息
  • Method:方法信息
  • Constructor:构造方法
  • Modifier:修饰符信息

实际应用场景:

  • 框架开发:Spring通过反射实现依赖注入
  • 动态代理:AOP切面编程
  • 序列化工具:Jackson/GSON处理JSON
  • 测试框架:JUnit发现并运行测试方法
  • 插件系统:动态加载和扩展功能

优点:

  • 灵活性高,实现动态编程
  • 框架开发的基础设施
  • 支持运行时类型检查

缺点:

  • 性能开销:反射操作比直接调用慢
  • 安全问题:可以绕过访问控制
  • 代码复杂:降低可读性和维护性
  • 编译检查缺失:错误在运行时才发现

性能优化:

  • 缓存反射对象
  • 使用setAccessible(true)减少检查
  • 避免在热点代码中使用反射

获取class对象三种方式:

  1. 类名.class如:Person.class 该方式安全可靠,程序性能最高
  2. 对象.getClass()如:person.getClass()
  3. Class.forName(全类名)如:Class.forName(“ldc.org. demo.person”)

总结:

反射是Java在运行时动态获取和操作类信息的能力。通过Class对象可以获取字段、方法、构造器等信息,并能创建对象、调用方法、访问字段。它广泛应用于框架开发(如Spring)、动态代理、序列化等场景。优点是灵活性高,缺点是性能差、安全性低。实际使用中需要注意性能优化和安全控制。

14、static和final的区别?以及分别存储在JVM的哪个区域?
维度staticfinal
语义类级成员,与对象无关值/引用只能赋一次
内存份数整个 JVM 只有一份与普通字段份数相同
生命周期类加载即分配,卸载才回收一旦赋值就冻结
可变性可反复修改不可再改(基本类型值不变,引用类型地址不变)
能否叠加✅ 可单独用✅ 可单独用
叠加后类级常量(编译期或运行期确定)仍是“只能一次”语义
类型static存储位置实例 final存储位置static final存储位置(优化后,值直接内联到使用处,引用存在堆(Class对象中))局部变量
基本类型变量堆(Class对象中)堆对象中元空间(运行时常量池)栈
字符串变量堆(Class对象中的引用) + 堆(字符串常量池)堆对象的引用 --> 堆(字符串常量池)元空间(运行时常量池)–> 堆(字符串常量池)栈引用–> 堆(字符串常量池)
对象引用堆(Class对象中的引用) + 堆对象堆对象的引用 + 堆对象元空间(运行时常量池)–> 堆对象栈引用 --> 堆对象
方法元空间元空间
类元空间元空间
代码块元空间–
15、Linux的五种IO模型

https://blog.csdn.net/Linging_24/article/details/134984317?spm=1001.2014.3001.5501

16、Reactor线程模型详解

https://blog.csdn.net/Linging_24/article/details/134984818?spm=1001.2014.3001.5501

17、IO零拷贝

https://blog.csdn.net/Linging_24/article/details/134984466?spm=1001.2014.3001.5501

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询