Java基础概念 — 一个新手学Java的笔记与理解

📅 2026/7/11 20:21:32
Java基础概念 — 一个新手学Java的笔记与理解
写在前面我学Java也就几个月的时间说实话刚开始接触的时候一头雾水。Java到底是个什么东西为什么大家都在学带着这些问题我就这么开始了。这篇文章算是我的学习记录吧把我觉得Java最核心基础的概念用自己的话整理一下。我不是什么大神如果哪里说得不对欢迎指正但我会尽量把我现在理解到的写清楚。说一下Java的特点学Java之前我大概知道它是一门编程语言但具体有什么特别的我也说不上来。后来一边学一边查资料慢慢发现有这么几个地方是Java最标志性的特征。**跨平台。**这个应该是Java最出名的一个特点了。“一次编写到处运行”我第一次听到这句话的时候觉得有点夸张。后来自己写了一个Hello World在Windows上编译出来一个.class文件我又扔到一台Linux服务器上试了一下——嘿还真能跑。那时候就觉得挺神奇的。原理其实也不复杂Java的代码编译之后生成的不是机器码是一种叫字节码的东西然后Java虚拟机JVM来解析执行这个字节码。JVM有Windows版本的、有Linux版本的、有Mac版本的但字节码是同一份。所以从程序员的角度来说我们只需要写一次代码编译一次拿到那个.class文件放到任何装了JVM的平台上都能跑。但我刚开始也犯了一个迷糊——我以为JVM也是跨平台的后来才知道不是。JVM本身是用C和C写的编译成机器码之后就不能跨平台了。跨平台的只是Java程序不是JVM。Windows上得装Windows版的JVMLinux上得装Linux版的。这点一开始没搞明白还跟同学争过挺尴尬的。**面向对象。**Java是一门面向对象的语言而且是非常严格的那种。什么叫面向对象呢简单说就是把现实世界里的东西抽象成对象来编程。比如你要描述一个人你就定义一个Person类里面有名字、年龄之类的属性还有吃法、走路之类的方法。然后你可以用这个类创建好多个具体的人对象每个人有自己的名字和年龄。我刚学面向对象的时候觉得这个概念有点绕。因为之前学的C语言是面向过程的——你要做一件事就一步一步写下来像做菜谱一样。但面向对象是把整个世界拆成一个个对象然后让对象之间互相发消息来协作。后来自己写了一个小项目用面向对象来组织代码确实感觉清晰很多。不同的功能写在不同的类里面改一个功能不会影响到其他地方。Java的封装、继承、多态、抽象这几个特性刚开始理解起来挺费劲的但用多了会慢慢有感觉。**内存管理垃圾回收。**这个我觉得对于新手来说特别友好。因为在C或者C里你申请了内存用完之后得自己释放不然就内存泄漏了。我有个学C的同学经常为了一个野指针调半天bug。但Java不一样它有自动的垃圾回收机制——那些不再被使用的对象JVM会自己找时间把它们清理掉。开发者不用手动释放内存基本可以说是告别了内存泄漏的问题当然也不是完全不会泄漏但确实省了很多事。这个机制在Java里叫GCGarbage Collection面试高频题具体怎么回收、有哪些回收算法那是另一篇文章的事了。**其他一些特点。**Java还有很丰富的标准库像集合框架、IO流、网络编程这些基本上常用功能都给你封装好了不用自己造轮子。而且Java的安全机制也不错有沙箱模型运行在JVM上的代码不能随便访问本地系统资源。还有多线程支持Java从语言层面就提供了线程相关的API写并发程序比C方便很多。另外Java的社区特别大遇到什么问题基本都能搜到答案生态也很成熟Spring、Hibernate这些框架我虽然还在学但已经感受到它们的强大了。Java的优势和劣势这一部分是我自己学下来的感受可能有不对的地方大家看看就好。先说说优势吧。跨平台我是真心觉得好用。特别是我们小组做项目的时候有人用Windows有人用Mac有人用Linux但因为Java跨平台我们写出来的代码在任何人的电脑上都能运行少了很多环境配置的麻烦。这个好处到了真实的开发环境里其实更明显——服务器大多是Linux的但开发可能是在Windows上Java在中间省掉了不少搬运成本。面向对象的优势我感受最深的是代码的组织和管理。刚开始学的时候没有感觉觉得多写一个类多写一个接口纯属麻烦。但后来项目稍微大一点几百行代码分布在几个不同的类里才体会到高内聚低耦合是什么意思。而且Java的继承和多态虽然概念理解起来有点门槛但用好了确实能省很多事。生态系统强大也是真的。不夸张地说Java的第三方库几乎覆盖了你能想到的任何领域。我最近在学Spring Boot配置一下就能跑一个Web应用里面的依赖注入、AOP什么的都不用自己实现。还有Hibernate做ORMMyBatis也是操作数据库很方便。还有Maven和Gradle这些构建工具管理依赖、打包部署都省心不少。内存管理对新手真的很友好。我不用去操心什么时候分配内存、什么时候释放写代码的注意力可以集中在业务逻辑上。当然不是说完全不用管内存了——如果对象引用没清理垃圾回收也回收不了还是可能导致内存溢出。但相比C来说真的轻松太多了。还有社区的稳定性。学Java不用担心学着学着这门语言就没落了。大厂在用金融、电商、通信这些行业都是Java的重度用户。而且Java版本更新也比较注意向后兼容你之前写的代码在新版本上基本还能跑。不像有些语言升级一个大版本代码全得重写。现在说说劣势吧也是我自己体会到的。性能确实不如C和Rust。虽然JVM在不断优化JIT编译器、逃逸分析这些技术让Java越来越快但毕竟中间隔了一层虚拟机启动速度也是一个问题。特别是微服务场景下一个服务启动要好几秒对比Go可能一两秒就起来了。不过这个一般业务场景下也感受不太出来。语法确实有点啰嗦。写过Python再回来写Java你会觉得自己在写作文。定义一个简单的类getter、setter、构造方法写完几十行就出去了。Java 16引入了record类Java 8有了Lambda表达式现在好了一些但跟Python比还是不够简洁。我记得第一次用Java写一个从List里过滤出符合条件的元素写了十多行人家Python一句话就搞定了。内存消耗大。JVM本身就是一个不小的程序启动之后就占着不少内存。对于小型的服务器或者资源受限的环境Java可能不太合适。我个人的项目里一个简单的Spring Boot应用启动后就占了好几百兆内存就为了跑一个CRUD确实有点重量级。面向对象有时候太死板。一切皆对象这个理念是好的但有时候你想简单写点逻辑也得先定义一个类再写一个方法才能开始写代码。Java 8引入了函数式编程和Lambda算是让步了但用起来还是没有Python或者JavaScript那么自然。还有一点Java的学习曲线对我来说不算平缓。要学的概念太多了JVM、类加载机制、内存模型、多线程、设计模式、各种框架……容易让人有挫败感。但反过来说这些也恰恰是Java的深度所在。Java为什么能跨平台这个问题我当时学的时候琢磨了好一阵子。Java的跨平台说白了就是靠JVM这个中间层。一开始我的理解是这样的我们写好的.java文件用javac编译会生成.class文件也就是字节码。这个字节码文件不能直接在操作系统上运行必须由JVM来加载和解释执行。不同操作系统上的JVM是不一样的——Windows上的JVM知道怎么跟Windows对话Linux上的JVM知道怎么跟Linux对话。但字节码文件是一样的。所以跨平台跨的是我写的那个程序不是JVM。打个比方的话就好比写了一封中文信然后我的读者里有懂中文的有不懂中文的但他们各自找了一个翻译——Windows配的翻译能把中文翻译成Windows能懂的话Linux配的翻译能把中文翻译成Linux能懂的话。信的内容是一样的但翻译的语言不一样。JVM就是这个翻译。还有一点我觉得挺重要的Java程序编译出来的不是机器码。这一点我之前一直以为是——写代码编译拿到一个可执行文件双击运行。但Java不是这个流程。Java编译的结果是字节码字节码是给JVM看的不是给操作系统直接看的。所以每次运行Java程序的时候JVM都需要把字节码翻译成当前平台能识别的机器码。即使是.exe文件用工具打包出来的那种里面也是带着一个小型JRE的本质上还是通过JVM来启动。所以总结起来就是跨平台的是Java程序字节码不是JVM。不同平台要装不同的JVM版本。字节码只有一份到哪个平台都由那个平台的JVM来翻译执行。JVM、JDK、JRE到底啥关系这三个东西我刚学的时候老是搞混。现在算是理清楚了其实很简单。JVMJava Virtual Machine就是Java虚拟机上面已经说过了负责把字节码翻译成机器码去执行。它是运行环境的核心。JREJava Runtime Environment是Java运行时环境。它包含了JVM加上Java的核心类库。如果你只是想运行一个Java程序不需要写代码那么装JRE就够了。它里面有JVM有那些你程序运行时需要的类像String、List、Map这些都是运行时要用到的但不包含编译器这些开发工具。JDKJava Development Kit是Java开发工具包。它包含了JRE全部的内容还额外加上了编译器javac、调试器jdb、构建工具、文档生成工具javadoc等等。你如果要写Java代码、编译Java代码就需要装JDK。所以它们的关系是JDK包含JREJRE包含JVM。JDK的安装包里有JREJRE的安装包里有JVM。一个比一个大一个比一个全。不过现在的JDK版本JDK 9之后其实改变了这个结构——引入了模块化系统把原来打包在一起的rt.jar拆分了。安装JDK的时候可以选择只装部分模块。但上面那个包含关系从概念上来说还是成立的。JVM和Java是同一个东西吗这个问题我之前被问到过第一反应是这不是废话吗当然不一样。但后来发现很多人包括我自己一开始确实会把这两个概念混在一起。简单来说Java是一门编程语言就是我用来写代码的那个东西——class、interface、if、for这些语法。JVM是一个平台是用来运行Java程序的。打个比方的话Java像是写文章用的中文JVM像是能够阅读理解中文的那个人。我用Java语言写了代码相当于写了一篇文章代码不能自己跑得先编译成字节码相当于把字写在纸上然后JVM来执行这个字节码相当于人来读这篇文章。还有一个我觉得挺有意思的地方因为JVM执行的是字节码所以不只能跑Java。Kotlin、Scala、Groovy这些语言虽然语法完全不一样但他们也能编译成字节码也能在JVM上跑。所以JVM现在其实不只是Java的虚拟机它是一个语言生态平台。我没用过这些语言但从理论上来说只要你有编译器能把代码转成字节码就能在JVM上运行。这点我觉得Java和JVM的设计还是挺厉害的。为什么说Java既有编译又有解释说实话这个概念我学的时候绕了半天才搞明白。因为其他语言一般要么是编译型的比如C、C要么是解释型的比如Python、JavaScript但Java偏偏两个都有。具体是这样的首先我们的.java源文件在被运行之前会先被javac编译器编译成.class字节码文件。这一步是编译——把人类能读懂的代码转成JVM能读懂的指令。然后这个字节码文件被JVM加载进去。JVM里面有两个东西来处理字节码一个是解释器一个是JIT编译器Just-In-Time。解释器的工作方式是逐条解释字节码——拿到一条指令翻译成机器码执行再拿一条再翻译再执行。这种方式启动快但执行慢。因为每条指令都要翻译一遍。JIT编译器的工作方式不一样。它会监控哪些代码被反复执行——这些代码JVM称之为热点代码——然后把整段热点代码一次性编译成本地机器码缓存起来。下次再执行这同一段代码的时候直接跑机器码不用再解释翻译了。这种执行方式启动慢因为要先判断和编译但执行快。JVM启动的时候是先用解释器慢慢跑同时JIT在后台统计热点代码。等到热点达到阈值了JIT接手编译后续执行就走快速通道。所以Java程序的运行速度其实是越来越快的——越跑越热越热越快。所以Java的是这样两个阶段先编译javac编译成字节码再混合执行解释器JIT编译。这也就是为什么Java既被称为编译型语言也被称为解释型语言。编译型语言和解释型语言的区别这个算是计算机基础了写一下我的理解。编译型语言代码写完之后通过编译器一次性把整个源代码翻译成目标平台的机器码生成一个可执行文件比如Windows上的.exe。这个文件可以直接由操作系统执行不需要额外的解释器或者虚拟机。典型的编译型语言有C、C、Go、Rust等。好处是执行速度快坏处是跨平台性差——在Windows上编译出来的.exe不能直接在Linux上跑。解释型语言代码写完之后由解释器逐行读取源代码边翻译边执行。不生成独立可执行文件。所以用解释型语言写的代码源码就是这个程序本身。典型的解释型语言有Python、JavaScript、Ruby等。好处是跨平台好——只要有对应的解释器就能跑坏处是执行速度慢因为要现场逐行翻译。Java比较特殊它走了一个中间路线先编译成字节码这一步不是编译成机器码而是编译成一种中间形式然后这个字节码由JVM来解释执行同时JIT还会把热点代码编译成本地机器码。所以Java既是编译型又是解释型严格来说是两者的混合。Python和Java有什么区别这个问题经常被问到我也来写写我的看法。Python我写过一点两者的对比还是挺明显的。首先是执行方式Java是编译javac 解释/JIT执行JVM的混合模式Python是解释执行CPython内部也会先编译成.pyc字节码但整体还是解释执行的模型。然后是语法风格Python的语法非常简洁同样的逻辑用Python写可能只需要Java一半甚至更少的代码。但简洁的代价是Python在大型项目里的可读性和可维护性可能会下降——类型不明确、代码结构不够规范。Java正好相反啰嗦但结构清晰。性能上Java通常比Python快很多因为Java有JIT编译而Python的解释器比较慢。在处理高并发、高性能要求的场景时Java的优势更明显。应用场景Java在大型企业应用、后端服务、大数据领域占主导地位Python在数据分析、人工智能、自动化脚本、快速原型开发方面更有优势。最近我个人的感受是两个都学一学没什么坏处。Java帮你理解软件工程的结构思维Python让你写起来更舒服各有各的好处。值传递和引用传递这个算是Java里比较经典的一个概念了而且是面试高频题。我刚学的时候也搞混过花了不少时间才理解清楚。先说结论Java中只有值传递没有引用传递。不管是基本类型还是引用类型传递的都是副本。如果是基本类型int、char、boolean这些传递的是这个值的副本。你在方法里修改这个副本不影响外面的原变量。比如publicstaticvoidmain(String[]args){intnum10;changeValue(num);System.out.println(num);// 仍然是10}publicstaticvoidchangeValue(inta){a20;// 改的是num的副本不是num本身}这里传进changeValue的不是num本人而是num的替身值为10的副本。你在方法里把替身改成20本人还是10。如果是引用类型对象传递的是这个对象引用的副本。两个引用原引用和副本指向堆里的同一个对象所以你在方法里通过这个副本修改对象的属性外面的原引用也能看到这个修改。但如果你把副本指向一个新的对象外面的原引用不会受影响。看个例子publicclassPerson{Stringname;Person(Stringname){this.namename;}}publicstaticvoidmain(String[]args){PersonpnewPerson(Alice);changeName(p);System.out.println(p.name);// Bob——因为p和obj指向同一个对象changeReference(p);System.out.println(p.name);// 还是Bob——因为p的指向没有变}publicstaticvoidchangeName(Personobj){obj.nameBob;// obj和p指向同一个对象改了obj的属性p也能看到}publicstaticvoidchangeReference(Personobj){objnewPerson(Charlie);// obj指向了一个新对象但p还是指向原来的对象}很多初学者包括我一开始会误以为引用类型传递的就是引用本身所以叫引用传递。但其实不是这样的。真正的引用传递比如C的引用传递是传进去的是变量的地址/别名你在方法里对参数做的任何改变包括重新赋值都会影响到外面的变量。但Java做不到这一点——你没法在一个方法内部让外面的引用指向一个新的对象。所以总结起来就是Java全都是值传递。基本类型传的是值的副本引用类型传的是引用的副本。不管哪种都是副本都不能通过修改参数本身来影响原变量。区别只在于对于引用类型通过引用的副本可以修改引用指向的那个对象的内容。写在后头这篇文章写得比我预想中长了不少。一开始只是想把Java基础概念理一理结果一写就刹不住车了。很多概念我自己也是边学边写边查写的过程本身也是一种学习。Java对我来说还是挺有魅力的——它不像C那样赤裸裸地和硬件打交道也不像Python那样让你什么都不用管。它刚好在一个中间位置给了你足够的控制力JVM调优、并发编程、内存模型但又帮你屏蔽了底层的麻烦垃圾回收、平台差异。我觉得对于想认真学编程的人来说Java是一个很好的起点。当然这些都是我自己的理解可能会有些偏差或者不够准确的地方。如果读者朋友发现哪里有错误欢迎指出来我也好去纠正和进步。