JAVA基础知识面试题

一、 面向对象

  1. 什么是面向对象?跟面向过程有什么区别?
  • 面向过程:就像做菜步骤 —— 洗菜、切菜、炒菜、装盘。关注的是“每一步怎么做”。
  • 面向对象:就像点外卖 —— 你有一个“厨师”对象,有一个“骑手”对象。你只管跟“厨师”说“做菜”,跟“骑手”说“送餐”。关注的是“谁来做这件事”。
  • Java 是面向对象的,因为现实世界就是由对象(人、车、订单)组成的,更自然。
  1. 三大特性:封装、继承、多态
  • 封装:把数据藏起来,只留几个按钮给别人用。比如你的银行卡余额是私有的(private),别人不能直接改,只能通过“存钱”、“取钱”这种公开方法(public)来操作。好处:安全、好维护。
  • 继承:子类继承父类,就能直接用父类的属性和方法,还可以自己加新东西。比如“狗”继承“动物”,动物能吃饭,狗也能,而且狗还能叫。好处:代码复用。
  • 多态:同一个行为,不同对象干出不同结果。比如“动物”都有一个“叫”的方法,狗叫是“汪汪”,猫叫是“喵喵”。你写代码时可以用“动物”类型的变量,运行时真正执行的是具体动物(狗或猫)的叫法。好处:灵活,易扩展。
  1. 重载(Overload)和重写(Override)区别
  • 重载:同一个类里,方法名相同,参数列表不同(个数、类型、顺序)。就像“吃饭”这个方法,可以“吃米饭”,也可以“吃面条,喝汤”。编译器在编译时就能决定调用哪个。
  • 重写:子类重新定义父类的方法,方法名、参数、返回类型都一样。比如父类动物“叫”是“?”,子类狗重写“叫”为“汪汪”。运行时决定调用哪个(多态的基础)。

二、 数据类型与关键字

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

8 种,记住口诀:整、浮、字、布。

  • 整数:byte(1字节), short(2), int(4), long(8)
  • 浮点数:float(4), double(8)
  • 字符:char(2)
  • 布尔:boolean(true/false)

注意:String 不是基本类型,是引用类型(类)。

5. final 关键字有什么用?

  • 修饰变量:变量变成常量,赋值后不能改。比如 final int MAX = 100;
  • 修饰方法:方法不能被重写。
  • 修饰类:类不能被继承,比如 String 类就是 final 的。

6. static 关键字什么意思?

  • 静态的,属于类本身,不属于某个对象。就像“全校学生的总数”,不依赖某个学生,用 Student.totalCount 就能访问。
  • 静态方法里不能直接访问非静态成员(因为还没创建对象呢)。
  • 静态代码块:类加载时执行一次,用来初始化静态资源。

三、 字符串

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

String 类里存字符的数组是 final 的,而且不提供修改它的方法。你每次对 String 做 +concat,其实是创建了一个新字符串,原来的没变。好处:安全(多线程不用加锁)、可以缓存(字符串常量池)。

8. String, StringBuilder, StringBuffer 区别?

  • String:不可变,适合不经常改的字符串。
  • StringBuilder:可变,线程不安全,但快。适合单线程下频繁拼接。
  • StringBuffer:可变,线程安全(方法加了 synchronized),但慢一些。适合多线程下拼接。

一句话:单线程用 StringBuilder,多线程用 StringBuffer,不动用 String。

四、 集合框架(重中之重)

9. ArrayListLinkedList 区别?

  • ArrayList:底层是数组。查找快(有下标),增删慢(因为要移动后面元素)。
  • LinkedList:底层是双向链表。增删快(只改前后指针),查找慢(要挨个遍历)。
  • 实际中 ArrayList 用得更多,因为大部分场景是遍历和查。

