什么是字节码?采用字节码的好处是什么?
在Java中,JVM可以理解的代码就叫做字节码,就是.class文件,不面向任何特定的处理器,只面向虚拟机。
通过字节码的方式,在一定程度上解决了传统解释型语言执行效率低的问题,同时又保留了解释型语言可移植的特点,所以Java程序运行时相对高效;而且字节码不针对一种特定的机器,Java程序无需重新编译就可以在多种不同操作系统的计算机上运行。
JDK(JRE(JVM(JIT)))
为什么说Java语言“编译与解释并存”?
因为Java语言既具有编译型语言的特征,也具有解释型语言的特征。Java程序要经过“先编译,后解释”这两个步骤,先编译生成字节码文件,然后必须由Java解释器来解释执行。
AOT有什么优点?
JDK9引入的AOT,与JIT不同的是,这种编译模式会在程序被执行前就将其翻译成机器码,属于静态编译(C、C++、Go也是静态编译)。AOT避免了JIT预热等方面的开销,提高了Java程序的启动速度,避免预热时间长;还能减少内存占用和增强Java程序的安全性(AOT编译后的代码不容易被反编译和修改)。
优势:
AOT:启动时间、内存占用、打包体积。
JIT:具备更高的极限处理能力,可以降低请求的最大延迟。
为什么不全部使用AOT呢?
AOT 编译无法支持 Java 的一些动态特性,如反 射、动态代理、动态加载、JNI(Java Native Interface)等。但是,很多框架和库(如 Spring、CGLIB)都用到了这些特性。如果只使用 AOT 编译,那就没办法使用这些框架和库 了,或者说需要针对性地去做适配和优化。
举个例子,CGLIB 动态代理使用的是 ASM 技 术,而这种技术大致原理是运行时直接在内存中生成并加载修改后的字节码文件也就是.class文件,如果全部使用 AOT 提前编译,也就不能使用 ASM 技术了。为了支持类似的 动态特性,所以选择使用 JIT 即时编译器。
Java和C++的区别?
虽然他们都是面向对象的语言,都支持封装、继承、多态,都是还有不同的地方:
Java不提供指针来访问内存,程序内存更安全;
Java的类是单继承的,C++支持多重继承;Java的接口可以多继承;
Java有自动内存管理垃圾回收机制(GC),不需要程序员手动释放内存;
C++支持方法重载、操作符重载,Java只支持方法重载(操作符重载增加了复杂性,与Java最初的设计思想不符)。
基本语法
注释有几种形式?
单行注释、多行注释、文档注释(用于生成Java开发文档)。
标识符和关键字的区别?
标识符就是为程序、类、方法、变量取的名字;
关键字就是被赋予特殊意义的标识符。
Java关键字有哪些?
private、protected、public、abstract、class、extend....
break、continue和return的区别是什么?
continue:跳出当前这一次循环,继续下一次循环
break:跳出整个循环体,继续执行循环下面的语句
return:跳出所在方法,结束该方法的运行
基本数据类型
Java中的几种基本数据类型了解么?
一共8种;
6种数字类型:4种整数型byte(8)、short(16)、int(32)、long(64);两种浮点型:float(32)、double(64)
一种字符类型:char(16)
一种布尔型:boolean(1)
基本类型和包装类型的区别?
用途:除了定义一些常量和局部变量之外,在其他地方比如方法参数、对象属性中很少会使用基本类型来定义变量。并且包装类型可用于泛型,基本类型不可以。
存储方式:基本类型的局部变量存放在Java虚拟机栈中的局部变量表中,基本类型的成员变量(未被static修饰的)存放在Java虚拟机的堆中。包装类属于对象类型,几乎所有对象实例都存放在堆中。
占用空间:相比于包装类(对象类型),基本数据类型占用的空间往往非常小。
默认值:成员变量包装类型不赋值就是null,基本类型有默认值且不是null。
比较方式:对于基本类型,==比较的是值;对于包装类型,==比较的是对象的内存地址。所有整型包装类对象值之间的比较,全部使用equals()方法。
包装类型的缓存机制了解么?
Java基本数据的包装类型大部分都用到了缓存机制来提升性能。
Byte、Short、Integer、Long这四种包装类默认创建了数值【-128,127】的相应类型的缓存数据,Character创建了数值在【0,127】范围的缓存数据,Boolean直接返回True或False。
如果超出对应范围仍然会创建新的对象,缓存的范围区间的大小只是在性能和资源之间的权衡。
两种浮点数类型的包装类Float、Double没有实现缓存机制。
自动装箱与拆箱了解吗?原理是什么?
装箱:将基本类型用对应的包装类包装起来,原理是调用包装类的ValueOf()方法。
拆箱:将包装类转换为基本数据类型,调用xxxValue()方法。
为什么浮点数运算的时候有精度丢失的风险?
这和计算机保存浮点数的机制有关系,计算机是二进制的,在表示数字时它的宽度是有限的,无限循环的小数存储在计算机时,只能被截断,所以就导致了精度丢失的情况。所以浮点数没办法用二进制精确表示。例如:十进制的0.2没办法转换成二进制(不断×2,直到不存在小数)
如何解决浮点数运算的精度丢失问题?
用BigDecimal可以实现对浮点数的运算,并且不造成精度丢失。通常情况,大部分需要浮点数精确运算结果的业务场景(比如:钱)都是通过BigDecimal做的。
超过long整型的数据应该如何表示?
基本数据类型都有一个表达范围,超出范围就会有数值溢出的风险。Java中64位long整型是最大的整数类型。应该用BIgInteger类来表示,它是Java中提供的一个用于处理任意大整数的类,可以表示任意长度的整数,没有长度限制。