mirror of
https://github.com/Snailclimb/JavaGuide
synced 2025-06-20 22:17:09 +08:00
Update Java基础知识.md
修改完善了对于 JVM JDK 和 JRE 的解释,增加了Oracle JDK 和 OpenJDK 的对比
This commit is contained in:
parent
e5b16ea4a0
commit
eb91fb7856
@ -1,37 +1,39 @@
|
||||
|
||||
|
||||
<!-- MarkdownTOC -->
|
||||
|
||||
- [1. 面向对象和面向过程的区别](#1-面向对象和面向过程的区别)
|
||||
- [面向过程](#面向过程)
|
||||
- [面向对象](#面向对象)
|
||||
- [2. Java 语言有哪些特点](#2-java-语言有哪些特点)
|
||||
- [3. 什么是 JDK 什么是 JRE 什么是 JVM 三者之间的联系与区别](#3-什么是-jdk-什么是-jre-什么是-jvm-三者之间的联系与区别)
|
||||
- [4. 什么是字节码 采用字节码的最大好处是什么](#4-什么是字节码-采用字节码的最大好处是什么)
|
||||
- [先看下 java 中的编译器和解释器:](#先看下-java-中的编译器和解释器)
|
||||
- [采用字节码的好处:](#采用字节码的好处)
|
||||
- [3. 关于 JVM JDK 和 JRE 最详细通俗的解答](#3-关于-jvm-jdk-和-jre-最详细通俗的解答)
|
||||
- [JVM](#jvm)
|
||||
- [JDK 和 JRE](#jdk-和-jre)
|
||||
- [4. Oracle JDK 和 OpenJDK 的对比](#4-oracle-jdk-和-openjdk-的对比)
|
||||
- [5. Java和C++的区别](#5-java和c的区别)
|
||||
- [6. 什么是 Java 程序的主类 应用程序和小程序的主类有何不同](#6-什么是-java-程序的主类-应用程序和小程序的主类有何不同)
|
||||
- [7. Java 应用程序与小程序之间有那些差别](#7-java-应用程序与小程序之间有那些差别)
|
||||
- [8. 字符型常量和字符串常量的区别](#8-字符型常量和字符串常量的区别)
|
||||
- [9. 构造器 Constructor 是否可被 override](#9-构造器-constructor-是否可被-override)
|
||||
- [10. 重载和重写的区别](#10-重载和重写的区别)
|
||||
- [11. Java 面向对象编程三大特性:封装、继承、多态](#11-java-面向对象编程三大特性封装继承多态)
|
||||
- [11. Java 面向对象编程三大特性: 封装 继承 多态](#11-java-面向对象编程三大特性-封装-继承-多态)
|
||||
- [封装](#封装)
|
||||
- [继承](#继承)
|
||||
- [多态](#多态)
|
||||
- [12. String 和 StringBuffer、StringBuilder 的区别是什么 String 为什么是不可变的](#12-string-和-stringbuffer、stringbuilder-的区别是什么-string-为什么是不可变的)
|
||||
- [12. String StringBuffer 和 StringBuilder 的区别是什么 String 为什么是不可变的](#12-string-stringbuffer-和-stringbuilder-的区别是什么-string-为什么是不可变的)
|
||||
- [13. 自动装箱与拆箱](#13-自动装箱与拆箱)
|
||||
- [14. 在一个静态方法内调用一个非静态成员为什么是非法的](#14-在一个静态方法内调用一个非静态成员为什么是非法的)
|
||||
- [15. 在 Java 中定义一个不做事且没有参数的构造方法的作用](#15-在-java-中定义一个不做事且没有参数的构造方法的作用)
|
||||
- [16. import java和javax有什么区别](#16-import-java和javax有什么区别)
|
||||
- [17. 接口和抽象类的区别是什么](#17-接口和抽象类的区别是什么)
|
||||
- [18. 成员变量与局部变量的区别有那些](#18-成员变量与局部变量的区别有那些)
|
||||
- [19. 创建一个对象用什么运算符?对象实体与对象引用有何不同?](#19-创建一个对象用什么运算符对象实体与对象引用有何不同)
|
||||
- [20. 什么是方法的返回值?返回值在类的方法里的作用是什么?](#20-什么是方法的返回值返回值在类的方法里的作用是什么)
|
||||
- [21. 一个类的构造方法的作用是什么 若一个类没有声明构造方法,该程序能正确执行吗 为什么](#21-一个类的构造方法的作用是什么-若一个类没有声明构造方法,该程序能正确执行吗-为什么)
|
||||
- [19. 创建一个对象用什么运算符?对象实体与对象引用有何不同?](#19-创建一个对象用什么运算符对象实体与对象引用有何不同)
|
||||
- [20. 什么是方法的返回值?返回值在类的方法里的作用是什么?](#20-什么是方法的返回值返回值在类的方法里的作用是什么)
|
||||
- [21. 一个类的构造方法的作用是什么 若一个类没有声明构造方法,该程序能正确执行吗 ?为什么?](#21-一个类的构造方法的作用是什么-若一个类没有声明构造方法该程序能正确执行吗-为什么)
|
||||
- [22. 构造方法有哪些特性](#22-构造方法有哪些特性)
|
||||
- [23. 静态方法和实例方法有何不同](#23-静态方法和实例方法有何不同)
|
||||
- [24. 对象的相等与指向他们的引用相等,两者有什么不同?](#24-对象的相等与指向他们的引用相等,两者有什么不同)
|
||||
- [25. 在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?](#25-在调用子类构造方法之前会先调用父类没有参数的构造方法其目的是)
|
||||
- [24. 对象的相等与指向他们的引用相等,两者有什么不同?](#24-对象的相等与指向他们的引用相等,两者有什么不同?)
|
||||
- [25. 在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?](#25-在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是)
|
||||
- [26. == 与 equals\(重要\)](#26--与-equals重要)
|
||||
- [27. hashCode 与 equals(重要)](#27-hashcode-与-equals(重要))
|
||||
- [hashCode()介绍](#hashcode()介绍)
|
||||
@ -39,17 +41,20 @@
|
||||
- [hashCode()与equals()的相关规定](#hashcode()与equals()的相关规定)
|
||||
- [28. 为什么Java中只有值传递](#28-为什么java中只有值传递)
|
||||
- [29. 简述线程,程序、进程的基本概念。以及他们之间关系是什么](#29-简述线程,程序、进程的基本概念。以及他们之间关系是什么)
|
||||
- [30. 线程有哪些基本状态?这些状态是如何定义的?](#30-线程有哪些基本状态?这些状态是如何定义的)
|
||||
- [30. 线程有哪些基本状态?](#30-线程有哪些基本状态)
|
||||
- [31 关于 final 关键字的一些总结](#31-关于-final-关键字的一些总结)
|
||||
- [32 Java 中的异常处理](#32-java-中的异常处理)
|
||||
- [Java异常类层次结构图](#java异常类层次结构图)
|
||||
- [Trowable类常用方法](#trowable类常用方法)
|
||||
- [Throwable类常用方法](#throwable类常用方法)
|
||||
- [异常处理总结](#异常处理总结)
|
||||
- [33 Java序列化中如果有些字段不想进行序列化 怎么办](#33-java序列化中如果有些字段不想进行序列化-怎么办)
|
||||
|
||||
- [34 获取用键盘输入常用的的两种方法](#34-获取用键盘输入常用的的两种方法)
|
||||
- [参考](#参考)
|
||||
|
||||
<!-- /MarkdownTOC -->
|
||||
|
||||
|
||||
|
||||
## 1. 面向对象和面向过程的区别
|
||||
|
||||
### 面向过程
|
||||
@ -75,39 +80,53 @@
|
||||
7. 支持网络编程并且很方便( Java 语言诞生本身就是为简化网络编程设计的,因此 Java 语言不仅支持网络编程而且很方便);
|
||||
8. 编译与解释并存;
|
||||
|
||||
## 3. 什么是 JDK 什么是 JRE 什么是 JVM 三者之间的联系与区别
|
||||
## 3. 关于 JVM JDK 和 JRE 最详细通俗的解答
|
||||
|
||||
这几个是Java中很基本很基本的东西,但是我相信一定还有很多人搞不清楚!为什么呢?因为我们大多数时候在使用现成的编译工具以及环境的时候,并没有去考虑这些东西。
|
||||
### JVM
|
||||
|
||||
**JDK:** JDK(Java Development Kit)顾名思义它是给开发者提供的开发工具箱,是给程序开发者用的。它除了包括完整的JRE(Java Runtime Environment),Java运行环境,还包含了其他供开发者使用的工具包。
|
||||
Java虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。
|
||||
|
||||
**JRE:** 普通用户而只需要安装 JRE(Java Runtime Environment)来运行 Java 程序。而程序开发者必须安装JDK来编译、调试程序。
|
||||
**什么是字节码?采用字节码的好处是什么?**
|
||||
|
||||
**JVM:** 当我们运行一个程序时,JVM 负责将字节码转换为特定机器代码,JVM 提供了内存管理/垃圾回收和安全机制等。这种独立于硬件和操作系统,正是 java 程序可以一次编写多处执行的原因。
|
||||
> 在 Java 中,JVM可以理解的代码就叫做`字节码`(即扩展名为 `.class` 的文件),它不面向任何特定的处理器,只面向虚拟机。Java 语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以 Java 程序运行时比较高效,而且,由于字节码并不专对一种特定的机器,因此,Java程序无须重新编译便可在多种不同的计算机上运行。
|
||||
|
||||
**区别与联系:**
|
||||
**Java 程序从源代码到运行一般有下面3步:**
|
||||
|
||||
1. JDK 用于开发,JRE 用于运行java程序 ;
|
||||
2. JDK 和 JRE 中都包含 JVM ;
|
||||
3. JVM 是 java 编程语言的核心并且具有平台独立性。
|
||||

|
||||
|
||||
## 4. 什么是字节码 采用字节码的最大好处是什么
|
||||
我们需要格外注意的是 .class->机器码 这一步。在这一步 jvm 类加载器首先加载字节码文件,然后通过解释器逐行解释执行,这种方式的执行速度会相对比较慢。而且,有些方法和代码块是经常需要被调用的,也就是所谓的热点代码,所以后面引进了 JIT 编译器,JIT 属于运行时编译。当 JIT 编译器完成第一次编译后,其会将字节码对应的机器码保存下来,下次可以直接使用。而我们知道,机器码的运行效率肯定是高于 Java 解释器的。这也解释了我们为什么经常会说 Java 是编译与解释共存的语言。
|
||||
|
||||
### 先看下 java 中的编译器和解释器:
|
||||
> HotSpot采用了惰性评估(Lazy Evaluation)的做法,根据二八定律,消耗大部分系统资源的只有那一小部分的代码(热点代码),而这也就是JIT所需要编译的部分。JVM会根据代码每次被执行的情况收集信息并相应地做出一些优化,因此执行的次数越多,它的速度就越快。JDK 9引入了一种新的编译模式AOT(Ahead of Time Compilation),它是直接将字节码编译成机器码,这样就避免了JIT预热等各方面的开销。JDK支持分层编译和AOT协作使用。但是 ,AOT 编译器的编译质量是肯定比不上 JIT 编译器的。
|
||||
|
||||
Java 中引入了虚拟机的概念,即在机器和编译程序之间加入了一层抽象的虚拟的机器。这台虚拟的机器在任何平台上都提供给编译程序一个的共同的接口。
|
||||
总结:Java虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。字节码和不同系统的 JVM 实现是 Java 语言“一次编译,随处可以运行”的关键所在。
|
||||
|
||||
编译程序只需要面向虚拟机,生成虚拟机能够理解的代码,然后由解释器来将虚拟机代码转换为特定系统的机器码执行。在 Java 中,这种供虚拟机理解的代码叫做`字节码`(即扩展名为 `.class` 的文件),它不面向任何特定的处理器,只面向虚拟机。
|
||||
### JDK 和 JRE
|
||||
|
||||
每一种平台的解释器是不同的,但是实现的虚拟机是相同的。Java 源程序经过编译器编译后变成字节码,字节码由虚拟机解释执行,虚拟机将每一条要执行的字节码送给解释器,解释器将其翻译成特定机器上的机器码,然后在特定的机器上运行。这也就是解释了 Java 的编译与解释并存的特点。
|
||||
JDK是Java Development Kit,它是功能齐全的Java SDK。它拥有JRE所拥有的一切,还有编译器(javac)和工具(如javadoc和jdb)。它能够创建和编译程序。
|
||||
|
||||
Java 源代码---->编译器---->jvm 可执行的 Java 字节码(即虚拟指令)---->jvm---->jvm 中解释器----->机器可执行的二进制机器码---->程序运行。
|
||||
JRE 是 Java运行时环境。它是运行已编译 Java 程序所需的所有内容的集合,包括 Java虚拟机(JVM),Java类库,java命令和其他的一些基础构件。但是,它不能用于创建新程序。
|
||||
|
||||
### 采用字节码的好处:
|
||||
如果你只是为了运行一下 Java 程序的话,那么你只需要安装 JRE 就可以了。如果你需要进行一些 Java 编程方面的工作,那么你就需要安装JDK了。但是,这不是绝对的。有时,即使您不打算在计算机上进行任何Java开发,仍然需要安装JDK。例如,如果要使用JSP部署Web应用程序,那么从技术上讲,您只是在应用程序服务器中运行Java程序。那你为什么需要JDK呢?因为应用程序服务器会将 JSP 转换为 Java servlet,并且需要使用 JDK 来编译 servlet。
|
||||
|
||||
**Java 语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以 Java 程序运行时比较高效,而且,由于字节码并不专对一种特定的机器,因此,Java程序无须重新编译便可在多种不同的计算机上运行。**
|
||||
## 4. Oracle JDK 和 OpenJDK 的对比
|
||||
|
||||
> 解释型语言:解释型语言,是在运行的时候将程序翻译成机器语言。解释型语言的程序不需要在运行前编译,在运行程序的时候才翻译,专门的解释器负责在每个语句执行的时候解释程序代码。这样解释型语言每执行一次就要翻译一次,效率比较低。——百度百科
|
||||
可能在看这个问题之前很多人和我一样并没有接触和使用过 OpenJDK 。那么Oracle和OpenJDK之间是否存在重大差异?下面通过我通过我收集到一些资料对你解答这个被很多人忽视的问题。
|
||||
|
||||
对于Java 7,没什么关键的地方。OpenJDK项目主要基于Sun捐赠的HotSpot源代码。此外,OpenJDK被选为Java 7的参考实现,由Oracle工程师维护。关于JVM,JDK,JRE和OpenJDK之间的区别,Oracle博客帖子在2012年有一个更详细的答案:
|
||||
|
||||
> 问:OpenJDK存储库中的源代码与用于构建Oracle JDK的代码之间有什么区别?
|
||||
>
|
||||
> 答:非常接近 - 我们的Oracle JDK版本构建过程基于OpenJDK 7构建,只添加了几个部分,例如部署代码,其中包括Oracle的Java插件和Java WebStart的实现,以及一些封闭的源代码派对组件,如图形光栅化器,一些开源的第三方组件,如Rhino,以及一些零碎的东西,如附加文档或第三方字体。展望未来,我们的目的是开源Oracle JDK的所有部分,除了我们考虑商业功能的部分。
|
||||
|
||||
总结:
|
||||
|
||||
1. Oracle JDK版本将每三年发布一次,而OpenJDK版本每三个月发布一次;
|
||||
2. OpenJDK 是一个参考模型并且是完全开源的,而Oracle JDK是OpenJDK的一个实现,并不是完全开源的;
|
||||
3. Oracle JDK 比 OpenJDK 更稳定。OpenJDK和Oracle JDK的代码几乎相同,但Oracle JDK有更多的类和一些错误修复。因此,如果您想开发企业/商业软件,我建议您选择Oracle JDK,因为它经过了彻底的测试和稳定。某些情况下,有些人提到在使用OpenJDK 可能会遇到了许多应用程序崩溃的问题,但是,只需切换到Oracle JDK就可以解决问题;
|
||||
4. 顶级公司正在使用Oracle JDK,例如Android Studio,Minecraft和IntelliJ IDEA开发工具,其中Open JDK不太受欢迎;
|
||||
5. 在响应性和JVM性能方面,Oracle JDK与OpenJDK相比提供了更好的性能;
|
||||
6. Oracle JDK不会为即将发布的版本提供长期支持,用户每次都必须通过更新到最新版本获得支持来获取最新版本;
|
||||
7. Oracle JDK根据二进制代码许可协议获得许可,而OpenJDK根据GPL v2许可获得许可。
|
||||
|
||||
## 5. Java和C++的区别
|
||||
|
||||
@ -146,7 +165,7 @@ Java 中引入了虚拟机的概念,即在机器和编译程序之间加入了
|
||||
|
||||
**重写:** 发生在父子类中,方法名、参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类;如果父类方法访问修饰符为 private 则子类就不能重写该方法。
|
||||
|
||||
## 11. Java 面向对象编程三大特性:封装、继承、多态
|
||||
## 11. Java 面向对象编程三大特性: 封装 继承 多态
|
||||
|
||||
### 封装
|
||||
|
||||
@ -168,7 +187,7 @@ Java 中引入了虚拟机的概念,即在机器和编译程序之间加入了
|
||||
|
||||
在Java中有两种形式可以实现多态:继承(多个子类对同一方法的重写)和接口(实现接口并覆盖接口中同一方法)。
|
||||
|
||||
## 12. String 和 StringBuffer、StringBuilder 的区别是什么 String 为什么是不可变的
|
||||
## 12. String StringBuffer 和 StringBuilder 的区别是什么 String 为什么是不可变的
|
||||
|
||||
**可变性**
|
||||
|
||||
@ -238,15 +257,15 @@ String 中的对象是不可变的,也就可以理解为常量,线程安全
|
||||
3. 从变量在内存中的生存时间上看,成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失。
|
||||
4. 成员变量如果没有被赋初值,则会自动以类型的默认值而赋值(一种情况例外被 final 修饰的成员变量也必须显示地赋值);而局部变量则不会自动赋值。
|
||||
|
||||
## 19. 创建一个对象用什么运算符?对象实体与对象引用有何不同?
|
||||
## 19. 创建一个对象用什么运算符?对象实体与对象引用有何不同?
|
||||
|
||||
new运算符,new创建对象实例(对象实例在堆内存中),对象引用指向对象实例(对象引用存放在栈内存中)。一个对象引用可以指向0个或1个对象(一根绳子可以不系气球,也可以系一个气球);一个对象可以有n个引用指向它(可以用n条绳子系住一个气球)。
|
||||
|
||||
## 20. 什么是方法的返回值?返回值在类的方法里的作用是什么?
|
||||
## 20. 什么是方法的返回值?返回值在类的方法里的作用是什么?
|
||||
|
||||
方法的返回值是指我们获取到的某个方法体中的代码执行后产生的结果!(前提是该方法可能产生结果)。返回值的作用:接收出结果,使得它可以用于其他的操作!
|
||||
|
||||
## 21. 一个类的构造方法的作用是什么 若一个类没有声明构造方法,该程序能正确执行吗 为什么
|
||||
## 21. 一个类的构造方法的作用是什么 若一个类没有声明构造方法,该程序能正确执行吗 ?为什么?
|
||||
|
||||
主要作用是完成对类对象的初始化工作。可以执行。因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。
|
||||
|
||||
@ -266,7 +285,7 @@ new运算符,new创建对象实例(对象实例在堆内存中),对象
|
||||
|
||||
对象的相等,比的是内存中存放的内容是否相等。而引用相等,比较的是他们指向的内存地址是否相等。
|
||||
|
||||
## 25. 在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?
|
||||
## 25. 在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?
|
||||
|
||||
帮助子类做初始化工作。
|
||||
|
||||
@ -374,7 +393,7 @@ final关键字主要用在三个地方:变量、方法、类。
|
||||
|
||||

|
||||
在 Java 中,所有的异常都有一个共同的祖先java.lang包中的 **Throwable类**。Throwable: 有两个重要的子类:**Exception(异常)** 和 **Error(错误)** ,二者都是 Java 异常处理的重要子类,各自都包含大量子类。
|
||||
|
||||
|
||||
**Error(错误):是程序无法处理的错误**,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。例如,Java虚拟机运行错误(Virtual MachineError),当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。
|
||||
|
||||
这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,如Java虚拟机运行错误(Virtual MachineError)、类定义错误(NoClassDefFoundError)等。这些错误是不可查的,因为它们在应用程序的控制和处理能力之 外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。在 Java中,错误通过Error的子类描述。
|
||||
@ -425,3 +444,9 @@ input.close();
|
||||
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
|
||||
String s = input.readLine();
|
||||
```
|
||||
|
||||
## 参考
|
||||
|
||||
- https://stackoverflow.com/questions/1906445/what-is-the-difference-between-jdk-and-jre
|
||||
- https://www.educba.com/oracle-vs-openjdk/
|
||||
- https://stackoverflow.com/questions/22358071/differences-between-oracle-jdk-and-openjdk?answertab=active#tab-top
|
Loading…
x
Reference in New Issue
Block a user