前言本文整理了 Java 基础核心高频知识点包括面向对象、数据类型、String、异常、反射注解等都是面试和日常开发最常用内容适合 Java 初学者和准备面试的同学复习使用。Java基础面向对象什么是面向对象要求有抽象的能力把实际开发中的各种业务抽象成具体的接口 抽象类 类面向对象的三大特征是什么继承问子类是否可以继承父类的private修饰的成员属性和方法///子类能不能继承父类的私有方法/私有属性答可以但是只能继承不能使用如果继承父类父类所有的一切包括私有但是调用不了拓展编码的设计原则里氏替换原则继承可以用但子类不能 “篡改” 父类的核心约定多态实现接口 继承抽象类可以使用父类去接受具体的子类实现 可以灵活的接受不同类型的实现类封装类的封装 方法的封装 模块的封装面向对象的封装指的是类的封装类的封装就是私有成员变量公开成员方法方法的封装指的是一个方法被多次调用可以抽取出来然后独立定义减少代码的重复度模块的封装如果一个功能被多个项目 被多个模块/微服务模块进行调用可以把这个功能进行抽取封装成一个独立的模块 然后在其他微服务/模块中进行依赖引入Java中重载Overload和重写Override的区别重载指的是相同的方法名称 相同的方法返回值 不同的参数重写子类抽象类 普通类 接口实现类重写父类的方法实现 方法名称返回值 形参都保持一致如果不一致就重载了抽象类和接口的区别抽象类如果一个类中至少包含一个abstract 修饰的方法那么这个类就是抽象类接口都是抽象方法默认情况区别抽象类abstract 抽象类是 单继承 其中有抽象方法/非抽象方法抽象类中可以有各种变量 抽象类中有构造方法接口interface接口时多实现 Jdk8 之前只能是抽象方法jdk8之后可以有默认方法和静态方法接口中只能是public static final 修饰的常量 接口中不能有构造方法Java8接口的默认方法和静态方法默认方法就是有方法体default void method A{方法体}静态方法static void method B{方法体}抽象方法void abstract C数据类型与包装类Java基本数据类型有哪些占多少字节基本数据类型字节取值范围Byte1-128~127Short2-32768 ~ 32767Int4-2³¹ ~ 2³¹-1Long8-2⁶³ ~ 2⁶³-1Float4约 ±3.40282347E38有效小数位 6~7 位Double8约 ±1.79769313486231570E308有效小数位 15~16 位Char20 ~ 65535即 \u0000 ~ \uffffBoolean不确定true / false自动装箱和拆箱的原理integer i10//装箱封装成一个包装类底层用的是Integer.valueOf(10);Int j i ; //拆箱底层是i.intValue();注意事项频繁装箱和拆箱会影响性能如果使用的是包装类可以为 null 使用时 注意空指针异常 NullPointerException简称 NPE。Integer缓存机制-128到127Integer a 127; Integer b 127; sout(a b); //true ; Integer c 128; Integer d 128; sout(c d); //false ;Integer的valueOfint i在这个方法中会进行判断i的值 如果是在-128到127之间 Integer会进行缓存IntegerCache .cache();其他包装类缓存Byte Short Long (缓存都是)-128到127Character:0到127Boolean:true和false两个对象面试问你在开发中有没有遇到过一些印象比较深刻的Bug,你是怎么解决的我之前在开发的时候 有一个用户发放优惠券的业务当时的业务要求每个用户只能领取一张优惠券所以我使用了锁机制但是我没有对整个优惠券的表进行加锁这样的并发太低了我当时使用的是用户id进行加锁也就是同一时间一个用户只能抢一张优惠券 不同的用户可以同时抢并发会更高但是还是出现了一个用户抢多张的情况当时我们的用户id是Long类型的 这时候我的用户id的值超过了128那么Long缓存失效然后同一个用户的id会被判断为不同的锁对象导致锁失效 与equals的区别 比较的是什么基本数据类型比较的是值是否相等引用类型比较的是内存地址是否相同是否是同一个对象equals比较的是什么Object类中默认的实现是String Integer等重写equals()比较的是内容是否相等String相关String、StringBuilder、StringBuffer的区别String是不可变的线程是安全的性能低会频繁创建新对象少量字符串操作的时候StringBuilder是可以变的线程是不安全的性能高单线程大量字符串操作局部StringBuffer是可以变的线程是安全的性能较高有锁开销多线程大量字符串操作成员String为什么设计成不可变的安全性字符串常量池的需要相同内容的字符串共享同一个对象防止被篡改String常用于网络传输 文件路径等以一些操作 通过不可变来保证安全性线程安全不可变对象天然就是线程安全的 多环境下无需考虑线程安全问题支持哈希String经常会作为HashMap的Key使用 不可变保证了Hash值不变性能优化字符串常量池可以复用对象 节省内存为什么是不可变的/怎么保证不可变String类是被final修饰的 也就是不可以被继承 也就意味着不可以重写父类方法字符数组也是final修饰的 不能修改引用String类本身并没有提供修改value的方法String字符串常量池的理解字符串常量池是JVM为了提升性能和减少内存开销专门为String类设计的一块内存区域存储的位置JDK7之前是方法区JDK7之后是堆内存面试题String s new String (hello);创建了几个对象如果“hello”在常量池中没有2个常量池中1个堆内存里面1个如果“hello”在常量池中没有1个堆内存里面1个intern方法的作用intern方法用于将字符串对象放入到字符串常量池中原理如果常量池中已存在该字符串返回池中的引用如果常量池中的不存在将该字符串放入到常量池中然后再返回引用异常处理Java异常体系结构ThrowableErrorOOMStackOverflowError栈溢出ExceptionRuntimeExceptionNPE 空指针异常数组角标越界类型转换异常编译异常IOExceptionSQLExceptionChecked异常和Unchecked异常的区别(运行时异常和编译异常的区别)编译异常在编译时期就必须要处理的异常try-catch和throw运行时异常编译时期不强制处理自己可能意识不到有异常如果是web项目 通常使用全局异常处理器去拦截这些运行时异常然后统一处理异常表是什么定义异常表是存储在Java字节码中的一个数据结构它存在于方法的Code属性中用于指导JVM如何处理方法执行过程中可能发生的异常然后统一处理。异常表是在方法级别创建的而不是类级别或项目级别。只有包含try-catch块的方法才会有异常表。每个包含异常处理逻辑的方法都会有自己的异常表。异常表是在编译时由Java编译器生成的作为字节码的一部分。它不是在运行时动态创建的。在Java的.class文件中异常表是方法属性的一部分。一个类可能包含多个方法每个方法可能由也可能没有异常表。一个方法中如果有多个try-catch块也只会存在一个异常表这个异常表中会有多个条目具体来说每个catch块都会对应一个条目如果代码在运行时发生异常但是方法中没有try-catch块也不会自动创建异常表每个方法的异常表是相互独立的。一个方法的异常处理不会影响其他方法的异常表。public void methodWithMultipleTryCatch(); Code: //...bytecode... //一个方法中的异常表 //一个try对应两个catch的情况每个catch对应一个条目 Exception Table: from to target type 0 8 11 Class java/lang/ArithmeticException 14 22 25 Class java/lang/NullPointerException 14 22 38 Class java/lang/Exception //方法中没有try-catch也就没有异常表 public void methodWithoutTryCatch(); Code: //...bytecode... //No exception table for this method结构异常表的每个条目通常包含以下信息fromtry块开始的字节码偏移量totry块结束的字节码偏移量target异常处理程序catch块的起始位置type要捕获的异常类型作用当方法执行过程中抛出异常时JVM会查询异常表JVM根据异常表的信息确定是否有匹配的catch块以及如何处理异常。工作原理当异常发生时JVM检查当前指令的位置是否在任何try块的范围内。如果在try块内JVM会查找匹配的异常类型。如果找到匹配执行会跳转到相应的catch块。优点效率异常表提供了一种高效的方式来定位异常处理程序。灵活性允许对不同类型的异常进行不同的处理。查看异常表可以使用javap工具查看编译后类的字节码包括异常表。命令javap -c -verbose ClassName与finally块的关系finally块的内容通常会被复制到每个可能的执行路径中包括正常执行路径和异常处理路径。性能考虑异常表的存在不会影响正常执行的性能。只有在实际抛出异常时才会查询异常表。嵌套try-catch对于嵌套的try-catch块会生成多个异常表条目。try-catch-finally的执行顺序执行try如果有异常执行对应的catch块无论是否有异常都会执行finally面试题try{ return 1; }catch(Exception e){ return 2; }finally{ return 3; } //最终返回3 public static int test(){ int x 1; try{ x ; return x; //返回2 先把整个2保存起来 }finally{ x ; //x 3; } } //最终返回2finally块一定会执行吗通常情况下都会执行不会执行断电JVM退出System.exit(0);public static int test(){ int x 1; try{ System.exit(0); //退出虚拟机不会执行finally x ; return x; //返回2 先把整个2保存起来 }finally{ x ; //x 3; } }finally块在守护线程中 主线程结束掉了在try方法块中如果有无限循环或者死锁finally也不会被执行到线程被外界直接杀死try-with-resources的使用try(FileInputStream fis new FileInputStream(file.txt)){ //使用fis }catch(IOException e){ e.printStackTrace(); } //自动调用close资源类必须要实现AutoCloseable接口可以在Try里面同时管理多个资源反射与注解什么是反射反射的应用场景反射就是在运行过程中能够动态拿到一个类的所有信息属性、方法、构造器甚至能够修改私有属性的值。核心类Class Field Method Constructor应用场景Spring容器 反射创建BeanAOP的实现 反射执行目标方法运行时注解的解析 发射拿注解上的值驱动加载反射获取Class对象的三种方式//方式1通过类名.class //需要导入这个类 或者是你自己创建类 ClassString clazz1 String.class; //方式2通过对象.getClass() //需要创建这个类的实例对象 String str hello; Class? clazz2 str.getClass(); //方式3通过Class.forName(权限定类名); //运行时加载 最灵活 通常框架都是使用这种方式 Class? clazz3 Class.forName(java.lang.String); //三种方式获取的是同一个Class对象 System.out.println(clazz1 clazz2);//true System.out.println(clazz2 clazz3);//true反射的优缺点优点灵活性运行时动态操作类不需要在编译时确定 判断方法的名称是否是我想要的 以XXX开头解耦降低模块间的耦合度可扩展性支持插件式开发缺点性能开销比直接调用慢10-20倍安全性可以访问私有成员破环封装代码可读性差难以理解和维护编译时无法检查类型安全问题延迟到运行时优化建议缓存Class、Method、Field对象使用setAccessible(true) 减少安全检查开销非必要不使用反射注解的作用和自定义注解注解其实就是一个标记没有任何的业务逻辑作用就是方便有一个核心类然后去扫描带有特定标记的类或方法 然后做业务处理怎么自定义注解Interface可以定义属性每个属性都可以有默认值 也可以没有默认值如果某个属性有默认值在使用这个注解的时候就可以不用再指定值如果某个属性没有默认值 则在使用这个注解的时候就必须要指定属性的值 否则报错元注解有哪些元注解就是修饰注解的注解。Target约束注解能写在哪类上、方法上、字段上。Target({ElementType.TYPE,ElementType.METHOD}) public interface MyAnnotation{}Retention约束注解活到什么时候。注解默认的生命周期市编译后就不在了SOURCE(源码可见编译丢弃)。CLASS(字节码可见运行丢弃)。RUNTIME(运行期可见反射必须用这个)Retention(RetentionPolicy.RUNTIME) public interface MyAnnotation{}Documented注解是否包含在JavaDoc中Inherited注解是否可被继承总结本文整理了 Java 基础高频面试点适合日常复习和面试突击。基础扎实才能更好学框架、分布式、高并发建议多敲代码、多总结。后续会继续更新集合、多线程、JVM、Spring、MySQL 等系列文章欢迎关注交流。
Java 基础核心知识点总结(面试必备)
前言本文整理了 Java 基础核心高频知识点包括面向对象、数据类型、String、异常、反射注解等都是面试和日常开发最常用内容适合 Java 初学者和准备面试的同学复习使用。Java基础面向对象什么是面向对象要求有抽象的能力把实际开发中的各种业务抽象成具体的接口 抽象类 类面向对象的三大特征是什么继承问子类是否可以继承父类的private修饰的成员属性和方法///子类能不能继承父类的私有方法/私有属性答可以但是只能继承不能使用如果继承父类父类所有的一切包括私有但是调用不了拓展编码的设计原则里氏替换原则继承可以用但子类不能 “篡改” 父类的核心约定多态实现接口 继承抽象类可以使用父类去接受具体的子类实现 可以灵活的接受不同类型的实现类封装类的封装 方法的封装 模块的封装面向对象的封装指的是类的封装类的封装就是私有成员变量公开成员方法方法的封装指的是一个方法被多次调用可以抽取出来然后独立定义减少代码的重复度模块的封装如果一个功能被多个项目 被多个模块/微服务模块进行调用可以把这个功能进行抽取封装成一个独立的模块 然后在其他微服务/模块中进行依赖引入Java中重载Overload和重写Override的区别重载指的是相同的方法名称 相同的方法返回值 不同的参数重写子类抽象类 普通类 接口实现类重写父类的方法实现 方法名称返回值 形参都保持一致如果不一致就重载了抽象类和接口的区别抽象类如果一个类中至少包含一个abstract 修饰的方法那么这个类就是抽象类接口都是抽象方法默认情况区别抽象类abstract 抽象类是 单继承 其中有抽象方法/非抽象方法抽象类中可以有各种变量 抽象类中有构造方法接口interface接口时多实现 Jdk8 之前只能是抽象方法jdk8之后可以有默认方法和静态方法接口中只能是public static final 修饰的常量 接口中不能有构造方法Java8接口的默认方法和静态方法默认方法就是有方法体default void method A{方法体}静态方法static void method B{方法体}抽象方法void abstract C数据类型与包装类Java基本数据类型有哪些占多少字节基本数据类型字节取值范围Byte1-128~127Short2-32768 ~ 32767Int4-2³¹ ~ 2³¹-1Long8-2⁶³ ~ 2⁶³-1Float4约 ±3.40282347E38有效小数位 6~7 位Double8约 ±1.79769313486231570E308有效小数位 15~16 位Char20 ~ 65535即 \u0000 ~ \uffffBoolean不确定true / false自动装箱和拆箱的原理integer i10//装箱封装成一个包装类底层用的是Integer.valueOf(10);Int j i ; //拆箱底层是i.intValue();注意事项频繁装箱和拆箱会影响性能如果使用的是包装类可以为 null 使用时 注意空指针异常 NullPointerException简称 NPE。Integer缓存机制-128到127Integer a 127; Integer b 127; sout(a b); //true ; Integer c 128; Integer d 128; sout(c d); //false ;Integer的valueOfint i在这个方法中会进行判断i的值 如果是在-128到127之间 Integer会进行缓存IntegerCache .cache();其他包装类缓存Byte Short Long (缓存都是)-128到127Character:0到127Boolean:true和false两个对象面试问你在开发中有没有遇到过一些印象比较深刻的Bug,你是怎么解决的我之前在开发的时候 有一个用户发放优惠券的业务当时的业务要求每个用户只能领取一张优惠券所以我使用了锁机制但是我没有对整个优惠券的表进行加锁这样的并发太低了我当时使用的是用户id进行加锁也就是同一时间一个用户只能抢一张优惠券 不同的用户可以同时抢并发会更高但是还是出现了一个用户抢多张的情况当时我们的用户id是Long类型的 这时候我的用户id的值超过了128那么Long缓存失效然后同一个用户的id会被判断为不同的锁对象导致锁失效 与equals的区别 比较的是什么基本数据类型比较的是值是否相等引用类型比较的是内存地址是否相同是否是同一个对象equals比较的是什么Object类中默认的实现是String Integer等重写equals()比较的是内容是否相等String相关String、StringBuilder、StringBuffer的区别String是不可变的线程是安全的性能低会频繁创建新对象少量字符串操作的时候StringBuilder是可以变的线程是不安全的性能高单线程大量字符串操作局部StringBuffer是可以变的线程是安全的性能较高有锁开销多线程大量字符串操作成员String为什么设计成不可变的安全性字符串常量池的需要相同内容的字符串共享同一个对象防止被篡改String常用于网络传输 文件路径等以一些操作 通过不可变来保证安全性线程安全不可变对象天然就是线程安全的 多环境下无需考虑线程安全问题支持哈希String经常会作为HashMap的Key使用 不可变保证了Hash值不变性能优化字符串常量池可以复用对象 节省内存为什么是不可变的/怎么保证不可变String类是被final修饰的 也就是不可以被继承 也就意味着不可以重写父类方法字符数组也是final修饰的 不能修改引用String类本身并没有提供修改value的方法String字符串常量池的理解字符串常量池是JVM为了提升性能和减少内存开销专门为String类设计的一块内存区域存储的位置JDK7之前是方法区JDK7之后是堆内存面试题String s new String (hello);创建了几个对象如果“hello”在常量池中没有2个常量池中1个堆内存里面1个如果“hello”在常量池中没有1个堆内存里面1个intern方法的作用intern方法用于将字符串对象放入到字符串常量池中原理如果常量池中已存在该字符串返回池中的引用如果常量池中的不存在将该字符串放入到常量池中然后再返回引用异常处理Java异常体系结构ThrowableErrorOOMStackOverflowError栈溢出ExceptionRuntimeExceptionNPE 空指针异常数组角标越界类型转换异常编译异常IOExceptionSQLExceptionChecked异常和Unchecked异常的区别(运行时异常和编译异常的区别)编译异常在编译时期就必须要处理的异常try-catch和throw运行时异常编译时期不强制处理自己可能意识不到有异常如果是web项目 通常使用全局异常处理器去拦截这些运行时异常然后统一处理异常表是什么定义异常表是存储在Java字节码中的一个数据结构它存在于方法的Code属性中用于指导JVM如何处理方法执行过程中可能发生的异常然后统一处理。异常表是在方法级别创建的而不是类级别或项目级别。只有包含try-catch块的方法才会有异常表。每个包含异常处理逻辑的方法都会有自己的异常表。异常表是在编译时由Java编译器生成的作为字节码的一部分。它不是在运行时动态创建的。在Java的.class文件中异常表是方法属性的一部分。一个类可能包含多个方法每个方法可能由也可能没有异常表。一个方法中如果有多个try-catch块也只会存在一个异常表这个异常表中会有多个条目具体来说每个catch块都会对应一个条目如果代码在运行时发生异常但是方法中没有try-catch块也不会自动创建异常表每个方法的异常表是相互独立的。一个方法的异常处理不会影响其他方法的异常表。public void methodWithMultipleTryCatch(); Code: //...bytecode... //一个方法中的异常表 //一个try对应两个catch的情况每个catch对应一个条目 Exception Table: from to target type 0 8 11 Class java/lang/ArithmeticException 14 22 25 Class java/lang/NullPointerException 14 22 38 Class java/lang/Exception //方法中没有try-catch也就没有异常表 public void methodWithoutTryCatch(); Code: //...bytecode... //No exception table for this method结构异常表的每个条目通常包含以下信息fromtry块开始的字节码偏移量totry块结束的字节码偏移量target异常处理程序catch块的起始位置type要捕获的异常类型作用当方法执行过程中抛出异常时JVM会查询异常表JVM根据异常表的信息确定是否有匹配的catch块以及如何处理异常。工作原理当异常发生时JVM检查当前指令的位置是否在任何try块的范围内。如果在try块内JVM会查找匹配的异常类型。如果找到匹配执行会跳转到相应的catch块。优点效率异常表提供了一种高效的方式来定位异常处理程序。灵活性允许对不同类型的异常进行不同的处理。查看异常表可以使用javap工具查看编译后类的字节码包括异常表。命令javap -c -verbose ClassName与finally块的关系finally块的内容通常会被复制到每个可能的执行路径中包括正常执行路径和异常处理路径。性能考虑异常表的存在不会影响正常执行的性能。只有在实际抛出异常时才会查询异常表。嵌套try-catch对于嵌套的try-catch块会生成多个异常表条目。try-catch-finally的执行顺序执行try如果有异常执行对应的catch块无论是否有异常都会执行finally面试题try{ return 1; }catch(Exception e){ return 2; }finally{ return 3; } //最终返回3 public static int test(){ int x 1; try{ x ; return x; //返回2 先把整个2保存起来 }finally{ x ; //x 3; } } //最终返回2finally块一定会执行吗通常情况下都会执行不会执行断电JVM退出System.exit(0);public static int test(){ int x 1; try{ System.exit(0); //退出虚拟机不会执行finally x ; return x; //返回2 先把整个2保存起来 }finally{ x ; //x 3; } }finally块在守护线程中 主线程结束掉了在try方法块中如果有无限循环或者死锁finally也不会被执行到线程被外界直接杀死try-with-resources的使用try(FileInputStream fis new FileInputStream(file.txt)){ //使用fis }catch(IOException e){ e.printStackTrace(); } //自动调用close资源类必须要实现AutoCloseable接口可以在Try里面同时管理多个资源反射与注解什么是反射反射的应用场景反射就是在运行过程中能够动态拿到一个类的所有信息属性、方法、构造器甚至能够修改私有属性的值。核心类Class Field Method Constructor应用场景Spring容器 反射创建BeanAOP的实现 反射执行目标方法运行时注解的解析 发射拿注解上的值驱动加载反射获取Class对象的三种方式//方式1通过类名.class //需要导入这个类 或者是你自己创建类 ClassString clazz1 String.class; //方式2通过对象.getClass() //需要创建这个类的实例对象 String str hello; Class? clazz2 str.getClass(); //方式3通过Class.forName(权限定类名); //运行时加载 最灵活 通常框架都是使用这种方式 Class? clazz3 Class.forName(java.lang.String); //三种方式获取的是同一个Class对象 System.out.println(clazz1 clazz2);//true System.out.println(clazz2 clazz3);//true反射的优缺点优点灵活性运行时动态操作类不需要在编译时确定 判断方法的名称是否是我想要的 以XXX开头解耦降低模块间的耦合度可扩展性支持插件式开发缺点性能开销比直接调用慢10-20倍安全性可以访问私有成员破环封装代码可读性差难以理解和维护编译时无法检查类型安全问题延迟到运行时优化建议缓存Class、Method、Field对象使用setAccessible(true) 减少安全检查开销非必要不使用反射注解的作用和自定义注解注解其实就是一个标记没有任何的业务逻辑作用就是方便有一个核心类然后去扫描带有特定标记的类或方法 然后做业务处理怎么自定义注解Interface可以定义属性每个属性都可以有默认值 也可以没有默认值如果某个属性有默认值在使用这个注解的时候就可以不用再指定值如果某个属性没有默认值 则在使用这个注解的时候就必须要指定属性的值 否则报错元注解有哪些元注解就是修饰注解的注解。Target约束注解能写在哪类上、方法上、字段上。Target({ElementType.TYPE,ElementType.METHOD}) public interface MyAnnotation{}Retention约束注解活到什么时候。注解默认的生命周期市编译后就不在了SOURCE(源码可见编译丢弃)。CLASS(字节码可见运行丢弃)。RUNTIME(运行期可见反射必须用这个)Retention(RetentionPolicy.RUNTIME) public interface MyAnnotation{}Documented注解是否包含在JavaDoc中Inherited注解是否可被继承总结本文整理了 Java 基础高频面试点适合日常复习和面试突击。基础扎实才能更好学框架、分布式、高并发建议多敲代码、多总结。后续会继续更新集合、多线程、JVM、Spring、MySQL 等系列文章欢迎关注交流。