编译错误是javac编译阶段因语法或类型问题导致无法生成.class文件;运行错误是程序执行中触发RuntimeException而崩溃;逻辑错误是代码无异常但结果不符合预期。

编译错误:代码没过 javac 这关,根本跑不起来
编译错误发生在把 .java 源文件交给 javac 编译成 .class 字节码时。Java 是强类型、语法严格的语言,任何不符合语法规则或类型约束的地方都会被拦下。
常见现象包括:
-
error: cannot find symbol—— 变量、方法或类名拼错了,或者没 import -
error: class, interface, or enum expected—— 多写了花括号、少写了分号,或者类外写了可执行语句 -
error: incompatible types—— 比如把String直接赋给int变量,没做转换 -
error: missing return statement—— 非void方法里所有分支都必须有return
这类错误必须修复后才能生成 .class 文件,连 java 命令都执行不了。
运行错误:编译过了,但程序跑着就崩了
运行错误(也叫运行时异常)是字节码能加载、也能开始执行,但在某一步触发了 JVM 无法继续的状况。它们属于 RuntimeException 及其子类,编译器不强制你处理。
立即学习“Java免费学习笔记(深入)”;
典型例子:
-
NullPointerException—— 调用了null引用的方法或字段 -
ArrayIndexOutOfBoundsException—— 数组下标越界,比如访问arr[5]但数组长度是 5(最大合法索引是 4) -
ClassCastException—— 强制转型失败,如把Object直接转成String,而它实际是Integer -
ArithmeticException: / by zero—— 整数除零
这些异常一旦抛出,默认会中断当前线程,并打印堆栈。你可以用 try-catch 捕获,但不捕获就会终止程序。
还有种错误:编译通过、运行也不报错,但结果不对
这不是编译或运行错误,而是逻辑错误(logic error)。JVM 完全按你的代码执行,但它和你“想让它做的”不一致。
比如:
- 循环条件写成
i 却该是i ,多跑了一次 - 用
==比较两个String,结果总是false(该用.equals()) - 变量作用域搞混,修改了不该改的副本
这种错误不会有任何提示,只能靠调试、日志、单元测试暴露。IDE 的断点和 System.out.println 还是得常备。
容易被忽略的关键点
编译错误和运行错误的界限其实没那么绝对——有些看似“运行时”的问题,其根源其实在编译期就被埋下了。
例如:
- 泛型擦除后类型信息丢失,导致
ClassCastException在运行时才暴露,但编译期的unchecked警告早就在提醒你了 - 使用反射调用方法时,方法名写错,编译期查不到(因为是字符串),但运行时抛
NoSuchMethodException -
static上下文中引用非static成员,编译直接报错;但若通过反射绕过去,可能到运行时才失败
真正难缠的,往往是那些“编译能过、运行不崩、结果不对”的组合态,这时候得盯住数据流,而不是只看错误提示。







