Java 基础常见面试题大全

   日期:2020-07-06     浏览:95    评论:0    
核心提示:原因焦虑。每次去面试更高的职位时候,内心总是担忧着那些面试题怎么解答。很多问题在实际工作中并不会遇到,没有实际的解决问题经验,看过也记不住。让你的Java知识功底更加强悍,后面的框架,微服务也好理解。学习目标收集常见经典的 Java 面试题。做出答案,分享出去,和博友们进行讨论,不断进步。扩大知识图谱,扎实基础,梳理知识脉络。锻炼自己写文章以及排版的能力。避免下次面试找工作的时候抓瞎。Java 常见面试题基础篇:1. JDK 和 JRE 的区别JRE:Java ._java基础面试题

原因

  1. 焦虑。每次去面试更高的职位时候,内心总是担忧着那些面试题怎么解答。
  2. 很多问题在实际工作中并不会遇到,没有实际的解决问题经验,看过也记不住。
  3. 让你的Java知识功底更加强悍,后面的框架,微服务也好理解。

学习目标

  1. 收集常见经典的 Java 面试题。
  2. 做出答案,分享出去,和博友们进行讨论,不断进步。
  3. 扩大知识图谱,扎实基础,梳理知识脉络。
  4. 锻炼自己写文章以及排版的能力。
  5. 避免下次面试找工作的时候抓瞎。

Java 常见面试题

基础篇:

1. JDK 和 JRE 的区别

JRE:Java Runtime Environment(java运行时环境)。即java程序的运行时环境,包含了java虚拟机,java基础类库。

JDK:Java Development Kit(java开发工具包)。即java语言编写的程序所需的开发工具包。JDK包含了JRE,同时还包括java源码的编译器javac、监控工具jconsole、分析工具jvisualvm等。

2. == 和 equals 的区别

==可以使用在基本数据类型和引用数据类型变量中。
如果比较的是基本数据类型变量,比较两个变量保存的数据是否相等(不一定类型要相同)。
如果比较的是引用数据类型变量,比较两个变量的地址值是否相等。即两个引用是否指向同一个对象实体。

equals()只能适用引用数据类型。默认情况下,比较内存地址值是否相等。
Object类中equals的定义:

public boolean equals(Object obj) {
	return (this == obj);
}

通常情况下,我们自定义的类如果使用equals()的话,也通常是比较两个对象的"实体内容"是否相同。
那么我们就需要对Object类中的equals()进行重写。

//手动实现
public boolean equals(Object obj) {
	if (this == obj){
		return true;
	}
	
	if(obj instanceof Customer){
		Customer cust = (Customer)obj;
		//比较两个对象的每个属性是否相同
// if(this.age == cust.age && this.name.equals(cust.name)){
// return true;
// }else{
// return false;
// }

		//或
		return this.age == cust.age && this.name.equals(cust.name);
	}else{
		return false;
	}
}
//自动生成的
右键生成
3. 基本类型和包装类对象使用 == 和 equals进行比较的结果?

1)值不同:使用 = = 和equals() 比较都返回false。

2)值相同:

使用 = = 比较:

  • 基本类型-基本类型、基本类型-包装对象返回true
  • 包装对象-包装对象返回false
  • 缓存中去的包装对象比较返回true(JVM 缓存部分基本类型常用的包装类对象,如 Integer 缓存 -128 ~ 127 )
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i == j);//false

//Integer内部定义了IntegerCache结构,IntegerCache中定义了Integer[],
//保存了从-128到+127范围的整数。如果我们使用自动装箱的方式,
//给Integer赋值的范围在-128到+127范围内时,可以直接使用数组中元素,不用再去new了。

Integer m = 1;
Integer n = 1;
System.out.println(m == n);//true

Integer x = 128;
Integer y = 128;
System.out.println(x == y);//false

使用equals() 比较:

  • 包装对象-基本类型返回true
  • 包装对象-包装对象返回true
