java面试题知识体系-java基础

整理一些java面试题供自己复习

一、基本常识

Q:Java语言有哪些特点?

A:Java语言共有十大特点,分别为:简单性、面向对象、分布性、编译和解释性、稳健性、安全性、可移植性、高性能、多线索性、动态性。
参考:https://zhuanlan.zhihu.com/p/109053181

Q:JDK JRE JVM三者有什么区别与联系?

A:

  • JDK 用于开发,JRE 用于运行java程序 ;如果只是运行Java程序,可以只安装JRE,无序安装JDK。
  • JDk包含JRE,JDK和 JRE 中都包含 JVM。
  • JVM 是 java 编程语言的核心并且具有平台独立性。
    在这里插入图片描述
Q:Java如何实现跨平台?

A:通过java虚拟机(JVM)。JVM会将编译后的.class文件(16进制的文件流)翻译成机器认识的语言(二进制的机械码)。

Q:8大基本数据类型有哪些?

A:在这里插入图片描述

Q:成员变量与局部变量的区别?

A:
在这里插入图片描述

二、基本算法

参考:冒泡排序、选择排序、快速排序、二分查找、快速排序

三、面向对象

Q:面向对象具有哪些特征,分别是什么?

A:封装、继承、多态。

Q:方法的重载有重写有什么区别?与返回值是否有关?

A:
重载(Overload):方法签名相同,参数列表不同(与返回值无关)。

重写/覆盖(Override):同名同参同返回,前面的权限修饰符不能比父类的更封闭,抛出的异常不能更宽泛。

Q:构造方法有什么特点,是否能被重写?

A:构造方法的名字必须与类名相同,且没有任何返回类型。不可重写。
构造方法名 = 类名,子类名 ≠ 父类名,又子类重写必须 = 父类方法重名。
相当于,父类名 = 父构造方法 = 子类名 = 子构造方法。
前后矛盾,故不可重写。

Q:值传递和引用传递有什么区别?为什么java只有值传递?

A:
值传递:传递值。(将复制后再操作)
引用传递:传递地址。(直接对参数操作)
Java在使用中不允许出现指针。
参考:java存在引用传递吗?

Q:接口和抽象类有什么区别?

A:抽象类主要作用是规范。

  • 抽象类只能继承一次,但是可以实现多个接口
  • 接口和抽象类必须实现其中所有的方法,抽象类中如果有未实现的抽象方法,那么子类也需要定义为抽象类。抽象类中可以有非抽象的方法
  • 接口中的变量必须用 public static final 修饰,并且需要给出初始值。所以实现类不能重新定义,也不能改变其值。
  • 接口中的方法默认是 public abstract,也只能是这个类型。不能是static,接口中的方法也不允许子类覆写,抽象类中允许有static 的方法
Q:四种访问权限修饰符的作用范围是什么?

A:在这里插入图片描述

Q:this super static final4个关键字的总结。

A:

1.this

  • 指向当前
    注意:this不能用在static方法中。

2.super

  • 指向父类
    注意:super不能用在static方法中。

3.static

  • 初始,静态、全局。
    注意:用static修饰的代码块表示静态代码块,当Java虚拟机(JVM)加载类时,就会执行该代码块。

4.final

  • final类不能被继承,没有子类,final类中的方法默认是final的。
  • final方法不能被子类的方法覆盖,但可以被继承。
  • final成员变量表示常量,只能被赋值一次,赋值后值不再改变。
  • final不能用于修饰构造方法。
    注意:父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。
Q:==与equals有什么区别

A:

  • ==只是比较是不是同一个对象。
  • 而equals可以完成你的个性化比较,可以重写equals方法。
  • 而如果子类没有复写,equals默认就是用==来判断俩对象是否相等的。
Q:Final Finally Finalize三个方法的作用是什么?

