多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Java学习第一天:JDK安装、环境变量与基础语法全攻略

Java学习第一天:JDK安装、环境变量与基础语法全攻略 Java学习的第一天往往不是从语法开始的而是从“配环境”开始的。我自己当年在这里卡了整整一个晚上后来带新人时发现十个里面有六七个会在JDK版本、环境变量、命令行这些地方出问题。这篇就把第一天该做的事说透怎么把Java环境配置得干净利落同时把最基础的一批语法过一遍让你今天就能写出并运行自己的第一个Java程序。文章按“先跑通环境、再读懂代码、最后用练习巩固”的顺序来。前两章讲JDK安装和环境变量配置这是很多教程一笔带过、但新手最容易翻车的地方第三章用一条完整的编译运行链路把“javac和java到底干了什么”讲清楚第四、五章梳理基础语法中最核心的变量、数据类型、判断、循环和数组最后一章汇总第一天的高频报错和练手题目。适合零基础、刚装好电脑准备学Java的同学也适合装完环境但一直没搞懂背后原理的人。1. 装对JDK版本、发行版与安装路径里的门道1.1 先分清JVM、JRE和JDK别被概念绕晕网上教程一会儿让你装JRE一会儿让你配JDK一会儿又冒出来一个JVM。其实这三个东西的关系很简洁JVMJava虚拟机负责运行Java字节码的程序。它是跨平台的关键不同系统有不同版本的JVM但所有JVM认识的字节码是一样的。JREJava运行时环境JVM Java自带的核心类库比如java.lang、java.util这些基础包。如果只想跑现成的Java程序装JRE就够了。JDKJava开发工具包JRE 开发工具最重要的是javac编译器和jar打包工具。要写代码、编译代码必须装JDK。打个比方JDK是一间完整的厨房里面有菜谱、有锅、有洗好的菜JRE是餐厅后厨只能把配好的菜加热JVM就是灶台本身。你学编程是要“做菜”的所以装JDK别只看名字里带不带“开发”两个字。新手常见的坑是电脑上原来装过一个单独的JREjava -version有输出但javac -version直接报“不是内部或外部命令”。这就是典型的环境里只有运行时、没有开发工具。解决办法很简单装上JDK并让PATH优先找到JDK的bin目录。1.2 LTS版本与OpenJDK发行版版本怎么选Oracle官方承诺长期维护的Java版本叫LTS长期支持版本。目前主流LTS是Java 8、Java 11、Java 17、Java 21。很多公司老项目还在用Java 8新项目慢慢迁到17或21。第一天学习我建议直接装最新LTSJava 21理由有三语法核心稳定跟网上绝大多数教程兼容新版本带了不少好用的增强写法比如switch箭头语法、var局部变量推断学起来更省心没必要现在就用老版本“适应公司环境”等到你入职时公司技术栈大概率已经不是Java 8一家独大了。至于发行版新手别纠结“Oracle JDK和OpenJDK哪个好”。下载页面看最通用的Eclipse TemurinAdoptium项目出品或Amazon Corretto就可以两者都是完全免费、社区活跃的OpenJDK构建版。真要较真性能差异那是服务器调优阶段的事第一天不碰。有个细节值得注意下载时看清系统架构。Windows一般是x64macOS要分情况——Apple SiliconM1/M2/M3芯片选aarch64或arm64版本Intel芯片选x64版本。选错架构的安装包装完后启动会提示“无法打开”或直接崩溃。1.3 Win11 / macOS 安装实操与路径选择Windows安装步骤很简单打开Temurin官网找到Java 21 LTS对应Windows版本的.msi安装包双击安装一路Next但在安装路径那一步不要用默认的C:\Program Files\...改成C:\java\jdk-21这样的短路径安装过程中如果询问“设置JAVA_HOME”、“将javac加入PATH”勾选上装完后打开一个新的命令行窗口输入java -version和javac -version验证。macOS安装有两种方式。图形化方式下载.pkg安装包双击安装命令行方式用Homebrewbrew install openjdk21Homebrew装完默认不会自动加入PATH它会在安装末尾提示你需要执行哪条ln -sfn命令照做即可。安装路径这里特意强调一下路径里不要有中文、不要有空格、不要带括号。虽然现代Java对特殊字符路径的兼容度提高了但很多第三方工具尤其是老一点的构建脚本碰到带空格的路径就容易出幺蛾子。第一天就把这类隐患掐死在摇篮里后面会省很多事。1.4 多版本JDK共存第一天先别碰有些同学电脑上可能已经装了某个版本的JDK或者因为之前试过别的方法环境里残留了Java 8和Java 17两个版本。我建议第一天只保留一个JDK把不需要的版本卸载干净Windows在“应用”里卸载即可macOS删除/Library/Java/JavaVirtualMachines/下对应的目录。为什么要这么做因为多版本共存涉及JAVA_HOME切换、PATH优先级、IDE里SDK选择等一整套管理方案。第一天就玩多版本很容易出现“明明JDK版本对了但运行还是别的版本”的情况排查起来特别打击信心。等基础扎实了再用工具管理多版本不迟。2. JAVA_HOME与PATH环境变量没那么玄乎2.1 环境变量存在的意义让命令行能找到java配置环境变量之前先想一个问题你在命令行输入java -version操作系统怎么知道java这个命令对应哪个程序答案是系统在PATH变量记录的一组目录里挨个查找看哪个目录下存在java.exeLinux和macOS是java。找到就执行找不到就报“不是内部或外部命令”。PATH就是一张“命令查找地图”。配置环境变量的本质就是把JDK里的bin目录加进这张地图让系统知道去哪里找java和javac。那JAVA_HOME又是干什么的它不直接参与命令查找它的作用更像一个“坐标地址”。Tomcat、Maven、Gradle、IDEA这些工具启动时会先读JAVA_HOME这个环境变量找到JDK的安装位置再用它来启动Java进程。所以我们既要配PATH也要配JAVA_HOME两者分工不同PATH面向命令行JAVA_HOME面向第三方工具。老教程里经常出现的CLASSPATH第一天完全不用管。JDK 1.5以后类加载器会自动搜索当前目录和lib下的jar包不需要手动指定了。2.2 JAVA_HOME与PATH的配置步骤Win11的配置路径右键“此电脑” → 属性 → 高级系统设置 → 环境变量。在“系统变量”区域不是“用户变量”点“新建”变量名填写JAVA_HOME变量值填写JDK的安装根目录比如C:\java\jdk-21。然后找到Path变量双击编辑点“新建”填入%JAVA_HOME%\bin确定保存。macOS和Linux是在~/.zshrc或~/.bash_profile、~/.bashrc里追加一行后执行source命令export JAVA_HOME$(/usr/libexec/java_home -v 21) export PATH$JAVA_HOME/bin:$PATH配置完成后一定要新开一个命令行窗口再执行验证命令。这是新手最常踩的坑配置完环境变量回到原来的旧窗口里输入java -version发现还是老样子。原因是命令行窗口在启动时就读取了环境变量之后不会自动刷新只有新开的窗口才会带上最新配置。2.3 javac和java验证失败的四种常见原因验证命令就两条java -version javac -version如果你把环境变量配好了这两条还报错按下面顺序排查症状可能原因解决方向java和javac都找不到没新开窗口 / 没改对Path / 路径写错新开窗口检查%JAVA_HOME%\bin是否真的存在确认Path编辑后保存java -version正常javac找不到装了JRE没装JDK或Path里bin目录写错检查C:\java\jdk-21\bin\javac.exe是否存在确认装的是JDK不是JRE输出的版本跟你装的不一样系统里残留了另一个JDK/JRE且它的目录排在前面卸载多余版本把%JAVA_HOME%\bin移到Path列表最上方java能运行但双击jar包打不开不是环境变量问题是文件关联问题这个属于第二阶段第一天先不纠结另外提醒一点有些电脑出厂会自带一个JRE或者被某些软件比如MATLAB、ArcGIS偷偷装过Java运行时。你卸载了JDK之后java -version可能依然有输出这并不代表你的环境没问题——因为那个是别人装的。判断标准永远是javac -version能不能正常输出能你的JDK环境才算真的通了。3. 第一行代码javac编译、java运行的完整链路3.1 从记事本到.class编译与运行的全过程很多人直接用IDE写代码反而不知道Java程序是怎么跑起来的。第一天我强烈建议你用记事本Windows或“文本编辑”macOS手动写一个Java文件然后在命令行编译运行一次。走完这个流程你对Java的认知会比跳过这一步的人扎实很多。新建一个文本文件重命名为Hello.java注意扩展名是.java而不是.txt。用记事本打开写下面这段public class Hello { public static void main(String[] args) { System.out.println(Hello Java); } }保存后在文件所在目录打开命令行执行javac Hello.java这一步是编译。javac会把Hello.java翻译成JVM认识的字节码文件Hello.class。如果代码有语法错误这里就会报错编译成功后目录里多出一个Hello.class文件。然后执行java Hello注意这里不带.class后缀也不要带.java后缀。java命令会启动JVM读取Hello.class执行其中的main方法屏幕上打印出Hello Java。这个“编译 运行”两步走的机制是Java和Python、JavaScript这类解释型语言最直观的区别Python拿到.py文件直接跑Java必须先经过javac生成中间产物再由JVM执行。理解这一点后面你看到“编译错误”和“运行时异常”这两种报错就不会蒙圈——前者是javac阶段没通过代码根本不能运行后者是JVM跑起来之后出的问题代码编译没问题但执行逻辑有毛病。3.2 命令行传参args到底接住了什么main方法签名里的String[] args是Java程序接收外部参数的入口。改一下代码public class HelloArgs { public static void main(String[] args) { System.out.println(第一个参数是 args[0]); } }编译后执行java HelloArgs 张三屏幕会输出“第一个参数是张三”。这里args[0]接住了命令行中HelloArgs后面传的第一个参数。如果执行时没传参数程序会报ArrayIndexOutOfBoundsException——也就是下标越界。这个异常你以后会经常遇到第一天的态度是认识它、不怕它看报错信息就知道自己是数组访问越界了。3.3 main方法签名一行代码为什么不能删public static void main(String[] args)是固定的入口写法缺一不可。拆开看public表示这个方法是公开的。JVM要从外部调用它所以必须是公开的private不行static表示它是静态方法不需要先创建对象就能调用。JVM加载类后直接调用main没有实例化过程void表示这个方法没有返回值main方法名固定JVM就认这个名字String[] args命令行参数。很多新手把static漏掉或者把void写成int编译能通过但运行时报“找不到main方法”。这就是为什么IDE里新建类会帮你把这一行写好的原因——它防止手滑写错。3.4 关于“Java是静态链接的”这个说法网上有个流传很广的说法叫“Java是静态链接的”这其实是把“静态类型语言”和“静态链接”两个概念搞混了。Java是静态类型语言意味着每个变量的类型在编译期就确定但它的.class文件在编译时并不做完整的静态链接而是在运行期由类加载器按需加载JVM再通过JIT即时编译把热点代码编译成本地机器码。所以更准确的说法是Java是“编译期生成字节码、运行期动态加载并编译执行”的语言。第一天的代码还触及不到这一层但顺手把这个概念摆正以后看JVM相关文章不会被误导。4. 变量与8种基本类型内存里的“小格子”4.1 变量的声明、赋值与命名规范变量本质是在内存中开辟一块带名字的存储空间。声明变量就是“申请格子并告诉编译器这个格子存什么类型”赋值就是“往格子里放数据”。int age; // 声明一个int类型的变量 age 20; // 给变量赋值 int score 95; // 声明赋值一步到位命名规范要养成习惯驼峰命名法。变量名首字母小写后面每个单词首字母大写比如studentName、maxValue。类名首字母大写比如HelloWorld。常量全大写加下划线比如MAX_NUMBER。变量名不能以数字开头不能包含空格不能使用Java关键字int、class、public这些都是关键字。4.2 8种基本数据类型速查字节数、范围与字面量写法Java提供了8种基本数据类型用一张表把它们的字节数和取值范围列清楚类型字节数取值范围示例byte1-128 ~ 127byte b 100;short2-32768 ~ 32767short s 30000;int4约 -21亿 ~ 21亿int i 1000000;long8极大long l 10000000000L;float4约 ±3.4E38float f 3.14F;double8约 ±1.7E308double d 3.1415926;char20 ~ 65535char c A;boolean1JVM决定true / falseboolean ok true;两个容易忘的细节long类型赋值时数字后面加L不区分大小写但建议大写小写l跟数字1太像float类型赋值后面加Fchar用单引号包一个字符字符串String用双引号包这是新手区分char和String的最直观标准。实际开发中int和double是绝对主力long在时间戳、金额等场景常用byte和short大多出现在和硬件、网络协议打交道的场景。第一天认识它们就行不需要纠结每种都用一遍。4.3 引用类型与String哪些类型占“引用”的坑除了8种基本类型Java里其他类型都是引用类型包括数组、类、接口、枚举。String是引用类型里最特殊的一个——它由char[]实现但用起来跟基本类型一样直观。下面这段代码第一天必写String name 小明; System.out.println(你好 name);字符串拼接是最常用的操作号可以直接把字符串和任何类型拼起来比如年龄是 20结果是年龄是20。需要注意字符串内容的比较不能用要用equals方法。第一天先记住这个结论具体原因涉及常量池和对象引用的概念等学到面向对象再深入。4.4 自动转换、强制转换与int/int陷阱Java的类型转换分两种情况自动类型转换发生在“小类型”转“大类型”时比如int赋值给long编译器自动帮你扩展不需要额外操作。int a 100; long b a; // 自动转换没问题强制类型转换发生在“大类型”转“小类型”时需要显式加上括号可能会丢失精度。double pi 3.99; int p (int) pi; // 结果是3小数部分被直接砍掉新手最容易踩的一个坑是整数除法。看这行代码int result 5 / 2;result的值不是2.5而是2。因为5和2都是int类型整数除以整数结果还是整数小数部分直接被舍弃。想得到2.5至少要有一个操作数是浮点类型double result 5.0 / 2; // 结果是2.5这个问题在蓝桥杯、面试题里出现频率极高第一天就要把“整除”这个概念刻进脑子里。5. 判断、循环与数组让程序有脑子5.1 if/else与switch程序的第一分岔口if/else if/else是Java最基础的分支结构语法简单但要注意逻辑顺序——else if分支从上往下判断一旦某个条件成立后续的分支不再执行。int score 85; if (score 90) { System.out.println(优秀); } else if (score 60) { System.out.println(及格); } else { System.out.println(不及格); }判断条件必须是一个布尔表达式。新手常犯的错是把赋值号当成比较符比如if (score 85)会直接编译报错因为score 85是个赋值表达式结果是int类型不是boolean。switch适合“变量取值是有限个固定值”的场景。传统的switch写法是int day 3; switch (day) { case 1: System.out.println(星期一); break; case 2: System.out.println(星期二); break; default: System.out.println(其他); }break不能漏漏了会“穿透”——也就是执行完当前case后继续往下跑。Java 14之后还有箭头写法不用写break更简洁但第一天建议先把传统写法跑明白因为老代码里传统写法很常见。5.2 三种循环for、while、do-while怎么选循环就是“重复做一件事”。for循环适合“我知道要循环多少次”的场景for (int i 1; i 5; i) { System.out.println(第 i 次循环); }括号里三个部分分别是初始化int i 1、循环条件i 5、步进更新i。执行顺序是先初始化再判断条件条件为true就进循环体执行完步进更新再判断条件。while循环适合“我不知道要循环多少次但知道什么时候结束”的场景int n 0; while (n 100) { n 10; }这个例子会一直执行直到n变成100。注意一点如果条件从一开始就是falsewhile循环一次都不执行。do-while和while唯一的区别是“先做一次再判断”所以即使条件为false也至少执行一次int n 100; do { System.out.println(至少打印一次); } while (n 10);实际写代码for和while占了绝大多数场景do-while很少用到。第一天能把for的计数器逻辑搞明白就足够应付大量练习题了。5.3 数组声明、初始化、遍历与常见操作数组是“同一类型数据的集合”。声明和初始化有三种常见写法// 写法一先声明长度再逐个赋值 int[] arr1 new int[5]; arr1[0] 10; arr1[1] 20; // 写法二直接给出初始值 int[] arr2 {1, 3, 5, 7, 9}; // 写法三new 初始值 int[] arr3 new int[]{2, 4, 6, 8};要点数组下标从0开始长度为5的数组有效下标是0到4数组的length是属性不是方法用arr.length而不是arr.length()最后一个元素是arr[arr.length - 1]不是arr[length]数组创建后长度固定不能动态扩缩。遍历数组用for循环 length属性int[] scores {80, 92, 75, 66, 88}; int sum 0; for (int i 0; i scores.length; i) { sum scores[i]; } System.out.println(总分 sum);Java还提供了一种简化遍历方式叫增强for适合“只读不修改下标”的场景for (int score : scores) { System.out.println(score); }这里int score是数组里每个元素的“副本”修改它不会影响原数组这是第一天理解增强for最容易忽略的点。5.4 命令行走起来的热身题求和、找最大、看段冒泡排序把上面学的东西串起来写一个完整程序public class ArrayDemo { public static void main(String[] args) { int[] nums {12, 5, 88, 34, 27, 43}; // 求和 int sum 0; for (int i 0; i nums.length; i) { sum nums[i]; } System.out.println(数组元素之和 sum); // 找最大值 int max nums[0]; for (int i 1; i nums.length; i) { if (nums[i] max) { max nums[i]; } } System.out.println(最大值 max); } }如果你想提前看看排序长什么样下面是冒泡排序的经典写法。先不要求自己写出来能读懂每一行在干什么就行for (int i 0; i nums.length - 1; i) { for (int j 0; j nums.length - 1 - i; j) { if (nums[j] nums[j 1]) { int temp nums[j]; nums[j] nums[j 1]; nums[j 1] temp; } } }冒泡排序的思想是“每一轮把最大的数浮到末尾”。那个temp临时变量是等号交换的标准写法以后写排序、写算法都离不开。6. 第一天的坑与练习把这些踩完明天继续6.1 翻车现场第一天最常见的编译错误逐条分析这些错误我见过不知道多少遍了列出来给你当“避雷地图”类名和文件名不一致。public class Hello文件名必须是Hello.java大小写也要一致。改了文件名没改类名javac会报“类Hello是公共的应在名为Hello.java的文件中声明”。main方法写错。最常见的是漏static、把String[] args写成String args[]其实这也能编译但不推荐、把void漏掉。大小写错误。Java是大小写敏感的语言System.out.println中System和out、println哪个字母错了都编译不过。中文标点。写了中文分号、中文括号、中文引号“”这是纯新手最容易犯、又最难发现的错误。编译器报错时会给出行列号比如Hello.java:3: error: 需要;你就去第3行看有没有中文符号。分号缺失。每条语句结束要写英文分号;漏掉一个编译器可能报错在下一行容易看晕。int / int结果是整数。这不是编译错误是逻辑错误程序能跑结果不对属于更难排查的一类。判断逻辑对不对永远用“预期结果 vs 实际输出”来检验。遇到编译错误时先读报错信息里的文件名和行号再去找那一行改。别一报错就从头到尾扫代码那样效率低且容易漏。6.2 今晚可以敲完的小练习附思路练手是巩固语法的最好方式。以下题目从易到难每道都是当天学过的内容建议今晚全部敲一遍输出个人信息定义变量保存姓名、年龄、城市用一条println拼接打印。练变量声明和字符串拼接。两数求和定义两个int变量求它们的和、差、积、商。注意商的结果是不是符合你的预期体会整数除法。判断奇偶定义一个整数用if判断它是奇数还是偶数。练取模运算%和if分支。打印1到100中能被5整除的数用for循环遍历1到100满足i % 5 0就打印。练循环和取模。求数组最大值定义一个数组用循环找出最大值并打印。练数组遍历和条件判断。如果这五道题都能在半小时内完成第一天的语法基础就算过关了。6.3 第二天的入口面向对象与更多语法第一天没有提“面向对象”的概念但第一节那个public class Hello本身就是类那个main方法本身就是方法。所以第二天入口很自然学方法如何定义和调用以及类和对象的关系。推荐预习方向是“写一个自己的方法”定义一个方法接收两个int参数返回它们的和然后在main里调用它。这一步会帮你把“方法的参数、返回值、调用”这三个核心概念落地也为第三天接触面向对象打好基础。如果今天一切顺利明天你会带着第一个能跑通的程序进入Java最精彩的“万物皆对象”世界。到时候你会发现今天这些基础语法——变量、类型、判断、循环——全都是对象世界里最底层的砖瓦一块都不会白学。
返回列表