10. HashMap 原理?简单说下。

  • 底层是“数组 + 链表 + 红黑树”。你存一个键值对,先算 key 的哈希值,然后通过哈希函数算出应该放在数组的哪个位置(桶)。
  • 如果那个位置是空的,直接放;如果已经有个节点(哈希冲突),就挂在它后面形成链表。链表太长(>8)且数组长度≥64,就转成红黑树,提高查询效率。
  • 取数据时,同样算哈希,找到桶,然后遍历链表/树,用 equals 找匹配的 key。
  • 扩容:当元素个数超过阈值(容量 * 负载因子0.75),就翻倍扩容,所有元素重新分配位置(rehash)。

11. HashMapHashtable 区别?

  • Hashtable 是古早产物,线程安全(方法都加 synchronized),不允许 null 键和 null 值。
  • HashMap 线程不安全,允许一个 null 键和多个 null 值,性能更好。想要线程安全可以用 ConcurrentHashMap

12. ConcurrentHashMap 为什么高效?

  • 它把数据分成多个段(JDK1.7)或者直接用更细粒度的 CAS + synchronized(JDK1.8 之后)。多个线程可以同时操作不同的桶,不用锁整个表,所以并发性能好。

五、 异常处理

13. throwthrows 区别?

  • throw:在方法体内“手动”抛出一个异常对象。比如 throw new RuntimeException();
  • throws:写在方法声明后面,表示这个方法可能会抛出某种异常,调用方必须处理或继续往上抛。

14. checked 异常和 unchecked 异常区别?

  • checked 异常(受检异常):编译器强制你必须处理(try-catch 或 throws)。比如 IOException, SQLException。一般是外部环境问题,比如文件没找到。
  • unchecked 异常(非受检异常):不强制处理,一般是程序 bug。比如 NullPointerException, ArrayIndexOutOfBoundsException。运行时才报出来。

六、 反射与泛型

  1. 什么是反射?有什么作用?

反射就是在程序运行时,动态地获取类的信息(有哪些方法、字段、构造器),甚至能调用方法、修改字段。就像你拿到一个黑盒子,反射能让你透视里面的结构。用途:框架(Spring 创建对象)、动态代理、注解处理器等。缺点:有性能开销,破坏封装。

  1. 泛型是什么?有什么用?

泛型就是“类型参数”,让你写一个类或方法时可以先用一个占位符(比如 T),等到使用时再指定具体类型。比如 ArrayList<String> 就是只能放 String 的列表。好处:编译时类型检查,避免强制类型转换,更安全。

七、 JVM 内存结构(基础)

  1. JVM 内存主要分哪几块?
  • 堆:所有对象和数组都在这,也是垃圾回收的主要区域。线程共享。
  • 栈(虚拟机栈):每个方法执行时会创建一个栈帧,存局部变量、操作数栈、方法返回地址。线程私有。
  • 方法区(JDK1.8 之后叫元空间):存类信息、常量、静态变量。线程共享。
  • 程序计数器:记录当前线程执行到哪一行字节码。线程私有。
  • 本地方法栈:给 native 方法用的。
  1. 什么时候会内存溢出(OOM)?
  • 堆内存溢出:不断创建对象,但对象都被引用着,垃圾回收不了,最后堆满了。比如无限往 ArrayList 里加对象。
  • 栈内存溢出:递归调用太深,每次调用都压栈,栈空间不够了。

八、 多线程基础(简单版)

  1. 创建线程有哪几种方式?
  • 继承 Thread 类,重写 run()
  • 实现 Runnable 接口,传给 Thread
  • 实现 Callable 接口(有返回值,可抛异常),配合 FutureTask
  • 用线程池 ExecutorService

20. synchronized 原理?

它可以锁住一个对象或一个类的方法/代码块。底层是每个对象有一个监视器锁(monitor)。当线程进入 synchronized 代码块时,会尝试获取对象的锁,如果被别的线程占了,就阻塞等待。锁释放后,别的线程才能拿到。JDK1.6 之后做了优化,有偏向锁、轻量级锁、重量级锁。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