A:

  • Final是一个修饰符,可修饰变量,方法等。
  • Finally在try/catch中使用
  • Finalize是一个方法,属于java.lang.Object类,finalize()方法是GC (garbage collector垃圾回收)运行机制的一部分,finalize()方法是在 GC清理它所从 属的对象时被调用的。
Q:深拷贝与浅拷贝有什么区别?

A:

  • 浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址。
  • 深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存。
  • 使用深拷贝的情况下,释放内存的时候不会因为出现浅拷贝时释放同一个内存的错误。
Q:强引用、弱引用、软引用、虚引用有什么区别?

A:
在这里插入图片描述
参考来源:知乎用户winterSunshine的回答

四、常用类

Q:String,StringBuffer, StringBuilder 的区别是什么?String为什么是不可变的?

A:
区别:

  • String是字符串常量,而StringBuffer和StringBuilder是字符串变量。由String创建的字符内容是不可改变的,而由StringBuffer和StringBuidler创建的字符内容是可以改变的。
  • StringBuffer是线程安全的,而StringBuilder是非线程安全的。StringBuilder是从JDK 5开始,为StringBuffer类补充的一个单线程的等价类。我们在使用时应优先考虑使用StringBuilder,因为它支持StringBuffer的所有操作,但是因为它不执行同步,不会有线程安全带来额外的系统消耗,所以速度更快。

String为什么不可变:

  • 虽然String、StringBuffer和StringBuilder都是final类,它们生成的对象都是不可变的,而且它们内部也都是靠char数组实现的,但是不同之处在于,String类中定义的char数组是final的,而StringBuffer和StringBuilder都是继承自AbstractStringBuilder类,它们的内部实现都是靠这个父类完成的,而这个父类中定义的char数组只是一个普通是私有变量,可以用append追加。因为AbstractStringBuilder实现了Appendable接口。
Q:System.gc()与Runtime.gc()有什么不同?

System.gc()内部代码为Runtime.getRuntime().gc()。
区别:

  • System.gc()是类方法,非本机方法(不与硬件和系统资源直接交互的代码)
  • Runtime.gc()是实例方法,本机方法(一种与硬件和系统资源直接交互的编程语言)
Q:hashCode方法有什么作用?

A:快速定位。

【什么是hash】首先,需要明白hash是什么,hash是用来快速定位元素的一种数据结构,如给定一个变量我们可以通过hash 确定这个变量在内存中的位置 即 变量a 经过 hash(a)->就可以确定这个元素在内存中的位置。
【hashCode 方法的作用】object基类 中 有hashcode(),这就导致了所有我们自建的类都继承了hashcode 方法。hashcode在单一类当中只是一个实例方法并没有什么大的作用。
【hashcode 应用】 在Java集合类当中有实现map接口的HashMap、Set接口的HashSet 要知道set集合中存储的对象的引用所指向的对象是不能重复的。

比如你要实现 Set students[] = new HashSet<>();那么 Student 这个类中必须override(重写)hashCode()与equals(), 如果不重写hashCode,只重写equals(),那么当你Student a = new Student(“张晓”,13);Student b = new Student(“张晓”,13); 这两个对象的引用都能被存储至hashset 集合当中,但其实我们肉眼观察到的对象已经重复了,这就是因为hashcode没有重写,两个对象的hash code不一致导致的肉眼观察到的相同内容的对象被存储至了set集合当中。所以总结:多个 单一类对象实例中,如果两个对象的hashCode() 相同 ,那么两个对象equals() 一定相同 因为是同一个对象,但equals相同 hashCode()不一定相同在HashTable、HashSet、HashMap 集合中存储的对象,hashCode 与 equals 结合来确保元素的肉眼可见的非重复性。

五、异常

Q:异常与错误有什么区别??

A:
异常(Exception):主要是语法错误和语义错误,异常都会通过jvm虚拟机告诉你。
错误(Error):应用程序不能截获的严重问题。

Q:异常的类层次结构是如何的?