//以int和Integer为例:
@Test
public void test1(){
	int i1 = 10000;
    Integer i2 = new Integer(10000);
    Integer i3 = new Integer(10000);
    System.out.println("Integer 基本类型和包装对象使用 == 比较 : " + (i1 == i2));//Integer 基本类型和包装对象使用 == 比较 : true
    System.out.println("Integer 基本类型和包装对象使用 equals 比较 : " + i2.equals(i1));//Integer 基本类型和包装对象使用 equals 比较 : true
    System.out.println("Integer 包装对象和包装对象使用 == 比较 : " + (i2 == i3));//Integer 包装对象和包装对象使用 == 比较 : false
    System.out.println("Integer 包装对象和包装对象使用 equals 比较 : " + i2.equals(i3));//Integer 包装对象和包装对象使用 equals 比较 : true
}
4.什么是自动装箱?什么是自动拆箱?装箱和拆箱的执行过程?

JDK 5.0新特性:自动装箱与自动拆箱
自动装箱:基本数据类型 —> 包装类
自动拆箱:包装类 —> 基本数据类型

int num1=10;
Integer num2=num1;//自动装箱
    
Integer a=10;
int b=a;//自动拆箱

装箱是通过调用包装器类的 valueOf 方法实现的
拆箱是通过调用包装器类的 xxxValue 方法实现的,xxx代表对应的基本数据类型。
如int装箱的时候自动调用Integer的valueOf(int)方法;Integer拆箱的时候自动调用Integer的intValue方法。

5.两个对象hashCode()相同,equals() 也一定为 true吗?

不一定。
类的hashCode方法和equals方法都可以重写,返回的值完全在于自己定义。
hashCode()返回该对象的哈希值;equals()返回两个对象是否相等。

6.final、finally和finalize()区别

final 表示最终的、不可改变的。用于修饰类、方法和变量。
用final修饰的类不能被其他类所继承。
用final修饰的方法不能被重写。
修饰属性:可以考虑赋值的位置有:显式初始化、代码块中初始化、构造器中初始化。
修饰局部变量:尤其是使用final修饰形参时,表明此形参是一个常量。当我们调用此方法时,给常量形参赋一个实参。一旦赋值以后,就只能在方法体内使用此形参,但不能进行重新赋值。

finally 异常处理的一部分,它只能用在try/catch语句中,finally中声明的是一定会被执行的代码。即便catch中又出现异常了,try中有return语句,catch中有return语句等情况。

finalize()是在java.lang.Object里定义的,Object的finalize方法什么都不做,对象被回收时finalized方法会被调用。
特殊情况下,可重写finalize方法,当对象被回收的时候释放一些资源。但注意,要调用super.finalize()。

7.final 与 static 的区别

都可以修饰类、方法、成员变量。

static可以修饰类的代码块,final不可以。
static不可以修饰方法内的局部变量,final可以。

static修饰表示静态或全局,被修饰的属性和方法属于类,可以用类名.静态属性 / 方法名 访问
static修饰的代码块表示静态代码块,当Java虚拟机(JVM)加载类时,就会执行该代码块,只会被执行一次
static静态变量的加载早于对象的创建。
static修饰的属性,也就是类变量,是在类加载时被创建并进行初始化,只会被创建一次。
static修饰的变量可以重新赋值
static方法中不能用this和super关键字
static方法必须被实现,而不能是抽象的abstract
static方法只能被static方法覆盖

final修饰表示常量、一旦创建不可改变。
final标记的成员变量必须在声明的同时赋值,或在该类的构造方法中赋值,不可以重新赋值。
final方法不能被子类重写。
final类不能被继承,没有子类,final类中的方法默认是final的。
final不能用于修饰构造方法。
private类型的方法默认是final类型的。

8.String对象中的replace和replaceAll的区别?

replace方法:支持字符和字符串的替换。
public String replace(char oldChar, char newChar)
public String replace(CharSequence target, CharSequence replacement)

replaceAll方法:基于正则表达式的字符串替换。
public String replaceAll(String regex, String replacement)

代码:

public static void main(String[] args) {
    String str = "Hello Java. Java is a language.";
    System.out.println(str.replace("Java.", "c++"));//打印 Hello c++ Java is a language.
    System.out.println(str.replaceAll("Java.", "c++"));//打印 Hello c++ c++is a language.
}
9.Math.round(-1.5) 等于多少?

结果是:-1。

扩展JDK中的java.lang.Math类
round:返回四舍五入,负.5小数返回较大整数,如-1.5返回-1。
ceil:返回小数所在两整数间的较大值,如-1.5返回-1。
tail:返回小数所在两整数间的较小值,如-1.5返回-2。

