JAVA基础知识(一)
-
1.JDK、JRE、JVM三者的区别?
JDK即java development kit是提供给开发人员使用的,其中包含了Java的开发工具以及JRE。
JRE即java runtime environment包括了java虚拟机和java程序所需要的核心类库。如过需要运行开发完成的Java程序,计算机中只需要安装jre即可。
JVM即Java virtual machine是java虚拟机,java程序需要在虚拟机上运行,不同的平台有不同的虚拟机,因此java可以实现跨平台。
-
2.java的跨平台性以及实现的原理是什么?
所谓的java跨平台型就是Java语言所编写的程序,一次编译后,可以在多个部署java环境的系统中运行。
java程序的运行是在Java虚拟机中运行的,只要该系统配置Java的环境,该系统就可以运行Java程序。
-
3.什么是字节码?采用字节码最大的好处是什么?
字节码即JAVA源代码经过javac编译后生成的class文件,而在java虚拟机中运行的就是字节码文件。
java采用字节码可以实现一次编程到处运行,也就是java的跨平台性。
java语言通过字节码的方式,在一定程度上解决类传统解释型语言执行效率低的问题,同时还保留了解释型语言可移植性的特点,因此java程序在运行时比较高效,而且字节码并不专对某一种特定的机器,所有java程序无需重新编译即可在多种不同系统平台上运行。
拓展:
什么是虚拟机?虚拟机的作用是什么?
虚拟机指通过软件模拟的具有完整系统功能的、能够独立运行在一个隔离环境中的计算机系统。虚拟机还分为系统虚拟机以及进程虚拟机。具体的介绍在《虚拟机:系统与进程的通用平台》一书中有详细的介绍。
解释型语言和编译型语言
编译型语言:需要通过编译器将源代码编译成机器码才能够执行的语言。一般是通过编译和链接两个步骤,编译是将程序编译成机器码,链接是将程序和依赖库等串联起来。例如C/C++、pascal、object-c、swift、go等就是编译型语言。
优点:编译器一般会有预编译的过程对代码进行优化,因为编译只做一次,运行时不会在编译,所以编译型语言效率高。
缺点:编译之后如果想要修改某一个功能,就需要将整个模块重新编译。编译的时候根据对应的运行环境生成不同的机器码。不同的操作系统之间,可能会出现问题。需要根据不同的运行环境生成不同的可执行文件。
解释型语言:解释型语言不需要编译,解析型语言在运行程序的时候才逐行翻译。字节码也是解释型语言的一部分。例如javaScript、python、php等都是解释型语言。
优点:有良好的平台兼容性,只要安装了虚拟机,就可以运行。维护比较容易,部署也比较方便。不用停机维护。
缺点:每次运行的时候都要解释一遍,性能上不如编译型语言。
Java 编译与解释共存
java通过javac将java源文件编译称class文件,jvm将class文件解释称二进制机器码。从class文件到二进制机器码,jvm类加载器首先加载字节码文件,然后通过解释器逐行解释执行,这种方式的执行速度相对比较慢,而且有些方法和代码块是经常被调用的。之后引进jit编译器,jit属于运行时编译,当jit编译完成第一次编译后,会将字节码对应的机器码保存下来,而我们知道机器码的运行效率是高于java解释器高的。
-
4.java与C++的区别
java不提供指针来直接访问内存,程序内存更安全。java的类是单继承的,c++的类支持多重继承;虽然java的类不支持多继承,但可以实现多个接口。java有自动内存管理机制,不需要程序员手动释放无用内存。
-
5.Oracle JDK和Open JDK的对比
Oracle jdk版本是每三年发布一次,而Open jdk每三个月发布一次。
Open Jdk是一个参考模型并且是完全开源的,而Oracle jdk是Open jdk的一个实现,并不是全部开源的。
Oracle jdk比Open jdk更稳定。Open jdk和Oracle jdk的代码几乎相同,但Oracle jdk有更多的类和一些错误修复。因此,如果开发企业/商业型软件最好使用Oracle jdk,因为Oracle jdk经彻底的测试,较为稳定。
在响应性和JVM性能上,Oracle jdk与Open jdk相比,提供类更好的性能。
-
6.面向对象的特征
封装、继承、多态,有时还会加上抽象
-
7.多态的好处
允许不同类对象对同一消息做出响应,即同一消息可以根据不同的发送对象采用不同的行为方式,主要有以下特点:
可替换性:多态对已存在的代码具有可替换性。
可扩充性:增加新的子类不影响已经存在的类结构。
接口性:多态是超类通过方法签名向子类提供一个公共接口,由子类重写完善。
-
8.接口的意义
规范、扩展以及回调
-
9.抽象类的意义
为其他的子类提供一个公共的类型。封装子类中重复定义的内容。定义抽象方法。
-
10.抽象类与接口的区别
子类使用extends关键字来继承抽象类,如果子类不是抽象类,子类需要提供抽象类中所声明的方法。子类使用implements来实现接口,需要提供接口中所有声明的实现。
抽象类方法可以使用public、protect等修饰,接口默认是public,不能使用其他修饰符。
添加新方法时抽象类可以默认实现该方法,因此可以不修改子类的代码。接口添加新方法,则子类需要实现该方法。
一个子类只能继承一个抽象类,一个子类可以存在多个接口。
-
11.静态变量和实例变量的区别
静态变量存储在方法区,属于类所有。实例变量存储在堆中,器引用当前线程栈。从jdk1.8开始用于实现方法区的PermSpace由MetaSpace取代了。
拓展:
jvm的内存分区
jvm从逻辑上把内存分为5个区域即方法区、堆、虚拟机栈、本地方法栈、程序计数器。其中方法区和堆是线程共享区域,其他三个区域为线程隔离区域。
一、方法区
jvm方法区是用于保存已经被虚拟机价值的类元信息(包括类的版本、字段、方法、接口和父类等信息)、运行时的常量信息(static、final定义的常量)、字符串常量信息(String a = "abc")。
1.方法区、永久代、元数据区的关系
方法区是jvm定义的一种规范,是所有java虚拟机都需要遵循的规范。而永久代(PermGen space)和元数据(MetaSpace)都是实际某个虚拟机针对方法区的实现。永久代是jdk1.7之前hotspot虚拟机对方法区的实现,而元数据是jdk1.8之后hotspot虚拟机对方法区的实现。
2.PermGen space和MetaSpace的区别?
不管是PermGen space还是MetaSpace他们都是Hotspot针对方法区的一种实现,两者最大的区别在于PermGen space在jvm虚拟机中分配内存,而MetaSpace则是分配本地内存。
因为在很多类是在运行期间加载的,这部分加载的空间不可控,如果这部分内存是在JVM内存里分配的话,永久代分配太大,那么JVM其他区域(比如堆)的内存就会变小,反之如果设置太小,就容易出现方法区内存溢出,因为本身存储的类信息属于不确定大小,类信息在我们运行的时候可以动态加载。所以jdk1.8中选择把MetaSpace内存分配在本地内存,这样做的好处是MetaSpace空间的大小不会受限于虚拟机分配的内存大小,只会首先于机器内存,可分配的内存大了那么就不那么容易出现内存溢出。
3.字符串常量、静态常量数据存放区域
java6中所有常量池数据存放在永久代中,但到java7后hotspot把永久代中的字符串常量、静态变量数据迁移到了堆中,后面的java8并没有对这部分内容进行迁移,在java8中字符串常量、静态变量数据还是放在堆中,所以常量池只是在jvm规范定义上属于方法区,但hotspot在实现的时候部分常量池的内容实际上是保存在堆中。
二、虚拟机栈
栈这部分区域主要是用于线程运行方法的区域,此区域属于线程私有的空间,每一个线程创建后都会申请一个自己单独的栈空间,每一个方法区的调用都会对应着一个栈帧。
栈帧里存储着方法的局部变量表(保存着变量的数据)、操作数栈(进行运算时存放数据的空间)、动态连接(指向常量池的引用)和方法返回地址(当前方法返回后的数据存放的地方)信息。
每调用一个方法都会生成一个新栈,调用方法的过程就是一个压栈和出栈的过程,遵循先进后出的原则。
三、本地方法栈
由于java需要与一些底层系统如操作系统或某些硬件交换信息,这个时候就需要通过调用native本地方法来实现,本地方法栈和虚拟机栈功能差不多,区别在于本地方法是虚拟机调用native方法时使用。
四、程序计数器
程序计数器是一个较小的内存空间,它的作用可以看作是当前线程所执行的字节码的行号指示器,程序计数器记录着某个线程当前执行指令的位置,此区域属于线程隔离区。
因为cpu是根据记录某个线程当前执行指令的位置,此区域属于线程隔离区。
因为cpu是根据时间片的方式分配资源的,它在某一个线程上进行调度的时间是一个或者多个时间片,所以当cpu从线程A切换到线程B执行时,就需要记录A线程当前指令的位置,方便cpu再次切回A线程时可以从上次位置继续执行指令,而程序计数器就是用了记录线程指令历史位置的区域。
五、堆
堆内存主要是用于存放创建的对象数据,此区域是属于线程共享区域,对于开发人员来说这块区域是我们关注比较多的地方,因为很多优化都是针对这块区域进行的,为了能更清楚的描述堆里的数据和分区信息,所以会结合垃圾回收的一些机制来描述此区域。
本文来自博客园,作者:jkbolck,转载请注明原文链接:https://www.cnblogs.com/lwjblogs/p/15723887.html