Java面试之道,让你轻松拿offer
Posted 扣丁学堂
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java面试之道,让你轻松拿offer相关的知识,希望对你有一定的参考价值。
本篇文章将讲述Java基础中的面试题及其解答,希望对大家有所帮助。
synchronized和Lock的区别
synchronized是JVM层面实现的,java提供的关键字,Lock是API层面的锁。
synchronized不需要手动释放锁,底层会自动释放;Lock则需要手动释放锁,否则有可能导致死锁。
synchronized等待不可中断,除非抛出异常或者执行完成;Lock可以中断,通过interrupt()可中断。
synchronized是非公平锁;Lock是默认非公平锁,当传入true时是公平锁。
synchronized不可绑定多个条件;Lock可实现分组唤醒需要唤醒的锁。
"=="和equals方法的区别
&和&&的区别
&和&&都可以用作逻辑与的运算符,当运算符两边的表达式的结果都为true时,整个运算结果才为true,否则,只要有一方为false,则结果为false。
&&还具有短路的功能,即如果第一个表达式为false,则不再计算第二个表达式,直接得出结果为false。
&还可以用作位运算符,当&操作符两边的表达式不是boolean类型时,&表示按位与操作,我们通常使用0x0f来与一个整数进行&运算,来获取该整数的最低4个bit位。
什么是可变参数
可变参数表示需要接收的参数个数可以不确定,例如:
public void show(int... nums){
}
此时该方法可以接收任意个int类型的参数。
想要获得所有参数,就可以对nums进行遍历,此时的nums为参数数组。
final,finally,finalize的区别
final,意为最终的,用于修饰类,方法和变量。
如果一个类被final修饰,意味着这个类为最终类,它将不能再派生出新的子类,不能被继承,否则出错,因此在声明类时,final和abstract无法同时出现,因为abstract修饰的类必定要有具体的子类实现,而final不允许子类的继承,此时陷入矛盾。
如果一个变量被final修饰,则它在程序中将不能被修改,而且必须在声明变量时就赋值。
如果一个方法被final修饰,它将无法被子类重写。
finally,是异常处理中的关键字,它表示无论异常是否被捕获,程序都将执行finally中的代码块。
finalize,是Object中的方法,它的目的是保证对象在被垃圾收集前完成特定资源的回收,而事实上,这个方法具有不确定性,它并不能保证你在调用了该方法之后就会完成资源回收。
String s = new String(“abc”);创建了几个String 对象
创建了两个,第一个:“abc”,这种方式称为显式声明字符串,会在常量池中创建一个对象;第二个:new关键字会在堆中创建指向常量池字符串的引用。所以一共创建了两个String对象。
GC是什么?为什么要有GC
GC是垃圾收集的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显式操作方法。Java程序员不用担心内存管理,因为垃圾收集器会自动进行管理。
要请求垃圾收集,可以调用下面的方法:System.gc() 或Runtime.getRuntime().gc() ,但JVM可以屏蔽掉显式的垃圾回收调用。
垃圾回收可以有效的防止内存泄露,有效地使用的内存。垃圾回收器通常是作为一个单独的低优先级的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时地调用垃圾回收器对某个对象或所有对象进行垃圾回收。
length()和length的区别
Java中的length属性是针对数组来说的,假设声明一个数组,则可以通过length属性直接获得数组的长度。
Java中的length()方法是针对字符串String的,如果想得到字符串长度,则可以使用length()方法。
Java 创建对象的几种方式
通过new关键字
通过反射
采用clone
通过序列化
throw和throws的区别
throw用于主动抛出java.lang.Throwable 类的一个实例化对象,意思是说你可以通过关键字 throw 抛出一个 Error 或者 一个Exception,如:throw new IllegalArgumentException(“″), 而throws 的作用是作为方法声明和签名的一部分,方法被抛出相应的异常以便调用者能处理。Java 中,任何未处理的受检查异常强制在 throws 子句中声明。
char型变量中能不能存贮一个中文汉字
char型变量是用来存储Unicode编码字符的,Unicode编码字符集中包含了汉字,所以,char型变量可以用于存储中文汉字。不过,如果某个特殊的汉字没有被包含在Unicode编码字符集中,那么,这个char型变量中就不能存储这个特殊汉字。
switch语句中的表达式能否使用byte类型、short类型、long类型、String类型
在switch中,例如switch(x),表达式x规定只能是一个整数表达式或者枚举类型,这里的整数表达式可以是int类型,也可以是Integer类型,而byte、short都可以隐式转换为int,所以可以使用,那么很显然,由于long无法隐式转换为int,所以long类型无法作用在switch语句中。从Java7开始,switch语句支持字符串作为表达式。
Integer与int的区别
int是Java提供的8种原始数据类型之一。Java为每个原始类型都提供了封装类,Integer即为int的封装类。int的默认值为0,而Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况。
例如,要想表达出没有参加考试和考试成绩为0的区别,则只能使用Integer。在JSP开发中,Integer的默认为null,所以用el表达式在文本框中显示时,值为空白字符串,而int默认的默认值为0,所以用el表达式在文本框中显示时,结果为0,所以,在web开发中的POJO中,你会发现int类型基本不会出现,int类型不适合作为web开发的数据展示。
http协议和https协议的区别
HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。
HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。
区别:
https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
环境变量path和classpath的作用分别是什么
path是配置Windows可执行文件的搜索路径,即扩展名为.exe的程序文件所在的目录,用于指定DOS窗口命令的路径。
Classpath是配置class文件所在的目录,用于指定类搜索路径,JVM就是通过它来寻找该类的class类文件的。
float f=1.1;是否正确
答案是错误,在Java中浮点数默认为double类型,所以这里的1.1其实是double类型,将double类型赋值给float类型会造成精度丢失,所以必须强制类型转换才行,否则报错。
List的三个子类的特点
ArrayList 底层结构是数组,底层查询快,增删慢。
LinkedList 底层结构是链表,增删快,查询慢。
Voctor 底层结构是数组,线程安全的,增删慢,查询慢。
静态变量和实例变量的区别
静态变量属于类,实例变量依存于某一实例。
静态变量:是被static修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,一个类不管创建多少个对象,静态变量在内存中有且仅有一个拷贝。
实例变量:必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。静态变量可以实现让多个对象共享内存。
如何理解线程的优先级
在Java中,每个线程都有相应的优先级,如果没有手动设置,则程序会有一个默认的线程优先级。一般来说,高优先级的线程在运行时会具有优先权,但这依赖于线程调度的实现,这个实现是和操作系统相关的。
我们可以定义线程的优先级,但是这并不能保证高优先级的线程会在低优先级的线程前执行。线程优先级是一个int变量(从1-10),1代表最低优先级,10代表最高优先级。
String类可以被继承吗
String类无法被继承,因为String类被final关键字修饰。
为什么要将String设计为无法被继承
因为只有当字符串是不可变的,字符串池才有可能实现。字符串池的实现可以在运行时节约很多堆空间,因为不同的字符串变量都指向池中的同一个字符串。但如果字符串是可变的,那么字符串驻留将不能实现,因为这样的话,如果变量改变了它的值,那么其它指向这个值的变量的值也会一起改变。如果字符串是可变的,那么会引起很严重的安全问题。
譬如,数据库的用户名、密码都是以字符串的形式传入来获得数据库的连接,或者在socket编程中,主机名和端口都是以字符串的形式传入。因为字符串是不可变的,所以它的值是不可改变的,否则黑客们可以钻到空子,改变字符串指向的对象的值,造成安全漏洞。
因为字符串是不可变的,所以是多线程安全的,同一个字符串实例可以被多个线程共享。这样便不用因为线程安全问题而使用同步。字符串自己便是线程安全的。
如何跳出当前的多重嵌套循环
在最外成循环前加一个标记,然后在需要跳出循环的地方编写break + 标记 即可跳出多重循环,例如:
public static void main(String[] args){
x:for(int i = 0;i < 3;i++){
for(int j = 0;j < 3;j++){
for(int k = 0;k < 3;k++){
break x;
}
}
}
}
break和continue的区别
break和continue 都是用来控制循环的语句。
break 用于完全结束一个循环,跳出循环体执行循环后面的语句。
String s = “Hello”;s = s + " world!";这两行代码执行后,原始的 String 对象中的内容有没有被改变
前面就已经说过了,String是被final修饰的,是无法修改的,那么输出s的内容为什么又是Helloworld!呢?是因为此时的s已经不再指向原始的字符串了,它指向了新拼接的字符串Helloworld!,而原始的字符串Hello其实并没有被改变。
同步和异步有什么区别
如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。
当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。
static方法内部可以调用非static方法吗
这是绝对不可以的,因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用时不需要创建对象,可以直接调用。
也就是说,当一个static方法被调用时,可能还没有创建任何实例对象,如果从一个static方法中发出对非static方法的调用,那个非static方法无法知晓它将关联的对象是哪个,所以不能。
使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变
使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的。
List、Map、Set三个接口存取元素时,各有什么特点
List以特定索引来存取元素,可以有重复元素。Set不能存放重复元素(用对象的equals()方法来区分元素是否重复)。
Map保存键值对映射,映射关系可以是一对一或多对一。
Set和Map容器都有基于哈希存储和排序树的两种实现版本,基于哈希存储的版本理论存取时间复杂度为O(1),而基于排序树版本的实现在插入或删除元素时会按照元素或元素的键(key)构成排序树从而达到排序和去重的效果。
编译时异常和运行时异常的区别
编译时异常在函数内被抛出,函数必须声明,否则编译失败。
声明的原因:是需要调用者对该异常进行处理。必须进行处理,否则无法编译通过。
运行时异常如果在函数内被抛出,在函数上不需要声明。
不声明的原因:不需要调用者处理,运行时异常发生,已经无法再让程序继续运行,所以,不让调用处理的,直接让程序停止,由调用者对代码进行修正。
wait( )和sleep( )的区别
sleep( )没有释放同步锁,而wait( )释放了同步锁。
sleep( )必须制定时间,而wait( )不用。
sleep()可以在任何地方使用,而wait( )、notify( )、notifyAll( )只能在同步方法或同步代码块中使用。
sleep()必须捕获异常,而wait( )、notify( )、notifyAll( )不用。
Java中如何实现序列化,有什么意义?
序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决对象流读写操作时可能引发的问题(如果不进行序列化可能会存在数据乱序的问题)。
要实现序列化,需要让一个类实现Serializable接口,该接口是一个标识性接口,标注该类对象是可被序列化的,然后使用一个输出流来构造一个对象输出流并通过
writeObject(Object)方法就可以将实现对象写出(即保存其状态);如果需要反序列化则可以用一个输入流建立对象输入流,然后通过readObject方法从流中读取对象。
例如,在web开发中,如果对象被保存在了Session中,tomcat在重启时要把Session对象序列化到硬盘,这个对象就必须实现Serializable接口。如果对象要经过分布式系统进行网络传输或通过rmi等远程调用,这就需要在网络上传输对象,被传输的对象就必须实现Serializable接口。
想要提升自己的小伙伴可以关注扣丁学堂,扣丁学堂是专业的IT培训机构,不论是入门、精通、提升、项目实战都有专业的老师,在你职业发展的道路中,扣丁学堂是你最好的朋友!
本文转自网络,如有侵权及时联系
想要 专 属 福 利 ,来找CoCo酱
微信ID:cocojiang525
以上是关于Java面试之道,让你轻松拿offer的主要内容,如果未能解决你的问题,请参考以下文章