上一篇 Java基础知识学习总结之(上)
下一篇 Java 集合容器篇面试题 (上)
毕设/私活/大佬必备,一个挣钱的开源前后端分离脚手架
2W字梳理总结Java--Mybatis经典面试题《王者笔记收藏版》
目录
Cookie和Session分别是什么?Cookie的容量限制是多少?说⼀下 Session 的⼯作原理?
如果客户端禁⽌ Cookie 能实现 Session 还能用吗?
三、计算机原理和操作系统
内存、CPU、硬盘?
内存是计算机的重要部件之⼀。 它是外存与CPU进⾏沟通的桥梁,计算机中所有程序的运⾏都在内存中进⾏。内存性能的强弱影响计算机整体发挥的⽔平。 内存(Memory)也称内存储器和主存储器,它用于暂时存放CPU中的运 算数据,与硬盘等外部存储器交换的数据。 只要计算机开始运⾏,操作系统就会把需要运算的数据从内存调到 CPU中进⾏运算。当运算完成,CPU将结果传送出来。 内存的运⾏也决定计算机整体运⾏快慢的程度。 内存条由内存芯片、电路板、⾦⼿指等部分组成。 电脑硬盘是计算机最主要的存储设备。硬盘(港台称之为硬碟,英⽂ 名:Hard Disk Drive, 简称HDD 全名温彻斯特式硬盘)由⼀个或者多个 铝制或者玻璃制的碟片组成。这些碟片外覆盖有铁磁性材料。 绝⼤多数硬盘都是固定硬盘,被永久性地密封固定在硬盘驱动器中。 早期的硬盘存储媒介是可替换的,不过今日典型的硬盘是固定的存储媒 介,被封在硬盘里 (除了⼀个过滤孔,用来平衡空⽓压⼒)。随着发 展,可移动硬盘也出现了,⽽且越来越普及,种类也越来越多.⼤多数微 机上安装的硬盘,由于都采用温切斯特(winchester)技术⽽被称之为“温切 斯特硬盘”,或简称“温盘”。 中央处理器(CPU),是电⼦计算机的主要设备之⼀,电脑中的核⼼ 配件。其功能主要是解释计算机指令以及处理计算机软件中的数据。CPU 是计算机中负责读取指令,对指令译码并执⾏指令的核⼼部件。中央处理 器主要包括两个部分,即控制器、运算器,其中还包括⾼速缓冲存储器及 实现它们之间联系的数据、控制的总线。电⼦计算机三⼤核⼼部件就CPU、内部存储器、输⼊/输出设备。中央处理器的功效主要为处理指 令、执⾏操作、控制时间、处理数据。
Linux基本命令
1.sudo
这个SuperUserDo是Linux新⼿要使用的最重要的命令。需要根权限的 每⼀个命令都需要这个sudo命令。你可以在需要根权限的每个命令之前使 用sudo。$ sudo su
2.ls(list)
借助list命令,终端就会显示你正在处理的那个目录里面的所有⽂件和⽂件夹。假设我在/home⽂件夹里面,想查看/home里面的目录和⽂ 件。
/home$ ls
/home中的ls返回下列结果:
imad lost+found
3.cd
更改目录(cd)是始终在终端中使用的主要命令。它是最基本的Linux命 令之⼀。使用这个命令很简单。只要输⼊你想要从当前目录进⼊到的那个 ⽂件夹的名称。如果想要返回上⼀级,只要将双圆点(..)作为参数。假设我在/home目录中,想进⼊到始终在/home里面的usr目录。下面 是我可以使用cd命令的⽅法:
/home $ cd usr
/home/usr $
4.mkdir
仅仅更改目录还不全面。有时候,你想要创建⼀个新的⽂件夹或⼦⽂
件夹。可以使用mkdir命令来做到这⼀点。只要在终端中将你的⽂件夹名称放在mkdir命令的后面即可。
$ mkdir folderName
5.cp
拷贝粘贴是我们为了组织整理⽂件⽽需要完成的重要任务。使用cp将 帮助你从终端拷贝粘贴⽂件。首先,你确定想要拷贝的那个⽂件,然后输⼊目的地位置,即可粘贴⽂件。
$ cp src des
注意:如果你将⽂件拷贝到任何新⽂件都需要根权限的目录,那么你就需要使用sudo命令。
6.rm
rm这个命令可以移除你的⽂件,甚⾄移除你的目录。如果⽂件需要根权限才能移除,可以使用-f。你还可以使用-r来进⾏递归移除,从⽽移除你的⽂件夹。
$ rm myfile.txt
7.apt-get
就不同的发⾏版⽽⾔,这个命令各不相同。在基于Debian的Linux发 ⾏版中,想安装、移除和升级任何软件包,我们可以使用⾼级包装⼯具 (APT)软件包管理器。apt-get命令可帮助你安装需要在Linux中运⾏的软件。这是个功能强⼤的命令⾏⼯具,可以执⾏安装、升级、甚⾄移除软件这类任务。 在其他发⾏版(比如Fedora和Centos)中,有不同的软件包管理器。
Fedora过去有yum,但现在它有dnf。
$ sudo apt-get update
$sudo dnf update
8.grep
你需要找到⼀个⽂件,但是又记不得它的确切位置或路径。grep可以帮助你解决这个问题。你可以使用grep命令,根据给定的关键字帮助找到⽂件。
$ grep user /etc/passwd
9.cat
作为用户,你常常需要查看来自脚本的⼀些⽂档或代码。同样,其中⼀个Linux基本命令是cat命令。它会为你显示⽂件里面的⽂本。
$ cat CMakeLists.txt
10.poweroff
有时候,你需要直接从终端来关机。这个命令就能完成这项任务。别忘了在命令的开头添加sudo,因为它需要根权限才能执⾏poweroff。
$ sudo poweroff
线程和进程的区别?
进程和线程的根本区别是进程是操作系统资源分配的基本单位,⽽线 程是处理器任务调度和执⾏的基本单位。另外区别还有资源开销、包含关 系、内存分配、影响关系、执⾏过程等。
资源开销:每个进程都有独立的代码和数据空间(程序上下⽂),程 序之间的切换会有较⼤的开销;线程可以看做轻量级的进程,同⼀类线程 共享代码和数据空间,每个线程都有自⼰独立的运⾏栈和程序计数器(PC),线程之间切换的开销小。
包含关系:如果⼀个进程内有多个线程,则执⾏过程不是⼀条线的,
⽽是多条线(线程)共同完成的;线程是进程的⼀部分,所以线程也被称为轻权进程或者轻量级进程。
内存分配:同⼀进程的线程共享本进程的地址空间和资源,⽽进程之间的地址空间和资源是相互独立的。
影响关系:⼀个进程崩溃后,在保护模式下不会对其他进程产⽣影响,但是⼀个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。
执⾏过程:每个独立的进程有程序运⾏的⼊⼝、顺序执⾏序列和程序出⼝。但是线程不能独立执⾏,必须依存在应用程序中,由应用程序提供多个线程执⾏控制,两者均可并发执⾏。
进程和线程的根本区别是进程是操作系统资源分配的基本单位,⽽线程是处理器任务调度和执⾏的基本单位。
四、数据库基础
关系型数据库和非关系型数据库有哪些区别?举例说明
关系型数据库,是指采用了关系模型来组织数据的数据库,其以⾏和列的形式存储数据,以便于用户理解,关系型数据库这⼀系列的⾏和列被称为表,⼀组表组成了数据库。用户通过查询来检索数据库中的数据,⽽查询是⼀个用于限定数据库中某些区域的执⾏代码。关系模型可以简单理解为⼆维表格模型,⽽⼀个关系型数据库就是由⼆维表及其之间的关系组成的⼀个数据组织。例如:mysql、oracle、sql server NoSQL,泛指非关系型的数据库。随着互联⽹web2.0⽹站的兴起,传统的关系数据库在处理web2.0⽹站,特别是超⼤规模和⾼并发的SNS类型的web2.0纯动态⽹站已经显得⼒不从⼼,出现了很多难以克服的问题,⽽非关系型的数据库则由于其本身的特点得到了非常迅速的发展。NoSQL数据库的产⽣就是为了解决⼤规模数据集合多重数据种类带来的挑战,尤其是⼤数据应用难题。例如:redis
数据库索引是做什么用的
在关系数据库中,索引是⼀种单独的、物理的对数据库表中⼀列或多列的值进⾏排序的⼀种存储结构,它是某个表中⼀列或若⼲列值的集合和 相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。
什么情况需要给字段建立索引?
表的主键、外键必须有索引;
数据量超过300的表应该有索引;
经常与其他表进连接的表,在连接字段上应该建索引;
经常出现在Where句 order by中的字段,特别是表的字段,应该建索引;
索引应该建在选择性的字段上;
索引应该建在字段上,对于的本字段甚超字段,不要建索引;
什么情况下索引会失效?
1.单独引用复合索引里非第⼀位置的索引列 假如有INDEX(a,b,c), 当条件为a或a,b或a,b,c时都可以使用索引,
但是当条件为b,c时将不会使用索引。
复合索引遵守“最左前缀”原则,即在查询条件中使用了复合索引的第 ⼀个字段,索引才会被使用。因此,在复合索引中索引列的顺序⾄关重要。如果不是按照索引的最左列开始查找,则⽆法使用索引。
2.对索引列运算,运算包括(+、-、*、/、!、、%、like’%_’(%放在前面)、or、in、exist等),导致索引失效。
错误的例⼦:select * from test where id-1=9;
正确的例⼦:select * from test where id=10;
注意!!
mysql sql 中如果使用了 not in , not exists , ( 不等于 !=) 这些不⾛ < 小于 > ⼤于 = 这个根据实际查询数据来判断,如果全盘扫描速度比索引速度要快则不⾛索引 。
3.对索引应用内部函数,这种情况下应该建立基于函数的索引。
select * from template t where ROUND(t.logicdb_id) = 1
此时应该建ROUND(t.logicdb_id)为索引。
4、类型错误,如字段类型为varchar,where条件用number。
例:template_id字段是varchar类型。
错误写法:select * from template t where t.template_id = 1
正确写法:select * from template t where t.template_id = ‘1’
5.如果MySQL预计使用全表扫描要比使用索引快,则不使用索引
6.like的模糊查询以%开头,索引失效
7.索引列没有限制 not null,索引不存储空值,如果不限制索引列是 not null,oracle会认为索引列有可能存在空值,所以不会按照索引计算
慢查询是什么?
分析MySQL语句查询性能的⽅法除了使用 EXPLAIN 输出执⾏计划,还可以让MySQL记录下查询超过指定时间的语句,我们将超过指定时间的SQL语句查询称为“慢查询”。
主从库是什么?
1、做数据的热备,作为后备数据库,主数据库服务器故障后,可切 换到从数据库继续⼯作,避免数据丢失。
2、架构的扩展。业务量越来越⼤,I/O访问频率过⾼,单机⽆法满⾜,此时做多库的存储,降低磁盘I/O访问的频率,提⾼单个机器的I/O性能。
3、读写分离,使数据库能支撑更⼤的并发。在报表中尤其重要。由于部分报表sql语句非常的慢,导致锁表,影响前台服务。如果前台使用master,报表使用slave,那么报表sql将不会造成前台锁,保证了前台速度。
五、Java开发相关基础
MVC框架?
MVC开始是存在于桌面程序中的,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从⽽使同⼀个程序可以使用不同的表现形式。比如⼀批统计数据可以分别用柱状图、饼图来表示。C存在的目的则是确保M和V的同步,⼀旦M改变,V应该同步更新。 [1-2] 模型-视图-控制器(MVC)是Xerox PARC在⼆⼗世纪⼋⼗年代为编程语⾔Smalltalk-80发明的⼀种软件设计模式,已被⼴泛使用。后来被推荐为Oracle旗下Sun公司Java EE平台的设计模式,并且受到越来越多的使用ColdFusion和PHP的开发者的欢迎。模型-视图-控制器模式是⼀个有用的⼯具箱,它有很多好处,但也有⼀些缺点。
js跨域请求是什么意思?
跨域访问,简单来说就是 A ⽹站的 javascript 代码试图访问 B ⽹站,包括提交内容和获取内容。由于安全原因,跨域访问是被各⼤浏览器所默认禁⽌的。
服务器500、502、503、504、505错误是什么?
HTTP 500 - 内部服务器错误
HTTP 502 - ⽹关错误
503 服务器目前⽆法使用(由于超载或停机维护)。通常,这只是暂时状态。(服务不可用)
504 表示超时,也就是客户端所发出的请求没有到达⽹关
505 服务器不支持请求中所用的 HTTP 协议版本。(HTTP 版本不受支持)
负载均衡是什么?
负载均衡建立在现有⽹络结构之上,它提供了⼀种廉价有效透明的⽅法扩展⽹络设备和服务器的带宽、增加吞吐量、加强⽹络数据处理能⼒、提⾼⽹络的灵活性和可用性。
负载均衡(Load Balance)其意思就是分摊到多个操作单元上进⾏执⾏,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从⽽共同完成⼯作任务。
Cookie和Session分别是什么?Cookie的容量限制是多少?说⼀下 Session 的⼯作原理?
Cookie是⼀段不超过4KB的小型⽂本数据,由⼀个名称(Name)、⼀个值(Value)和其它⼏个用于控制Cookie有效期、安全性、使用范围的可选属性组成。
Session:在计算机中,尤其是在⽹络应用中,称为“会话控制”。
Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,⽽是在整个用户会话中⼀直存在下去。当用户请求来自应用程序的 Web页时,如果该用户还没有会话,则Web服务器将自动创建⼀个 Session对象。当会话过期或被放弃后,服务器将终⽌该会话。Session 对象最常见的⼀个用法就是存储用户的首选项。
如果客户端禁⽌ Cookie 能实现 Session 还能用吗?
能用。需要特殊处理。
Session共享原理是什么?怎么实现?
应用服务器间的session复制共享
基于cache DB缓存的session共享
基于redis缓存的session共享目的是实现单点登录
java的历史
1991 年Sun公司的James Gosling等⼈开始开发名称为 Oak 的语⾔,希望用于控制嵌⼊在有线电视交换盒、PDA等的微处理器;
1994年将Oak语⾔更名为Java;
Java的三种技术架构:
JAVAEE:Java Platform Enterprise Edition,开发企业环境下的应用程序,主要针对web程序开发;
JAVASE:Java Platform Standard Edition,完成桌面应用程序的开发,是其它两者的基础;
JAVAME:Java Platform Micro Edition,开发电⼦消费产品和嵌⼊式设备,如⼿机中的程序;
正则表达式?
好处:正则的出现,对字符串的复杂操作变得更为简单。
特点:将对字符串操作的代码用⼀些符号来表示。只要使用了指定符号,就可以调用底层的代码对字符串进⾏操作。符号的出现,简化了代码的书写。
弊端:符号的出现虽然简化了书写,但是却降低了阅读性。
其实更多是用正则解决字符串操作的问题。
组:用小括号标示,每定义⼀个小括号,就是⼀个组,⽽且有自动编 号,从1开始。 只要使用组,对应的数字就是使用该组的内容。别忘了,数组要加 \\。 (aaa(wwww(ccc))(eee))技巧,从左括号开始数即可。有⼏个左括号就是⼏组。
常见操作:
1,匹配:其实用的就是String类中的matches⽅法。
String reg = “[1—9][0—9]{4,14}";
boolean b = qq.matches(reg);//将正则和字符串关联对字符串进⾏匹配。
2,切割:其实用的就是String类中的split⽅法。
3,替换:其实用的就是String类中的replaceAll();
4,获取:
1),先要将正则表达式编译成正则对象。使用的是Pattern中静态⽅法 compile(regex);
2),通过Pattern对象获取Matcher对象。
Pattern用于描述正则表达式,可以对正则表达式进⾏解析。 ⽽将规则操作字符串,需要从新封装到匹配器对象Matcher中。
然后使用Matcher对象的⽅法来操作字符串。
如何获取匹配器对象呢?
通过Pattern对象中的matcher⽅法。该⽅法可以正则规则和字符串想关联。并返回匹配器对象。
3),使用Matcher对象中的⽅法即可对字符串进⾏各种正则操作。
反射技术?
就是动态加载⼀个指定的类,并获取该类中的所有的内容。⽽且将字
节码⽂件封装成对象,并将字节码⽂件中的内容都封装成对象,这样便于操作这些成员。简单说:反射技术可以对⼀个类进⾏解剖。
反射的好处:⼤⼤的增强了程序的扩展性。
反射的基本步骤:
1、获得Class对象,就是获取到指定的名称的字节码⽂件对象。
2、实例化对象,获得类的属性、⽅法或构造函数。
3、访问属性、调用⽅法、调用构造函数创建对象。
Java 语⾔有哪些特点?
简单易学;
面向对象(封装,继承,多态);
平台⽆关性( Java 虚拟机实现平台⽆关性);
可靠性;
安全性;
支持多线程( C++ 语⾔没有内置的多线程机制,因此必须调用操作
系统的多线程功能来进⾏多线程程序设计,⽽ Java 语⾔却提供了多线程支持);
支持⽹络编程并且很⽅便( Java 语⾔诞⽣本身就是为简化⽹络编程
设计的,因此 Java 语⾔不仅支持⽹络编程⽽且很⽅便);
重载和重写的区别?
重载: 发⽣在同⼀个类中,⽅法名必须相同,参数类型不同、个数
不同、顺序不同,⽅法返回值和访问修饰符可以不同,发⽣在编译时。
重写: 发⽣在⽗⼦类中,⽅法名、参数列表必须相同,返回值范围
小于等于⽗类,抛出的异常范围小于等于⽗类,访问修饰符范围⼤于等于⽗类;如果⽗类⽅法访问修饰符为 private 则⼦类就不能重写该⽅法。
接⼝和抽象类的区别是什么?
接⼝的⽅法默认是 public,所有⽅法在接⼝中不能有实现(Java 8 开始接⼝⽅法可以有默认实现),⽽抽象类可以有非抽象的⽅法。
接⼝中除了static、final变量,不能有其他变量,⽽抽象类中则不⼀
定。 ⼀个类可以实现多个接⼝,但只能实现⼀个抽象类。接⼝自⼰本身可以通过extends关键字扩展多个接⼝。
接⼝⽅法默认修饰符是public,抽象⽅法可以有public、protected和 default这些修饰符(抽象⽅法就是为了被重写所以不能使用private关键字 修饰!)。 从设计层面来说,抽象是对类的抽象,是⼀种模板设计,⽽接⼝是对⾏为的抽象,是⼀种⾏为的规范。
备注:在JDK8中,接⼝也可以定义静态⽅法,可以直接用接⼝名调
用。实现类和实现是不可以调用的。如果同时实现两个接⼝,接⼝中定义了⼀样的默认⽅法,则必须重写,不然会报错。
成员变量与局部变量的区别有哪些?
从语法形式上看:成员变量是属于类的,⽽局部变量是在⽅法中定义
的变量或是⽅法的参数;成员变量可以被 public,private,static 等修饰符所修饰,⽽局部变量不能被访问控制修饰符及 static 所修饰;但是,成员变量和局部变量都能被 final 所修饰。
从变量在内存中的存储⽅式来看:如果成员变量是使用static修饰的,
那么这个成员变量是属于类的,如果没有使用static修饰,这个成员变量是属于实例的。⽽对象存在于堆内存,局部变量则存在于栈内存。
从变量在内存中的⽣存时间上看:成员变量是对象的⼀部分,它随着
对象的创建⽽存在,⽽局部变量随着⽅法的调用⽽自动消失。
成员变量如果没有被赋初值:则会自动以类型的默认值⽽赋值(⼀种
情况例外:被 final 修饰的成员变量也必须显式地赋值),⽽局部变量则不会自动赋值。
== 与 equals?
== : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象 是不是同⼀个对象(基本数据类型==比较的是值,引用数据类型==比较的是内存地址)。
equals() : 它的作用也是判断两个对象是否相等。但它⼀般有两种使用情况:
情况1:类没有覆盖 equals() ⽅法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。
情况2:类覆盖了 equals() ⽅法。⼀般,我们都覆盖 equals() ⽅法来比较两个对象的内容是否相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。
举个例⼦:
public class test1 {
public static void main(String[] args) {
String a = new String("ab"); // a 为⼀个引用
String b = new String("ab"); // b为另⼀个引用,对象的内容⼀样
String aa = "ab"; // 放在常量池中
String bb = "ab"; // 从常量池中查找
if (aa == bb) // true
System.out.println("aa==bb");
if (a == b) // false,非同⼀对象
System.out.println("a==b");
if (a.equals(b)) // true
System.out.println("aEQb");
if (42 == 42.0) { // true
System.out.println("true");
}
}
}
说明:
String 中的 equals ⽅法是被重写过的,因为 object 的 equals ⽅法是比 较的对象的内存地址,⽽ String 的 equals ⽅法比较的是对象的值。
当创建 String 类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建⼀个 String 对象。
hashCode 与 equals ?
hashCode()介绍
hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回⼀ 个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。 hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包 含有hashCode() 函数。
散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利用到了散列码!(可以快速找到所需要的对象)
为什么要有 hashCode
我们先以“HashSet 如何检查重复”为例⼦来说明为什么要有
hashCode: 当你把对象加⼊ HashSet 时,HashSet 会先计算对象的hashcode 值来判断对象加⼊的位置,同时也会与其他已经加⼊的对象的hashcode 值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 equals() ⽅法来检查 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让其加⼊操作成功。如果不同的话,就会重新散列到其他位置。
(摘自我的Java启蒙书《Head first java》第⼆版)。这样我们就⼤⼤减少了 equals 的次数,相应就⼤⼤提⾼了执⾏速度。
通过我们可以看出:hashCode() 的作用就是获取哈希码,也称为散列码;它实际上是返回⼀个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode()在散列表中才有用,在其它情况下没用。在散列表中hashCode() 的作用是获取对象的散列码,进⽽确定该对象在散列表中的位置。hashCode()与equals()的相关规定如果两个对象相等,则hashcode⼀定也是相同的 两个对象相等,对两个对象分别调用equals⽅法都返回true两个对象有相同的hashcode值,它们也不⼀定是相等的因此,equals ⽅法被覆盖过,则 hashCode ⽅法也必须被覆盖hashCode() 的默认⾏为是对堆上的对象产⽣独特值。如果没有重写hashCode(),则该 class 的两个对象⽆论如何都不会相等(即使这两个对象指向相同的数据)
关于 JVM JDK 和 JRE
JVM
Java虚拟机(JVM)是运⾏ Java 字节码的虚拟机。JVM有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。
什么是字节码?采用字节码的好处是什么?
在 Java 中,JVM可以理解的代码就叫做字节码(即扩展名为 .class 的⽂件),它不面向任何特定的处理器,只面向虚拟机。Java 语⾔通过字节码的⽅式,在⼀定程度上解决了传统解释型语⾔执⾏效率低的问题,同时又保留了解释型语⾔可移植的特点。所以 Java 程序运⾏时比较⾼效,⽽且,由于字节码并不针对⼀种特定的机器,因此,Java程序⽆须重新编译便可在多种不同操作系统的计算机上运⾏。
我们需要格外注意的是 .class->机器码 这⼀步。在这⼀步 JVM 类加载器首先加载字节码⽂件,然后通过解释器逐⾏解释执⾏,这种⽅式的执⾏速度会相对比较慢。⽽且,有些⽅法和代码块是经常需要被调用的(也就是所谓的热点代码),所以后面引进了 JIT 编译器,⽽JIT 属于运⾏时编译。当 JIT 编译器完成第⼀次编译后,其会将字节码对应的机器码保存下来,下次可以直接使用。⽽我们知道,机器码的运⾏效率肯定是⾼于 Java解释器的。这也解释了我们为什么经常会说 Java 是编译与解释共存的语⾔。
HotSpot采用了惰性评估(Lazy Evaluation)的做法,根据⼆⼋定律,消耗⼤部分系统资源的只有那⼀小部分的代码(热点代码),⽽这也就是JIT所需要编译的部分。JVM会根据代码每次被执⾏的情况收集信息并相应地做出⼀些优化,因此执⾏的次数越多,它的速度就越快。JDK 9引⼊ 了⼀种新的编译模式AOT(Ahead of Time Compilation),它是直接将字节码编译成机器码,这样就避免了JIT预热等各⽅面的开销。JDK支持分层编译和AOT协作使用。但是 ,AOT 编译器的编译质量是肯定比不上 JIT编译器的。
总结:
Java虚拟机(JVM)是运⾏ Java 字节码的虚拟机。JVM有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,
它们都会给出相同的结果。字节码和不同系统的 JVM 实现是 Java 语⾔“⼀次编译,随处可以运⾏”的关键所在。
JDK 和 JRE
JDK是Java Development Kit,它是功能齐全的Java SDK。它拥有JRE 所拥有的⼀切,还有编译器(javac)和⼯具(如javadoc和jdb)。它能够创建和编译程序。
JRE 是 Java运⾏时环境。它是运⾏已编译 Java 程序所需的所有内容的集合,包括 Java虚拟机(JVM),Java类库,java命令和其他的⼀些基础构件。但是,它不能用于创建新程序。
如果你只是为了运⾏⼀下 Java 程序的话,那么你只需要安装 JRE 就可以了。如果你需要进⾏⼀些 Java 编程⽅面的⼯作,那么你就需要安装JDK了。但是,这不是绝对的。有时,即使您不打算在计算机上进⾏任何Java开发,仍然需要安装JDK。例如,如果要使用JSP部署Web应用程序,那么从技术上讲,您只是在应用程序服务器中运⾏Java程序。那你为什么需要JDK呢?因为应用程序服务器会将 JSP 转换为 Java servlet,并且需要使用 JDK 来编译 servlet。
静态⽅法和实例⽅法有何不同?
在外部调用静态⽅法时,可以使用”类名.⽅法名”的⽅式,也可以使用”对象名.⽅法名”的⽅式。⽽实例⽅法只有后面这种⽅式。也就是说,调用静态⽅法可以⽆需创建对象。
静态⽅法在访问本类的成员时,只允许访问静态成员(即静态成员变 量和静态⽅法),⽽不允许访问实例成员变量和实例⽅法;实例⽅法则⽆此限制