Java面试宝典-java基础01
- 1、java的跨平台性
- 2、Java是如何实现跨平台性的?
- 3、JDK 和 JRE 有什么区别?
- 4、为何要配置Java环境变量?
- 5、Java都有哪些特性?
- 6、== 和 equals 的区别是什么?
- 7、Java中有哪些数学函数?
- 8、Java中有哪些位运算符?
- 9、说说运算符的优先级
- 10、final 在 java 中有什么作用?
1、java的跨平台性
java跨平台性的优势主要体现在以下几个方面:
真正的平台无关性:Java程序可以在各种操作系统上运行,包括Windows、Linux、Mac等,无需为每个平台编写特定的版本,大大简化了软件开发和维护的工作量。
提高开发效率:开发人员可以专注于编写业务逻辑,而不必关心底层的操作系统细节,减少了学习和切换不同平台的成本。
降低成本和风险:企业可以在不同的操作系统上部署相同的应用程序,无需为每个平台购买和维护独立的硬件和软件,降低了硬件和软件的成本,同时减少了因为平台差异引起的风险。
2、Java是如何实现跨平台性的?
Java实现跨平台性的关键在于JVM虚拟机,Java语言编写的程序会被编译成与平台无关的字节码文件,这些字节码文件可以在任何装有Java虚拟机的系统上运行,因为Java字节码不针对特定的操作系统或硬件,而是设计成一种中间代码,可以在不同平台上被解释执行。
JVM是Java跨平台的核心组件。它作为一个运行时环境,负责加载字节码并将其解释或编译为特定平台的机器代码。每个操作系统都有其专用的JVM实现,例如Windows、Linux和macOS等。
Java源码只需编译一次,将java文件编译成class文件,就可以通过安装在Windows或Linux中的JVM中运行。
3、JDK 和 JRE 有什么区别?
JDK是Java开发工具包,它包含了JRE和开发工具(如javac编译器和java程序运行工具等),主要用于Java程序的开发。而JRE是Java运行环境,它只包含了运行Java程序所必须的环境,主要用于Java程序的运行。
JDK面向的是Java开发者,提供了Java开发工具,如编译工具(javac)和打包工具(jar)等,方便开发者进行Java程序的开发和调试。而JRE面向的是Java程序的使用者,只要安装了JRE,就可以在对应的操作系统上运行Java程序。
JDK由JRE和Java开发工具组成,包含了Java语言所必须的类库和Java虚拟机(JVM),以及编译器和调试器等开发工具。而JRE只包含Java虚 拟机(JVM)和Java语言所必须的类库,这些类库对于开发来说是足够的,但对于开发过程中的编译和调试并不足够。
4、为何要配置Java环境变量?
path环境变量的作用就是告诉系统,当要求系统运行一个程序而没有告诉它程序所在的完整路径时,系统除了在当前目录下面寻找此程序外,还应到哪些目录下去寻找。而我们通常情况下配置的path变量,就是这个目录的完整路径。
简而言之,就是运行某个命令需要某些参数时,如果当前目录下找不到,则自动去环境变量中寻找。
5、Java都有哪些特性?
这是一道没有标准回答的面试题,按照下面的内容陈列即可,回答是切记刻板背诵。
(1)面向对象
Java是一个面向对象的语言,万物皆对象。
面向对象是一种程序设计规范,其基本思想是使用对象、类、继承、封装、多态等基本概念来进行程序设计。从现实世界中客观存在的事物
(即对象)出发来构造软件系统,并且在系统构造中尽可能运用人类的自然思维方式。
程序就是由无数个对象+对象的行为组装而成,当程序请求某个对象时,实际上就是通过一个请求,将“你自己的对象”传递给程序,程序经过一系列匪夷所思的操作,再将一个新的对象返给你。
从底层角度而言,每一个对象都是由其它对象组成的,只是它们的维度、粒度不同而已。
每一个对象都有不同的属性。
比如芯片+电路板组成了内存,内存+硬盘+cpu+机箱组成了电脑,芯片、电路板、内存、硬盘、CPU、机箱、电脑,都是一个对象,只不过粒度不同罢了。
对象具有属性、方法,在内存中的地址都是唯一的。
(2)分布式
分布式系统对于用户而言,他们面对的就是一个服务器,提供用户需要的服务而已,而实际上这些服务是通过背后的众多服务器组成的一个
分布式系统,因此分布式系统看起来像是一个超级计算机一样。
(3)健壮性
为了获得可靠性,Java在一些关键领域进行了限制,从而迫使程序员在程序开发中及早地发现错误。
因为Java是强类型化的语言,它在编译时检查代码。当然不管怎样,在运行时也检查代码。许多难以跟踪的bug,在运行时通 常难以再现,这种情况在Java中几乎不可能产生。因为使编写好的程序在不同的运行条件下,以可预见的方式运行是Java的关键特性之一。在传统的编程环境中,内存管理是一件困难、乏味的工作。例如,在C/C++中,程序员必须手动分配和释放所有动态内存。Java通过为您管理内存的分配和释放,可以从根本上消除这些问题(事实上,释放内存完全是自动的,因为Java为不再使用的对象提供了垃圾回收功能)。
(4)安全性
Java取消了强大但又危险的指针,而代之以引用。由于指针可进行移动运算,指针可随便指向一个内存区域,而不管这个区域是否可用,这样做是危险的,因为原来这个内存地址可能存储着重要数据或者是其他程序运行所占用的,并且使用指针也容易数组越界。
垃圾回收机制:不需要程序员直接控制内存回收,由垃圾回收器在后台自动回收不再使用的内存。避免程序忘记及时回收,导致内存泄露。
避免程序错误回收程序核心类库的内存,导致系统崩溃。
异常处理机制:Java异常机制主要依赖于try、catch、finally、throw、throws五个关键字。
强制类型转换:只有在满足强制转换规则的情况下才能强转成功。
Java在字节码的传输过程中使用了公开密钥加密机制(PKC)。在运行环境提供了四级安全性保障机制:字节码校验器 -类装载器 -运行时内存布局 -文件访问限制。
(5)体系结构中立
编译器生成一个体系结构中立的目标文件格式,这是一种编译过的代码,只要有Java运行时系统,就可以在许多处理器上运行。Java编译器通过生成与特定的计算机体系结构无关的字节码指令来实现这一特性。精心设计的字节码不仅可以很容易地在任何机器上解释执行,而且还可以迅速地翻译成本地机器的代码。字节码实现了结构中立,与计算机结构无关。
(6)可移植性
Java语言之中最大的特点在于其可移植性的支持,所谓的可移植性指的是同一个程序可以在不同的操作系统之间任意的进行部署,这样就减少了开发的难度,在Java里面如果要想实现可移植性的控制,那么主要依靠的是JVM(Java 虚拟机)。Java虚拟机是一个由软件和硬件模拟出来的计算机,所有的程序只要有Java虚拟机的支持,那么就可以实现程序的执行,并且不同的操作系统上会有不同版本的JVM存在,这样
就可以实现移植性。
(7)解释性
有人说Java是编译型的。因为所有的Java代码都是要编译的,.java不经过编译就无法执行。 也有人说Java是解释型的。因为java代码编译后不能直接运行,它是解释运行在JVM上的,所以它是解释型的。
(8)高性能
即时编译器可以监控经常执行哪些代码并优化这些代码以提高速度。更为复杂的优化是消除函数调用(即内联)。即时编译器知道哪些类已经被加载。基于当前加载的类集,如果特定的函数不会被覆盖,就可以使用内联。必要时,还可以撤销优化。
(9)多线程
指的是这个程序(一个进程)运行时产生了不止一个线程。
(10)动态性
Java本质为静态语言,而不是动态语言。动态语言显著的特点是在程序运行时,可以改变程序结构或变量类型,典型的动态语言有Python、ruby、javascript等。Java不是动态语言,但Java具有一定的动态性,表现在以下几个方面:
- 反射机制;
- 动态字节码操作;
- 动态编译;
- 执行其他脚本代码;
6、== 和 equals 的区别是什么?
(1)类型与定义
"== " 是一个操作符,用于比较两个变量的值。对于基本数据类型,它比较的是变量存储的值是否相等;对于引用类型,它比较的是两个引用是否指向内存中的同一地址(即是否是同一个对象的引用)。
equals()是Object类中的一个方法,用于比较两个对象的内容是否相等。默认情况下,它比较的是对象的内存地址(即是否是同一个对象),但该方法可以被重写以提供自定义的比较逻辑。
(2)运行速度
"== “:由于只是比较引用或内存地址,所以通常比equals()方法更快。
equals():由于可能需要执行更复杂的比较逻辑(尤其是在被重写的情况下),因此其运行速度可能慢于”== "。
(3)可重写性
"== ":不可重写,其行为是固定的。
equals():可以被重写以提供自定义的相等性判断逻辑。
下面程序的输出结果是什么?
public static void main(String[] args) {
Integer a = 0;
Integer b = 3;
Integer c = 4;
Integer d = 4;
Integer e = 321;
Integer f = 321;
Long g = 4L;
Long h = 3L;
System.out.println(c==d);//true
System.out.println(e==f);//false
System.out.println(c==(a+b));//true
System.out.println(c.equals(a+b));//true
System.out.println(g==(a+b));//true
System.out.println(g.equals(a+b));//false
System.out.println(g.equals(a+h));//true
}
当 "=="运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的程)。另外,对于包装器类型,equals方法并不会进行类型转换。
第一个和第二个输出结果没有什么疑问。第三句由于 a+b包含了算术运算,因此会触发自动拆箱过程(会调用intValue方法),因此它们比较的是数值是否相等。而对于c.equals(a+b)会先触发自动拆箱过程,再触发自动装箱过程,也就是说a+b,会先各自调用intValue方法,得到了加法运算后的数值之后,便调用Integer.valueOf方法,再进行equals比较。同理对于后面的也是这样,不过要注意倒数第二个和最后一个输出的结果(如果数值是int类型的,装箱过程调用的是Integer.valueOf;如果是long类型的,装箱调用的Long.valueOf方法)。
7、Java中有哪些数学函数?
Java中提供了一些数学函数,位于java.lang.Math类中。这些函数包括以下几种:
基本数学函数:abs、max、min。
指数函数:exp、log、pow。
三角函数:sin、cos、tan、asin、acos、atan。
双曲函数:sinh、cosh、tanh、asinh、acosh、atanh。
随机数函数:random。
8、Java中有哪些位运算符?
(1)与运算符 &
只有两个位都是1,结果才是1
public static void main(String[] args) {
int x = 129;
int y = 128;
System.out.println("x 和y 与的结果是:"+(x&y)); // 128
}
x 二进制 10000001;
y 二进制 10000000;
根据与运算符的运算规律,只有两个位都是1,结果才是1,可以知道结果就是10000000,即128。
(2)或运算符 |
两个位只要有一个为1,那么结果就是1,否则就为0。
public static void main(String[] args) {
int x = 129;
int y = 128;
System.out.println("x 和y 或的结果是:"+(x|y)); // 129
}
(3)非运算符 ~
如果位为0,结果是1,如果位为1,结果是0。
(4)异或运算符 ^
两个操作数的位中,相同则结果为0,不同则结果为1。
(5)左移运算符<<、右移运算符>>
移位运算符的右操作数要完成模32的运算。 1<<35的值等同于1<<3或8。
public static void main(String[] args) {
System.out.println(1 <<35);//8
System.out.println(1<<3);//8
}
(6)>>>运算符会用0填充高位,不存在<<<运算符。
9、说说运算符的优先级
这道题属实有点变态,这谁能记得住,运算符优先级只是一种约定,实际使用时应根据具体情况加上括号以明确运算顺序。
Java中的运算符按照优先级从高到低依次为:
- ():括号运算符,具有最高优先级;
- !、~、++、–:逻辑非、位取反、自增、自减运算符;
- *、/、%:乘、除、取模运算符,优先级相同,从左向右结合;
- +、-:加、减运算符,优先级相同,从左向右结合;
- <<、>>、>>>:左移、右移、无符号右移运算符,优先级相同,从左向右结合;
- <、<=、>、>=:小于、小于等于、大于、大于等于运算符,优先级相同,从左向右结合;
- ==、!=:等于、不等于运算符,优先级相同,从左向右结合;
- &:按位与运算符,优先级较低;
- ^:按位异或运算符,优先级更低;
- |:按位或运算符,优先级最低;
- &&:逻辑与运算符,优先级较低;
- ||:逻辑或运算符,优先级更低;
- ?::三元条件运算符,优先级最低;
10、final 在 java 中有什么作用?
(1)用来修饰一个引用
如果引用为基本数据类型,则该引用为常量,该值无法修改;
如果引用为引用数据类型,比如对象、数组,则该对象、数组本身可以修改,但指向该对象或数组的地址的引用不能修改。
如果引用时类的成员变量,则必须当场赋值,否则编译会报错。
(2)用来修饰一个方法
当使用final修饰方法时,这个方法将成为最终方法,无法被子类重写。但是,该方法仍然可以被继承。
(3)用来修饰类
当用final修改类时,该类成为最终类,无法被继承。 比如常用的String类就是最终类。