代码:

	Math.round(1.4)=1
	Math.round(-1.4)=-1
	Math.round(1.5)=2
	Math.round(-1.5)=-1
	Math.round(1.6)=2
	Math.round(-1.6)=-2
	
	Math.ceil(1.4)=2.0
	Math.ceil(-1.4)=-1.0
	Math.ceil(1.5)=2.0
	Math.ceil(-1.5)=-1.0
	Math.ceil(1.6)=2.0
	Math.ceil(-1.6)=-1.0
	
	Math.floor(1.4)=1.0
	Math.floor(-1.4)=-2.0
	Math.floor(1.5)=1.0
	Math.floor(-1.5)=-2.0
	Math.floor(1.6)=1.0
	Math.floor(-1.6)=-2.0
10.String 属于基础的数据类型吗?

不属于。
Java8种基础的数据类型:byte、short、char、int、long、float、double、boolean。

11.String、StringBuffer和StringBuilder的区别?

String :不可变的字符序列;底层使用char[]存储。
StringBuffer : 可变的字符序列;线程安全的,效率低;底层使用char[]存储。
StringBuilder : 可变的字符序列; jdk5.0新增的,线程不安全的,效率高;底层使用char[]存储。
注意:作为参数传递的话,方法内部String不会改变其值,StringBuffer和StringBuilder会改变其值。

源码分析:
String str = new String();//char[] value = new char[0];
String str1 = new String(“abc”);//char[] value = new char[]{‘a’,‘b’,‘c’};

StringBuffer sb1 = new StringBuffer();//char[] value = new char[16];//底层创建了一个长度是16的数组
System.out.println(sb1.length());//0
sb1.append(‘a’);//value[0] = ‘a’;
sb1.append(‘b’);//value[1] = ‘b’;

StringBuffer sb2 = new StringBuffer(“abc”)/char[] value =new char[“abc”.length() +16];
System.out.println(sb2. Length());//3

扩容问题:如果要添加的数据底层数组盛不下了,那就需要扩容底层的数组。
默认情况下,扩容为原来容量的2倍 + 2,同时将原有数组中的元素复制到新的数组中。

12.普通类和抽象类有哪些区别?
  • 抽象类不能被实例化。
  • 抽象类可以有抽象方法,抽象方法只需申明,无需实现。
  • 含有抽象方法的类必须申明为抽象类。
  • 抽象的子类必须实现抽象类中所有抽象方法,否则这个子类也是抽象类。
  • 抽象方法不能被声明为静态。
  • 抽象方法不能用private修饰。
  • 抽象方法不能用final修饰。
13.抽象类与接口的区别?

相同点:
不能实例化;都可以包含抽象方法的。

不同点:

  • 抽象类一定有构造方法,创建子类对象时被调用;接口中不能有构造方法。
  • 抽象类通过extends来继承,只能继承一个抽象类(单继承);接口通过implements来实现,允许实现多个接口(多继承),用逗号隔开。
  • 抽象类中可以有普通成员变量;接口中没有普通成员变量。
  • 抽象类中可以包含非抽象普通方法;接口中的所有方法必须都是抽象的。
  • 抽象类中的抽象方法的访问权限可以是 public、protected 和 default;接口中的抽象方法只能是 public 类型的,并且默认即为 public abstract 类型。
  • 抽象类中可以包含静态方法;JDK1.8 前接口中不能包含静态方法,JDK1.8 及以后可以包含已实现的静态方法。
  • 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量可以是任意访问权限;接口中变量默认且只能是 public static final 类型。
  • 接口不可以实现接口,但可以继承接口,并且可以继承多个接口,用逗号隔开。
14.Java4种访问修饰符权限的区别?

15.Java中的 << << >>> 是什么?
<<  表示左移,不分正负数,低位补0
>>  表示右移,如果该数为正,则高位补0,若为负数,则高位补1
>>> 表示无符号右移,也叫逻辑右移,即若该数为正,则高位补0,而若该数为负数,则右移后高位同样补0

代码:

	16 << 1 : 32
	16 >> 3 : 2
	16 >> 10 : 0
	1 >> 1 : 0
	16 >>> 2 : 4
	-16 >> 2 : -4
	-16 << 2 : -64
	-16 >>> 2 : 1073741820
16.throw 和 throws 的区别?

