)
前言 你好陌生人。如果你点开了这篇文章说明你或许正站在Java学习的起点甚至可能感到一丝迷茫。没关系我也是从头开始重新梳理Java体系。这篇文章是我学习路上的笔记也是我想和所有初学者、迷茫者一起进步的见证。 本系列将分阶段更新这是第一篇Java基础语法、数据类型、流程控制、数组与方法。每一个知识点我都配备了代码和解释希望能帮你少走弯路。我们顶峰相见阶段一Java基础语法入门1. 常见配置与HelloWorld学习Java前我们需要配置JDKJava开发工具包和IDE如IntelliJ IDEA。JDK包含了编译和运行Java程序的工具。// 这是一个Java程序的基本骨架 public class HelloWorld { // main方法是程序的入口JVM会从这里开始执行 public static void main(String[] args) { System.out.println(Hello, World! 开启Java之旅); } }2. 注释、关键字与保留字注释解释代码不参与编译。关键字Java赋予特殊含义的单词如class,public,static全部小写。保留字现有Java版本尚未使用但以后版本可能会作为关键字使用如goto,const。/** * 文档注释可用于生成API文档 (多行) */ public class CommentDemo { public static void main(String[] args) { // 单行注释解释单行代码 int age 18; /* * 多行注释解释多行代码 * 注意多行注释不能嵌套 */ System.out.println(age); } }3. 字面量、变量与命名规范字面量代码中直接写出的值如10,abc,a。变量内存中存储数据的基本单元。命名规范变量/方法名小驼峰myAge,getUserName类名大驼峰UserService,HelloWorld常量全大写下划线分隔MAX_VALUEpublic class VariableDemo { public static void main(String[] args) { // 数据类型 变量名 字面量; int myAge 20; // 整数字面量 double price 99.9; // 小数字面量 char gender 男; // 字符字面量 String name 张三; // 字符串字面量 (注意String是引用类型) boolean isStudent true;// 布尔字面量 System.out.println(name 的年龄是 myAge); } }阶段二数据类型与底层存储原理1. 整数与字符在计算机中的存储原理整数存储原码、反码、补码 计算机底层只存储和运算补码。正数原码 反码 补码。负数原码 - 符号位不变其余取反得反码 - 反码1得补码。为什么用补码因为补码可以将加法和减法统一且解决了0和-0的问题。字符存储ASCII、Unicode 字符在底层也是数字。Java使用Unicode编码占用2个字节兼容 ASCII。public class StorageDemo { public static void main(String[] args) { // 字符底层是数字可以直接参与运算 char c1 A; // ASCII中 A 是 65 char c2 a; // ASCII中 a 是 97 System.out.println(c1 1); // 输出 66 System.out.println(c2 - 32); // 输出 65 (A) } }2. 进制转换与Java书写格式二进制转十进制按权展开求和如101- 1×220×211×205 。二转八/十六二进制每3位转一位八进制每4位转一位十六进制。public class RadixDemo { public static void main(String[] args) { int num1 10; // 默认十进制 int num2 0b1010; // 0b开头二进制 (值为10) int num3 012; // 0开头八进制 (值为10) int num4 0xA; // 0x开头十六进制 (值为10) // 输出十进制结果 System.out.println(num1); // 10 System.out.println(num2); // 10 // 将十进制转为其他进制字符串输出 System.out.println(Integer.toBinaryString(10)); // 1010 System.out.println(Integer.toHexString(10)); // a } }3. 八大基本数据类型与类型转换Java有8大基本类型byte(1),short(2),int(4),long(8),float(4),double(8),char(2),boolean(1)。自动类型转换小范围自动转大范围byte - short - int - long - float - double。强制类型转换大范围转小范围可能精度丢失或溢出。public class TypeCastDemo { public static void main(String[] args) { // 1. 自动类型转换 int i 100; double d i; // int自动转为double System.out.println(d); // 100.0 // 2. int边界与溢出 int max Integer.MAX_VALUE; // 2147483647 System.out.println(max 1); // 溢出变成 -2147483648 // 3. 强制类型转换 (格式(目标类型) 变量) double pi 3.14; int piInt (int) pi; // 精度丢失小数部分被截断 System.out.println(piInt); // 3 // 注意long类型赋值需要加Lfloat需要加F long bigNum 10000000000L; float f 3.14F; } }阶段三运算符与键盘输入1. 算术、自增自减与赋值运算符复合赋值运算符如隐含了强制类型转换。/--前置先自增后使用后置先使用后自增。public class OperatorDemo1 { public static void main(String[] args) { int a 5; int b a; // 后置先把a的值(5)给ba再自增变6 int c a; // 前置a先自增变7再把值(7)给c System.out.println(a a , b b , c c); // 7, 5, 7 byte b1 10; // b1 b1 1; // 报错1是intb11结果是int不能自动赋给byte b1 1; // 正确 底层自带强制转换 (byte)(b1 1) } }2. 比较、逻辑与三元运算符逻辑运算符和||具有短路效果左边能确定结果右边不执行。三元运算符条件 ? 表达式1 : 表达式2。public class OperatorDemo2 { public static void main(String[] args) { int x 5, y 10; // 比较运算符结果是boolean System.out.println(x y); // false // 逻辑短路测试 boolean flag false; // 因为flag是false短路后面的 x 不会执行 if (flag (x 0)) {} System.out.println(x); // 依然是 5 // 三元运算符获取最大值 int max (x y) ? x : y; System.out.println(最大值 max); // 10 } }3. Scanner 键盘输入用于接收用户在控制台输入的数据。import java.util.Scanner; // 必须导包 public class ScannerDemo { public static void main(String[] args) { // 1. 创建Scanner对象关联系统标准输入流 Scanner sc new Scanner(System.in); System.out.println(请输入您的年龄); // 2. 接收整数 int age sc.nextInt(); System.out.println(请输入您的名字); // 3. 接收字符串 String name sc.next(); // 遇到空格/回车结束 // String line sc.nextLine(); // 接收整行遇到回车结束 System.out.println(欢迎您 name 年龄 age); sc.close(); // 关闭扫描器 } }阶段四流程控制1. 分支结构if 与 switchswitch 注意事项支持的类型byte, short, int, char, String, 枚举。case穿透问题如果没有break会继续执行下一个case。public class BranchDemo { public static void main(String[] args) { int day 2; // if 分支 if (day 1) { System.out.println(星期一); } else if (day 2) { System.out.println(星期二); } else { System.out.println(其他); } // switch 分支 (演示 case 穿透) switch (day) { case 1: case 2: case 3: case 4: case 5: System.out.println(工作日); // 1-5都会执行这里 break; // 跳出switch防止穿透 case 6: case 7: System.out.println(周末); break; default: System.out.println(输入错误); } } }2. 循环结构for、while、do-while选择原则已知次数用for未知次数用while至少执行一次用do-while。import java.util.Random; public class LoopDemo { public static void main(String[] args) { // 1. for 循环打印1-5 for (int i 1; i 5; i) { System.out.print(i ); } System.out.println(); // 2. while 循环 int count 0; while (count 3) { System.out.println(while执行: count); count; } // 3. do-while至少执行一次 int num 10; do { System.out.println(do-while执行了); } while (num 5); // 条件不满足但已经执行了一次 // 4. 死循环与 break/continue for (int i 1; i 10; i) { if (i 4) continue; // 跳过本次循环不打印4 if (i 8) break; // 跳出整个循环8及以后不打印 System.out.print(i ); // 输出 1 2 3 5 6 7 } // 5. 随机数生成 Random r new Random(); int randomNum r.nextInt(10); // 生成 0-9 的随机数 System.out.println(\n随机数: randomNum); } }阶段五数组与内存管理1. 数组基础与初始化数组是存储同一种数据类型的连续内存空间。下标从0开始长度一旦初始化不可改变。public class ArrayDemo { public static void main(String[] args) { // 1. 静态初始化指定元素 int[] arr1 {10, 20, 30}; // 2. 动态初始化指定长度系统赋默认值 (int默认0引用类型默认null) int[] arr2 new int[5]; // 3. 索引访问与遍历 arr2[0] 100; for (int i 0; i arr2.length; i) { System.out.print(arr2[i] ); // 100 0 0 0 0 } System.out.println(); // 4. 增强for循环 (foreach) 遍历 for (int num : arr1) { System.out.print(num ); // 10 20 30 } // 5. 数组越界异常 // System.out.println(arr1[3]); // 报错ArrayIndexOutOfBoundsException } }2. 内存存储与引用机制核心难点栈内存存储局部变量包括基本类型的值和引用类型的地址。方法执行完自动释放。堆内存存储new出来的对象和数组实体。由垃圾回收器GC管理。public class MemoryDemo { public static void main(String[] args) { // arr1 是一个引用变量存在栈中它指向堆中的一块内存(实体) int[] arr1 new int[]{1, 2, 3}; // 将 arr1 的地址赋值给 arr2此时两个变量指向堆中同一个数组实体 int[] arr2 arr1; // 通过 arr2 修改数据 arr2[0] 99; // 通过 arr1 访问发现数据也被修改了这就是引用机制 System.out.println(arr1[0]); // 输出 99 // 如果 arr1 null; 则 arr1 不再指向堆内存如果 arr2 也 null该数组实体将被GC回收 } }图解记忆arr1和arr2就像两把钥匙栈它们开的是同一扇门堆里的数组。阶段六方法函数与参数传递1. 方法的定义与调用方法用于封装一段可复用的代码。注意Java中方法不能嵌套定义不能在方法里面写方法。public class MethodDemo { public static void main(String[] args) { // 调用方法 int result add(5, 10); System.out.println(和为 result); // 调用重载方法 double result2 add(5.5, 10.2); System.out.println(和为 result2); } // 定义方法修饰符 返回值类型 方法名(参数列表) { 方法体 } public static int add(int a, int b) { return a b; // return 返回结果并结束方法 } // 方法重载方法名相同参数列表不同类型、个数、顺序 public static double add(double a, double b) { return a b; } // void 方法不需要返回值但可以用 return; 提前终止方法 public static void printInfo(int age) { if (age 0) return; // 提前结束 System.out.println(年龄 age); } }2. 方法执行原理与值传递机制面试必考栈调用原理方法被调用时会在栈内存中压入一个“方法栈帧”方法执行完毕后栈帧弹出。值传递机制基本数据类型传递的是数据值的副本。修改形参不影响实参。引用数据类型传递的是地址值的副本。修改形参指向的实体内容会影响实参。public class PassValueDemo { public static void main(String[] args) { // 1. 基本类型传递 int x 10; changeInt(x); System.out.println(main中的x: x); // 依然是 10互不影响 // 2. 引用类型传递 int[] arr {1, 2, 3}; changeArray(arr); System.out.println(main中的arr[0]: arr[0]); // 变成了 99因为修改了堆中的同一个实体 } public static void changeInt(int num) { num 100; // 只是修改了栈中局部变量 num 的值 } public static void changeArray(int[] array) { array[0] 99; // array 和 main 中的 arr 指向同一个堆内存修改生效 } }方法核心规则与参数传递避坑指南深度总结 学习提示方法和参数传递是基础阶段最核心、也是面试中最容易被问到的难点。很多初学者会卡壳搞不清“为什么传进去的数组被修改了而整数却没变”。下面为你系统总结帮你彻底扫清障碍① 方法的三大核心规则方法不能嵌套定义Java中方法内部绝对不能定义另一个方法与Python/JS不同所有方法必须平级定义在类中。return的双重作用有返回值的方法结束方法并将结果返回给调用者。void无返回值的方法写return;用于提前终止方法后面代码不再执行。方法重载Overload的判定发生在同一个类中方法名相同参数列表不同个数、类型、顺序不同。⚠️注意仅返回值类型不同、修饰符不同不能构成重载会编译报错② 参数传递机制核心重难点结论先行Java中只有“值传递”没有“引用传递”所谓“值传递”就是传递的是实参的副本拷贝。根据数据类型不同表现分为两种情况A基本数据类型传递“数据值”的副本传递给方法的是具体的数值。在方法内部修改这个值完全不会影响外部的原始变量。public static void main(String[] args) { int num 10; change(num); System.out.println(main中的num: num); // 输出 10没有改变 } public static void change(int x) { x 100; // 修改的只是 x 这个副本不影响外面的 num }内存解释main栈帧里num10调用change时在change栈帧里创建了x把10复制给x。x变成100只是change栈帧里的事main里的num毫发无损。情况B引用数据类型传递“地址值”的副本传递的是内存地址的副本。修改地址指向的内容➡️会影响外部原对象。给形参重新赋值改变地址➡️不会影响外部原对象。public static void main(String[] args) { int[] arr {1, 2, 3}; // 1. 修改内容会影响外部 changeContent(arr); System.out.println(修改内容后 arr[0]: arr[0]); // 输出 99 // 2. 重新赋值不会影响外部 changeReference(arr); System.out.println(重新赋值后 arr[0]: arr[0]); // 输出 99没变 } public static void changeContent(int[] array) { array[0] 99; // 顺着地址找到堆内存中的数组修改了元素 } public static void changeReference(int[] array) { array new int[]{100, 200}; // array 指向了新地址原 arr 依然指向老数组 }③ 方法执行的内存原理栈调用理解方法必须结合栈内存Stack。JVM为每个线程分配了一个栈方法的调用就是栈帧Stack Frame的压栈和弹栈压栈Push调用方法时JVM在栈顶分配一块内存栈帧存储局部变量和形参。执行方法在自己的栈帧内执行。弹栈Pop方法执行完毕遇到return或到末尾栈帧销毁局部变量瞬间消失。⚠️致命风险如果方法自己调用自己递归且没有终止条件栈帧会无限压栈最终撑爆栈内存抛出StackOverflowError。④ 常见易错点与避坑指南易错点 / 坑详细说明与避坑建议返回值类型不匹配方法声明返回int但return了double会报错。必须保证类型一致或能自动转换。void 方法带返回值void方法只能写return;提前结束绝对不能写return 值;。形参和实参搞混实参调用时实际传入的值如add(5, 10)。形参定义时声明的变量如add(int a, int b)。数组参数空指针传入的数组如果是null方法内直接arr.length会抛NullPointerException。操作前务必判空 终极避坑代码示例养成好习惯public static void printArray(int[] arr) { // 核心好习惯操作引用类型前先判断是否为null if (arr null) { System.out.println(数组为空无法打印); return; // 提前终止防止空指针异常 } for (int i 0; i arr.length; i) { System.out.print(arr[i] ); } }结语恭喜你看到了这里这篇文章涵盖了Java基础最核心的语法、底层存储原理、流程控制以及数组和方法的内存机制。这些内容是后续学习面向对象、集合框架、并发编程的基石。学习建议不要只看不练把上面的代码复制到IDEA里自己改改参数看看报错信息这是进步最快的方式。理解内存模型遇到想不通的问题画一画栈和堆的内存图90%的问题都能迎刃而解。下期预告 在下一篇文章中我们将进入Java的灵魂——面向对象编程OOP。我们会深入探讨类与对象、封装、继承、多态以及抽象类和接口的实战应用。如果你在学习中也感到迷茫或者对文章中的某个知识点有疑问欢迎在评论区留言我们一起讨论一起进步点个赞和收藏我们下一篇见