A:在这里插入图片描述

Q:常见的异常有哪些?

A:

  • 空指针异常类:NullPointerException
  • 数据类型转换异常:java.lang.ClassCastException
  • 没有访问权限:java.lang.IllegalAccessException
  • 方法的参数错误:java.lang.IllegalArgumentException
  • 数组下标越界异常:java.lang.IndexOutOfBoundsException
  • 文件已结束异常:EOFException
  • 文件未找到异常:FileNotFoundException
  • 字符串转换为数字异常:NumberFormatException
  • 指定的类不存在: java.lang.ClassNotFoundException
  • 实例化异常:java.lang.InstantiationException
Q:如何自定义异常?

A:继承Exception类。

// 先自定义异常类,如用户不存在异常DollarsNotFoundException
public class DollarsNotFoundException extends Exception { 
 
    public DollarsNotFoundException () {
        super();
    }
     
    public DollarsNotFoundException (String message) {
        super(message);
    }
 
    public DollarsNotFoundException (Throwable cause) {
        super(cause);
    }
 
    public DollarsNotFoundException (String message, Throwable cause) {
        super(message, cause);
    }
}

异常使用场景类

public void findMondy() throws DollarsNotFoundException{
     try {
         // todo
     } catch(Exception e) {
         throw  new  DollarsNotFoundException("你没钱!");  
     }
}
Q:throw与throws有什么区别?

A:
throw:抛出
throws:声明
语法:[(修饰符)] (返回值类型)(方法名)([参数列表])[throws(异常类)]{…}
public void doA(int a) throws Exception1,Exception3{…}

六、IO

Q:java中io流分为几种?字节流与字符流有什么区别?

A:
(1)按流向分类:

  • 输入流
  • 输出流

(2)按处理数据不同分类:

  • 字节流:二进制,可以处理一切文件,包括:纯文本、doc、音频、视频等。
  • 字符流:文本文件,只能处理纯文本。

(3)按功能不同分类:

  • 节点流:包裹源头。
  • 处理流:增强功能,提高性能。
Q:IO中BIO、NIO、AIO有什么区别?

A:

  • BIO:同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
  • NIO:同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。
  • AIO:异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。

七、JAVA集合

Q:java集合类的集成体系是怎样的?

A:
在这里插入图片描述

Q:ArrayList与LinkedList有什么区别?

A:
总结:ArrayList适合查,LinkedList适合增删。

ArrayList和LinkedList都实现了List接口。但是在数据结构的实现上ArrayList是数组,LinkedList是双向链表,所以LinkedList比ArrayList会更耗内存,因为它一个节点要存两个引用,一个指向上一个元素,一个指向下一个元素。而数组查找元素的时间复杂度是O(1),链表查找元素的时间复杂度是O(n),所以查询多的情况下,ArrayList比LinkedList更适合。
只要不是首尾的增加或删除操作,那么LinkedList的效率就是比ArrayList高,因为ArrayList进行增删操作后,数组内就会有一些数据会受到影响,需要更换下标,影响的数据范围越广,效率越低。

Q:HashMap底层原理是怎样的

A:HashMap=数组+链表

put:

  • 对key的hashCode()做hash,然后再计算index;
  • 如果没碰撞直接放到bucket里;
  • 如果碰撞了,以链表的形式存在buckets后;
  • 如果碰撞导致链表过长(大于等于TREEIFY_THRESHOLD),就把链表转换成红黑树;
  • 如果节点已经存在就替换old value(保证key的唯一性) 如果bucket满了(超过load factor*current
    capacity),就要resize。

get:

  • bucket里的第一个节点,直接命中;
  • 如果有冲突,则通过key.equals(k)去查找对应的entry:
    若为树,则在树中通过key.equals(k)查找,O(logn);
    若为链表,则在链表中通过key.equals(k)查找,O(n)。
    在这里插入图片描述
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值