throw:

  • 表示方法内抛出某种异常对象。
  • 如果异常对象是非 RuntimeException 则需要在方法申明时加上该异常的抛出 即需要加上 throws 语句 或者 在方法体内 try catch 处理该异常,否则编译报错。
  • 执行到 throw 语句则后面的语句块不再执行。

throws:

  • 方法的定义上使用 throws 表示这个方法可能抛出某种异常。
  • 需要由方法的调用者进行异常处理。
17.常见的异常类有哪些?
java.lang.Throwable
	|-----java.lang.Error:一般不编写针对性代码进行处理
	|-----java.lang,Exception:可以进行异常的处理
		|-----编译时异常(checked)
			|-----IOException
				|-----FileNotFoundException
			|-----ClassNotFoundException
		|-----运行时异常(unchecked、RuntimeException)
			|-----NullPointException:空指针异常
			|-----ArrayIndexOutOfBoundsException:数组角标越界
			|-----ClassCastException:类型转换异常
			|-----NumberFormatException
			|-----InputMismatchException
			|-----ArithmeticException:算数异常
18.重载和重写有什么区别?
  • 从定义上:

重载:在同一个类中声明多个方法名相同形参列表不同的方法,彼此之间构成了重载,构造器也可以重载。
重写:子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作。

  • 具体规则:

重载的规则:
①必须具有不同的参数列表。
②可以有不同的访问修饰符。
③可以抛出不同的异常。

重写方法的规则:
①参数列表必须完全与被重写的方法相同,否则不能称其为重写而是重载。
②返回的类型必须一直与被重写的方法的返回类型相同,否则不能称其为重写而是重载。
③访问修饰符的限制一定要大于被重写方法的访问修饰符。
④重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常。

  • 类的关系上:

重写是子类和父类之间的关系,是垂直关系。
重载是同一个类中方法之间的关系,是水平关系。

  • 形态上:

重载:不表现为多态性。
重写:表现为多态性。

19.如何解决线程安全问题, 有几种方式?分别是什么?

4种
1.继承Thread类
2.实现Runnable接口
3.实现Callable接口
4.使用线程池

20.synchronized 与 Lock的异同?

相同:

  • 二者都可以解决线程安全问题。

不同:

  • synchronized 机制在执行完相应的同步代码以后,自动的释放同步监视器。
  • Lock需要手动的启动同步(Lock()),同时结束同步也需要手动的实现(unLock())。
21.sleep() 和wait()的异同?

相同点:

  • 一旦执行方法,都可以使得当前的线程进入阻塞状态。

不同点:

  • 两个方法声明的位置不同: Thread类 中声明sleep(),object类 中声明wait()
  • 调用的要求不同: sleep()可以在任何需要的场景下调用。 wait()必须使用在同为
  • 关于是否释放同步监视器:如果两个方法都使用在同步代码块或同步方法中,sleep()不会释放锁,wait() 会释放锁。
22.wait()、notify()和notifyAll()的异同?

相同点:

  • 三个方法必须使用在同步代码块或同步方法中。
  • 三个方法的调用者必须是同步代码块或同步方法中的同步监视器中的,否则,会出现IlLegaLMonitorStateException异常。
  • 三个方法是定义在java.lang.object类中。

不同点:

  • wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器。
  • notify():一旦执行此方法,就会唤醒被wait的一个线程。 如果有多个线程被wait,就唤醒优先级高的那个。
  • notifyALl():一旦执行此方法,就会唤醒所有被wait的线程。
23.如何理解实现Callable接口的方式创建多线程比实现Runnable接口创建多线程方式强大?
  • call() 可以有返回值的。
  • call() 可以抛出异常,被外面的操作捕获,获取异常的信息。
  • Callable是支持泛型的。
24.比较ArrayList、LinkedList、Vector三者的异同?

相同:

  • 三个类都实现了list接口,存储数据的特点相同,有序,可重复。

不同:

  • ArrayList:作为List接口的主要实现类;jdk1.2,线程不安全的,效率高;底层使用Object[] elementData存储。
  • LinkedList:jdk1.2:底层使用双向链表存储,对于频繁的插入、删除操作比ArrayList的效率。
  • Vector:作为List接口的古老的实现类;jdk1.0,线程安全的,效率低;底层使用Object[] elementData存储。
如果有收获!!! 希望老铁们来个三连,点赞、收藏、转发
创作不易,别忘点个赞,可以让更多的人看到这篇文章,顺便鼓励我写出更好的博客
 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服