尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Java基础面试高频考点全解析:从集合原理到实战避坑

Java基础面试高频考点全解析:从集合原理到实战避坑 做Java开发这些年我既面试过别人也被别人面试过。聊到Java基础的时候我见过太多候选人一听到“八股文”三个字就头疼然后开始死记硬背结果面试官多追问一句“为什么”立刻就卡壳。其实换个角度想面试官问基础问题不是为了刁难你而是想通过这些问题判断你对这门语言的理解深度、代码品味和思维方式。这篇文章就按面试官视角把Java基础篇的高频考点一条条拆开。内容覆盖面向对象、数据类型、String、集合框架、异常、泛型反射和Java 8新特性每个考点我会告诉你面试官到底想听什么、怎么答才能拿高分、哪些坑是你必须避开的。适合正在准备校招或社招的朋友也适合学完Java基础想系统自查的同学。文章不追求面面俱到但凡是写进去的都是真正高频、真正能拉开差距的内容。1. 先搞清楚Java基础面试到底在考什么1.1 面试官为什么要问“八股”很多人把“八股”理解成背诵这是最大的误区。我当面试官的时候问“HashMap原理”这种题不是真想让你把源码背一遍而是想通过这道题看三件事第一你有没有主动看过源码第二你能不能把复杂机制讲清楚第三你知不知道这个设计的取舍在哪里。所以同样一道题有人答“底层是数组加链表链表超过8转红黑树”只能算及格有人能接着说“为什么转红黑树而不是平衡树因为红黑树插入删除效率更稳定为什么是8因为遵循泊松分布在负载因子0.75下链表长度达到8的概率极低”这才是能拿高分的答案。面试官追问题的时候基本能判断你是背的还是真的理解。1.2 基础篇考点的优先级地图Java基础范围很广但面试考来考去就是那么几块。我把高频考点按题目类型和优先级整理了一下方便你有针对性地复习。考点领域核心知识点面试常见问法重要程度面向对象封装、继承、多态、抽象类与接口接口和抽象类的区别是什么极高String与数据类型字符串常量池、Integer缓存、与equalsnew String(abc)创建几个对象极高集合框架ArrayList扩容、HashMap原理HashMap为什么线程不安全极高异常体系受检异常与非受检异常Error和Exception有什么区别高泛型类型擦除、通配符List 能转成List吗中高反射Class对象、动态代理反射为什么慢中Java 8新特性Lambda、Stream、Optional函数式接口是什么中从这张表能看出面试官更偏爱“概念能理解、源码能展开、实践能举例”的考点。你复习的时候不要对着知识点清单一条条背而是自己问自己如果我是面试官我会怎么追问追问之后我能接住吗2. 面向对象“三大特性”怎么答才能拿高分2.1 封装从“隐藏数据”说到“契约设计”封装是面向对象里最基础的概念但很多人的理解停留在“把属性设成private提供getter/setter”这个层面。这个回答没错但太浅了。面试官想听到的是封装不是为了“隐藏”而是为了“约束”。举个例子你设计一个银行账户类里面有余额字段。如果你直接暴露public字段调用方就可以随便把余额改成负数业务逻辑就废了。但如果你提供deposit和withdraw方法就可以在方法里做校验比如余额不能为负、取款金额不能超过余额。这就是封装的本质把外部对内部状态的直接操作变成经过你允许的受控操作保证对象状态永远合法。我面试的时候特别喜欢追问一句“你写代码的时候getter/setter是直接生成的还是会思考哪些字段需要暴露”这个问题能筛掉很多只会用IDE的人。真正理解封装的人会说到不变性、防御性拷贝、尽量暴露行为而不是数据。比如一个订单类不要暴露status字段的setter而是提供cancel()、confirm()这样的行为方法让状态流转被业务规则约束住。2.2 继承与多态从方法表到动态分派继承回答的是“是什么”的关系多态回答的是“怎么用”的关系。面试中关于多态最常见的一个入门问题是class Animal { public void speak() { System.out.println(Animal speak); } } class Dog extends Animal { Override public void speak() { System.out.println(Dog bark); } } Animal a new Dog(); a.speak(); // 输出 Dog bark答案大家都知道因为子类重写了父类方法所以调用的是子类的实现。但如果你能再往下说一层讲出JVM的动态分派机制这道题就从“入门”升级成“加分”了。JVM在类加载的时候会为每个类生成一个方法表里面存放了方法签名到实际代码地址的映射。调用虚方法的时候JVM不是编译期就确定调用哪个方法而是在运行期根据对象的实际类型去方法表里查找。这就叫动态分派。重载和重写不一样重载是静态分派编译期根据参数的静态类型就确定调用哪个方法重写是动态分派运行期才确定。很多人把这两个搞混面试官一问就露馅。继承这块还有一个高频追问“继承有什么缺点”如果你只想到复用那说明思考还不完整。继承的缺点是破坏了封装子类依赖父类实现细节父类一变子类全崩。所以现在很多规范都强调“组合优于继承”不是不能用继承而是能用组合解决的问题尽量别为了省代码去继承。2.3 抽象类和接口的选择题抽象类和接口的区别是Java面试出镜率最高的问题之一。传统的答案是这样抽象类可以有构造方法、可以有成员变量、可以有具体方法接口在Java 8之前只能有抽象方法Java 8之后可以有default和static方法Java 9之后还可以有private方法。但光背区别还不够。面试官更想听的是“你怎么选”。我一般会用一个类比抽象类像一本半成品图鉴已经画好了大部分轮廓留了几页给你补细节接口像一份契约规定了你要提供哪些能力但不关心你怎么实现。选择上有一条经验当多个类本质上是同一种东西、只是细节不同时用抽象类当多个类本质无关、只是都需要某种能力时用接口。比如狗和猫都是动物用抽象类Animal合理但飞机和鸟都会飞你不能让它们都继承一个Flyable抽象类因为两者没有血缘关系应该定义Flyable接口。还有一个坑必须提Java 8之后接口里有了default方法很多人开始纠结“那我以后用接口还是抽象类”。记住一个原则——接口强调的是能力契约抽象类强调的是模板复用。另外为什么Java只支持单继承这个问题也从侧面理解接口存在的意义单继承保证类层次足够简单避免菱形继承的复杂度而接口可以多实现既弥补了单继承的不足又不带来多继承的状态混乱。3. 数据类型与String连环追问的“重灾区”3.1 基本类型和包装类型之间藏着读源码的起点Java有8种基本类型byte、short、int、long、float、double、char、boolean。面试一般不会让你背占用字节数但你要清楚int是4字节、long是8字节、boolean在JVM规范里没有明确的字节数定义。这些概念虽然基础却经常被包装进一些奇怪的题目里。真正高频的是自动装箱拆箱和包装类型的缓存机制。看这段代码Integer a 127; Integer b 127; Integer c 128; Integer d 128; System.out.println(a b); // true System.out.println(c d); // false很多初学者第一次看到这个结果会懵。原因是Integer内部有一个缓存数组默认缓存了-128到127的Integer对象。当你用自动装箱的方式创建Integer时如果值落在缓存范围内直接返回缓存里的同一个对象所以a和b指向同一块地址返回truec和d超过了127每次装箱都会new一个新对象比较的是地址返回false。面试官很容易追问“这个缓存范围能改吗”答案是可以通过JVM参数-XX:AutoBoxCacheMax指定但一般不推荐动。你最好还能说一句“缓存范围为什么是-128到127”因为这是使用最频繁的数字区间缓存能有效减少对象创建提升性能和内存使用效率。能答到这一层说明你真的研究过而不是背的结论。3.2 和 equals 的底层逻辑这个问题基本属于“逢面必考”。在比较基本类型时比较的是值在比较引用类型时比较的是引用地址。equals默认来自Object类内部用的就是但很多类会重写它比如String、Integer。String的equals重写逻辑值得背一下先比较引用是否相同再判断是不是String类型然后用char[]逐位比较内容。这在源码里就是instanceof判断加循环比较面试能说出来就已经超过很多人了。面试官非常喜欢接着问你“重写equals的时候为什么必须重写hashCode”这是有标准答案的因为对象的hashCode用来定位它在哈希集合中的存储位置。如果两个对象equals相等hashCode必须相等否则HashMap中会出现同一个key存在两个不同位置的情况导致get找不到值。反过来hashCode相等不代表equals相等因为存在哈希冲突。这个知识点在集合部分会反复用到你先把它刻进脑子里。3.3 String那一串经典题不可变、常量池、创建几个对象String不可变性是Java基础里最值得展开的问题。String类用final修饰底层char[]也用final修饰一旦赋值就不可改变。这个设计不是拍脑袋背后有好几层原因。第一字符串常量池的复用需要不可变性。只有值不变多个引用才能安全地共享同一个字符串对象。第二hashCode可以缓存。String的hashCode经常被用到如果内容可变每次计算都要重新算不可变就可以把哈希值缓存起来提升效率。第三安全性。String在类加载、网络参数、文件路径等场景中大量使用如果可变攻击者就可以通过修改引用内容来绕过校验。第四线程安全。不可变对象天然是线程安全的不需要加锁。new String(abc)创建了几个对象这也是一个经典问题。这里要区分两种情况如果常量池中还没有abc那么会创建两个对象一个是常量池中的字符串对象一个是堆里的String对象如果常量池中已经有abc了那就只创建一个堆对象。注意String s abc这种写法只会在常量池里找或创建字符串对象不会在堆里新建。还有一个加分点可以说说字符串拼接的优化。很多人知道“循环里用拼接字符串性能差要改用StringBuilder”但更深一层的是Java编译器在编译a b这种常量拼接时会直接优化成ab而在变量拼接时编译器可能会自动帮你new一个StringBuilder来append。所以“”在小规模拼接时不一定会出大问题但循环里反复拼接每次都生成新的StringBuilder对象和String对象GC压力就上来了。3.4 StringBuilder还是StringBuffer从“线程安全”说起这两个类常常被拿来对比。StringBuffer是线程安全的因为它的关键方法都加了synchronizedStringBuilder是线程不安全的但性能更高。面试官问“你会选哪个”如果你直接说“并发场景选StringBuffer单线程选StringBuilder”那只是及格。更好的回答是说出一个反常识的实践绝大多数实际开发场景包括我见过的大部分项目中默认都用StringBuilder哪怕有些方法看起来像“可能被多线程访问”。原因是StringBuffer的线程安全只保证单个方法内部安全但它保护不了多个方法组合起来的复合操作。举个例子一个线程先append再toString另一个线程也在append两个操作之间是割裂的StringBuffer并不会保证你拿到的字符串是“某一时刻的完整快照”。所以真正需要线程安全的时候靠的不是StringBuffer而是加锁、去局部变量替代、或者用其他并发结构。也就是说StringBuffer的“安全”是很局限的代价却是每次都加锁性能损失实打实。这个视角一出来面试官就会觉得你对API的理解是建立在实际场景上的而不是停留在教科书。4. 集合框架HashMap是绕不过去的硬核考点4.1 聊聊ListArrayList扩容不是翻倍而是1.5倍List的面试题集中在ArrayList和LinkedList的区别上我直接给结论。ArrayList底层是Object[]随机访问快按下标取值是O(1)但中间插入和删除需要移动元素是O(n)。LinkedList底层是双向链表插入删除如果已经定位到节点就是O(1)但按下标访问是O(n)因为要向后遍历。实际开发中绝大多数场景用ArrayList就够了LinkedList的优势场景非常少。然后是扩容机制。ArrayList默认初始容量是10当数组满了会扩容成原来的1.5倍。这里有个细节它不是直接乘以1.5而是通过位运算oldCapacity (oldCapacity 1)实现的右移一位就是除以2加起来就是1.5倍。很多人不知道扩容倍数还有人说是翻倍这就是扣分点。为什么是1.5倍而不是2倍这其实是一个时间和空间的平衡。扩容意味着要创建新数组并把老元素拷贝过去。如果倍数太大浪费空间如果倍数太小比如1.1倍会导致频繁扩容拷贝插入性能下降。1.5倍是JDK不断调优出来的折中值。你可以顺着说一句“ArrayList构造时可以指定初始容量如果能预判数据规模应该指定一个合理初始容量避免多次扩容”这样既有源码细节又有工程经验。4.2 HashMap核心原理从数组链表到红黑树HashMap是Java面试的“必考之王”展开讲能讲半小时。我先给一个完整的答题脉络你照着练就不会乱。第一步讲结构。HashMap底层是Node[]数组每个Node可能是一个链表节点也可能是一个红黑树节点。所以整体结构是“数组链表红黑树”。第二步讲put流程。计算key的hash值这里有一个扰动处理h key.hashCode() ^ (h 16)把高位信息混入低位降低哈希冲突概率。然后用(n - 1) hash计算数组下标因为HashMap容量必须是2的幂用位运算可以替代取模效率更高。如果该位置没有元素直接放入如果有元素遍历链表或红黑树比较key是否相同相同则覆盖value不同则尾插到链表末尾或树节点中。链表长度超过8且数组长度达到64时链表转红黑树。第三步讲扩容。当size超过容量 x 负载因子时触发扩容默认容量16负载因子0.75所以到12个元素时扩容。扩容后容量翻倍元素需要重新散列。这里有个经典问题为什么Java 8要把头插法改成尾插法因为在多线程并发put时头插法会让链表成环导致get死循环。尾插法能避免这个问题但多线程下HashMap仍然不是安全的因为size的竞态条件照样存在所以并发场景要用ConcurrentHashMap。面试官很喜欢问为什么负载因子的默认值是0.75。你可以这样答负载因子太大比如1.0数组利用率高但冲突增多链表变长查询效率下降负载因子太小比如0.5冲突少但空间浪费严重。0.75是时间成本和空间成本的折中。还有一道衍生题为什么链表转红黑树的阈值是8因为遵循泊松分布在负载因子0.75的情况下链表长度达到8的概率只有约千万分之六这种情况下还出现长链表说明哈希函数有问题或者key分布极度不均匀用红黑树来兜底。4.3 线程安全的集合怎么答很多人的回答是“用Hashtable或者Collections.synchronizedMap”。这个答案没错但已经过时了。现在推荐的是ConcurrentHashMap你应该把这个变化讲清楚。Hashtable的做法是在put和get等整个方法上加上synchronized相当于给整张表加了一把大锁并发度极低。Collections.synchronizedMap也是一样只不过换了个壳本质还是全表锁。ConcurrentHashMap在Java 7里用分段锁把表分成一段一段的不同的段可以并发操作Java 8放弃了分段锁改用CAS synchronized锁的粒度细化到单个桶位。这个演进过程就是Java并发性能优化的缩影你能把1.7和1.8的差异讲出来面试官会非常满意。还有一个加分项CopyOnWriteArrayList。它适用于“读多写少”的场景读的时候不加锁写的时候复制一份新数组再修改然后让引用指向新数组。听起来很粗暴但确实有效代价是写操作有复制成本不适合频繁写的场景。你能讲出“什么场景下选什么集合”说明你是有工程判断力的。5. 异常、泛型与反射这些基础考点最容易“翻车”5.1 异常体系受检异常和非受检异常怎么区分异常的继承结构不难记。Throwable是所有异常和错误的父类下面有两个子类Error和Exception。Error表示JVM层面的严重错误比如OutOfMemoryError、StackOverflowError程序一般无法也不应该处理。Exception下面又分两类受检异常Checked Exception和非受检异常RuntimeException及其子类。受检异常在编译期强制要求处理要么try-catch要么throws比如IOException、SQLException非受检异常不强制处理比如NullPointerException、ArrayIndexOutOfBoundsException、ClassCastException。面试官喜欢问“你平时怎么处理异常”这个问题其实没有标准答案但有高下之分。低分回答是“都用try-catch包起来”。高分回答是结合自己的项目说明对需要调用方感知并处理的业务异常用受检异常或自定义异常对程序bug导致的运行时异常不该去catch应该让它暴露出来配合日志定位问题。另外尽量不要catch了Exception后什么都不做这会掩盖问题。try-with-resources也是高频考点。它是在Java 7引入的实现了AutoCloseable的资源类可以在try块结束后自动关闭。这个机制比手动在finally里close要安全得多因为finally里的close如果有异常可能把之前的业务异常覆盖掉而try-with-resources可以保留主异常关闭异常作为被抑制的异常附加。你多讲这一层面试官就知道你是有实战经验的。5.2 泛型擦除之后还能做什么泛型是Java基础里比较烧脑的部分。一句话概括Java的泛型是编译期概念运行时会进行类型擦除。ListString和ListInteger在运行时的Class对象都是ArrayList.class元素类型信息在字节码里被擦除成Object或边界类型。为什么Java采用类型擦除而不是像C那样生成不同的类型因为要向后兼容。Java 5引入泛型时已经存在大量未使用泛型的旧代码和类库为了保证旧代码能继续运行只能在编译期做类型检查运行期擦除类型信息。这个设计的代价是泛型在运行时无法获取具体的类型所以你不能new T()也不能T.class。面试真题ListString能赋值给ListObject吗不能因为List 不是List的子类型。假设能赋值你在List里放一个Integer原来的List 就“混入”了不兼容类型破坏了泛型安全。但ListString可以赋值给List? extends Object因为通配符表达了“某种Object的子类型”的范围含义。关于通配符记住PECS原则就够了? extends T用于读操作称为Producer因为只能往外取T? super T用于写操作称为Consumer因为可以往里放T。举个实际例子List? extends Number可以读但不能add任何元素除了null因为你不知道实际列表里存的具体是Integer还是DoubleList? super Integer可以add Integer但读出来只能当Object处理。能把这个原则讲清楚面试官一般不会继续为难你。5.3 反射用在哪里以及性能为什么慢反射是Java动态性的基础面试中通常结合框架来考。获取Class对象有三种方式类名.class、对象.getClass()、Class.forName(全限定类名)。反射的典型应用场景我列几个Spring的IoC容器运行时通过反射创建Bean实例Spring MVC通过反射把请求参数绑定到方法参数上MyBatis通过反射把数据库结果集映射成实体对象还有JUnit动态调用测试方法。框架之所以要用反射是因为框架在写代码时根本不知道你会定义什么类只能在运行期根据配置或注解动态加载和调用。面试官考“反射为什么慢”你不要只说一句“因为动态解析”。可以拆成几点第一反射调用方法时JVM无法在编译期做方法内联等优化第二每次调用都要进行安全检查比如访问权限校验第三反射API通过方法名查找Method对象涉及字符串匹配和方法表查比直接调用慢得多。这也是为什么Spring在大量使用反射的场景里会做缓存和优化比如缓存Method对象或者用CGLIB生成代理类来替代反射调用。一个很重要的加分细节method.setAccessible(true)可以跳过访问权限检查确实能显著提升反射速度。但要注意在JDK 17之后强封装模式下非法反射访问会抛InaccessibleObjectException你需要在启动参数里加--add-opens才能访问jdk内部API。这样既能体现你对反射原理的理解也能体现你对JDK版本演进的关注。6. Java 8新特性基础面试的“加分板块”6.1 Lambda表达式从匿名类到函数式接口Java 8引入了Lambda表达式本质上是匿名类的简化写法但它不是单纯的语法糖。它的底层是通过invokedynamic指令实现的这个细节如果你能说出来面试官会眼前一亮。Lambda表达式的类型是函数式接口就是只有一个抽象方法的接口用FunctionalInterface注解标注。比如Runnable、Comparator、Callable。下面是个最简单的例子// 匿名类写法 Runnable r1 new Runnable() { Override public void run() { System.out.println(hello); } }; // Lambda写法 Runnable r2 () - System.out.println(hello);Lambda还有一个隐藏考点捕获和非捕获。非捕获Lambda指的是Lambda体里没有引用外部变量JVM可以创建同一个实例并复用相当于单例捕获Lambda指的是Lambda体里引用了外部局部变量这个变量必须是final或事实上final每次调用时可能创建新实例。你可以顺手解释“为什么Lambda引用的局部变量必须是final的”——因为Java的Lambda捕获的其实是变量的值副本而不是变量本身如果这个变量还能被修改副本和原值就会不一致容易产生歧义。6.2 Stream API优雅但别过度封装Stream是Java 8带来的集合处理利器。它的核心特点是流水线和惰性求值。Stream操作分中间操作和终端操作中间操作比如filter、map、sorted它们不会立即执行只是把操作记录下来终端操作比如collect、forEach、reduce一调用整条流水线才开始执行。你可以类比成做菜的菜谱先列出步骤真正开火才一步步执行。面试题喜欢考“Stream和for循环哪个性能好”。诚实地说简单场景下for循环通常比Stream快一点点因为Stream有额外的抽象开销但整体差距在现代JIT优化下已经很小。真正的优势在于Stream表达的是“做什么”而不是“怎么做”代码可读性更高、更不易出错。对绝大多数业务场景来说可维护性的收益远大于那微小的性能损失。并行流也是考点。parallelStream()用的是ForkJoinPool公共线程池并行处理时如果任务里有共享可变状态或者涉及阻塞IO很容易出问题。同时并行流适合“元素之间无依赖、计算密集”的场景不适合有状态操作或者线程不安全的集合。我见过有人用parallelStream处理数据库查询结果把连接池打崩了所以别盲目用并行。6.3 Optional用对了是糖用错了是毒药Optional是Java 8用来解决空指针问题的类。它的设计初衷是让你在返回值上明确表达“这个值可能为空”倒逼调用方去处理空的情况。但实际开发中对Optional的误用非常严重。常见错误是把Optional当成一个随时可以包裹的箱子每个字段都包一层或者把Optional作为方法参数传进来。这两者都是反模式。Optional本身是一个持有对象的容器并不是为了替代所有判空场景而生的。我总结一下正确的使用姿势第一作为返回值类型使用比如OptionalUser findById(Long id)比返回null更安全调用方必须显式处理“没找到”的情况。第二配合orElse、orElseGet、orElseThrow使用比如user.orElseThrow(() - new UserNotFoundException(id))。第三字段里不要用Optional因为Optional没有实现Serializable在实体类里用它反而浪费。能用null表示“不存在”的普通字段就不要硬套Optional。此外orElse和orElseGet有个经典坑orElse(T other)无论Optional是否为空都会计算other这个对象orElseGet(Supplier)只在值为空时才执行Supplier。如果orElse里的对象创建代价很大比如查数据库或构建默认对象这里就浪费了。你以为你写了优雅的判空其实可能每调用一次都白做一次无用功。7. 实战经验答题框架、常见坑与备考建议7.1 答题思路是什么-为什么-怎么做-有什么坑面试答题确实有套路但不是死板的模板而是一种表达结构。我推荐“是什么-为什么-怎么做-有什么坑”四层递进正好对应面试官的四个期望层次。拿一个高频题举例“说一下HashMap”。低分回答是上来就讲源码讲完就结束。高分回答是先一句话说清“HashMap是基于哈希表的Map实现用于存储键值对”然后讲为什么用哈希为了实现O(1)的查找再讲怎么做数组链表红黑树put流程扩容机制最后讲坑线程不安全并发下用ConcurrentHashMap。你会发现这个结构天然地把你的知识串联了起来而且形成了一种“我能清楚地表达自己的思考过程”的观感。这个方法也适用于其他问题比如“说一说你对Spring IoC的理解”是什么IoC是控制反转把对象创建和管理交给容器——为什么解耦对象不再自己new依赖而是声明依赖由容器注入——怎么做容器扫描配置或注解通过反射创建Bean管理生命周期——有什么坑循环依赖、作用域选错、Bean初始化顺序问题。7.2 这些“八股”表面的坑你踩过几个我在面试中经常遇到一些看似很小但很致命的回答错误统一列出来你自查一下。第一个坑把ArrayList扩容说成“翻倍”。正确答案是1.5倍进位运算是oldCapacity (oldCapacity 1)。第二个坑说HashMap初始容量是16、负载因子是0.75就没下文了。你要补上初始容量可以指定而且扩容阈值是capacity * loadFactor不光是16和0.75两个数。第三个坑把StringBuffer说得比StringBuilder更好。如果你只说“StringBuffer线程安全所以更好”面试官基本就断定你缺乏工程实践。更好的说法是StringBuffer的安全性很局限实际开发中StringBuilder才是默认选择。第四个坑分不清编译期和运行期。比如“泛型在运行期会检查类型”是错的这是编译期“反射在编译期就能确定调用方法”是错的这是运行期。所有涉及“时期”的表述都要格外小心。第五个坑回答概念时只背结论不给例子。你说“接口是对行为的抽象”面试官听了毫无感觉如果你补一句“比如Sortable接口声明排序能力具体是升序还是降序由实现类决定”就立体多了。好的答案是概念例子场景三合一。7.3 备考建议写Demo、讲给别人听、整理自己的八股本最后分享几个我亲测有效的备考方法。第一把每个考点写成一个可运行的Demo。比如Integer缓存就写一段代码打出来验证HashMap的put流程就写个继承重写hashCode的类故意制造哈希冲突看看链表怎么生成的。动手验证过的知识记得比看十遍资料都牢。第二用“讲给别人听”的方式复习。我备考的时候会把每个知识点讲给同事听或者对着录音机自己讲一遍。讲着讲着就发现哪里卡壳了卡壳的地方就是你的薄弱点。能用自己的话讲明白才是真的明白了。第三维护一份自己的“八股本”。不要抄别人的面试题合集而是基于你的复习过程把每道题按“我的答案”和“可能的追问”两个维度整理出来。这份东西在面试前快速翻阅效果远好于临时抱佛脚。最后再说一个小技巧。面试官问完你一个问题如果还有余力可以主动说“这个点其实和XX是相关的需要我展开吗”。这一句话既展示了知识网络又把对话引导到你熟悉的方向很多候选人就是靠这个动作拿到加分的。Java基础的内容说多不多说少不少。我见过太多人在“八股”面前栽跟头本质上不是他们不努力而是努力的方向错了——光背结论不追原理光看文章不动手验证。如果你能把这篇文章里提到的每个考点都用“是什么-为什么-怎么做-有什么坑”这条线串起来再配合Demo验证面试官问到你的时候你会发现自己比大多数候选人答得深一截。
返回列表