首页 > 编程语言 >Java 面试题 01 - Java 基础

Java 面试题 01 - Java 基础

时间:2022-10-06 17:13:17浏览次数:40  
标签:面试题 01 Java String 对象 链表 数组 字符串 Integer

基础概念

JDK、JRE、JVM 的区别?

  • JDK 是 Java 开发工具包,包含了 Java 的 开发工具(编译工具 javac.exe 和打包工具 jar.exe 等)和 JRE
  • JRE 是 Java 运行环境,提供了库、JVM 和其他组件,用于运行 Java 程序。
  • JVM 负责把 Java 程序生成的字节码解释成具体系统平台上的机器指令,让其在各个平台上运行。

JDK = 开发工具 + JRE,JRE = JVM + 类库。


final 关键字的作用是什么:

  • final 修饰的类不能被继承
  • final 修饰的方法不能被重写
  • final 修饰的变量必须被初始化,且不能被修改

包装类型的缓存机制是什么?

Integer 缓存池的大小默认为 -128 ~ 127,调用 Integer.valueOf(intNum) 方法时,如果 intNum 对象存在于缓存池中,会直接使用这个对象,而不是新建对象。

Integer x = new Integer(123); // 创建新对象
Integer y = new Integer(123); // 创建新对象
x == y; // false
Integer a = Integer.valueOf(123); // 使用缓存池中的对象
Integer b = Integer.valueOf(123); // 使用缓存池中的对象
a == b; // true

自动装箱时,如果数值位于缓冲池范围内,会隐式调用 valueOf 方法。

ByteShortIntegerLong 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character 创建了数值在 [0,127] 范围的缓存数据。而 DoubleFloat 没有实现缓存机制。


访问权限修饰符有哪些?

  • private:当前类内部可见。
  • protected:用于 修饰成员,当前 package 和所有子类可见。
  • default:当前 package 可见。
  • public:所有类可见。

初始化顺序是什么?

  1. 父类的静态变量、静态语句块
  2. 当前类的静态变量、静态语句块
  3. 父类的实例变量、普通语句块
  4. 父类的构造函数
  5. 当前类的实例变量、普通语句块
  6. 当前类的构造函数

静态成员是属于类的,在类加载时就会分配内存。而非静态成员属于实例对象,只有在对象实例化之后才存在。


Exception 有哪些种类?

  • RuntimeException运行时异常(非受查异常),在编译时不会被发现。这些异常一般 是由程序逻辑错误引起的,应该由程序员来避免。NullPointerExceptionIndexOutOfBoundsExceptionIllegalArgumentException ……
  • 编译时异常:(受查异常),如果不处理这种类型的异常,程序就不能编译通过。
    • IOExceptionFileNotFoundException
    • SQLException

面向对象

重写和重载的方法是什么?

  • 重写(Override):指 子类 实现了一个与父类的方法签名相同的方法。
  • 重载(Overload):在 同一个类中,一个方法与另一个已存在方法的 方法名相同,但是 参数类型、个数、顺序至少有一个不同

只有返回类型不同不是重载。


==equals 的区别是什么?

  • == 对基本类型比较值,对对象类型比较引用(地址值)。
  • equals 默认情况下是比较引用,但是很多类重写了 equals 方法,比如 StringInteger 类,将它变成了 值的比较,所以一般情况下是比较值是否相等。

抽象类和接口的区别是什么?

语法层面:

  • 抽象类的 成员变量 可以是各种类型的,接口的只能是 public static final
  • 抽象类可以有 static 代码块和 static 方法,接口没有。
  • 一个类只能继承一个抽象类,但可以实现多个接口。

设计层面:

  • 抽象类是对 一类事物 的抽象,接口是对 行为 的抽象。
  • 抽象类作为 父类,是一种 模板式 设计,而接口作为 行为规范,是一种 辐射式 设计。

在多数情况下,接口优先于抽象类,因为接口没有抽象类严格的类层次结构要求,可以灵活地为类添加行为。并且从 Java 8 开始,接口也可以有默认的方法实现,使得修改接口的成本也变得很低。


深拷贝、浅拷贝、引用拷贝的区别是什么?

  • 浅拷贝:浅拷贝会在堆上创建一个新的对象(区别于引用拷贝的一点),不过,如果原对象内部的属性是引用类型的话,浅拷贝会直接复制内部对象的引用地址,也就是说拷贝对象和原对象共用同一个内部对象。
  • 深拷贝 :深拷贝会完全复制整个对象,包括这个对象所包含的内部对象。


hashCode()equals() 的关系是什么?

hashCode() 的作用是获取哈希码,作用是确定该对象在哈希表中的索引位置。以 HashSet 检查重复 为例,加入一个对象时,会先调用 hashCode() 来计算该对象应该插入的位置,如果该位置处没有其他对象,说明当前对象不重复。而如果当前位置处存在其他对象,这时候 不能说明重复,需要 进一步调用 equals() 方法来判断 当前对象和已存在对象是否真的重复。也就是说,只有在 hashCode 相同时才会调用 equals() 方法,大大降低了开销。

总结来说:

  • 如果两个对象的 hashCode 不相等,则这两个对象 不相等
  • 如果两个对象的 hashCode 相等,那么这两个对象 不一定相等(哈希碰撞)。需要同时满足 equals() 条件,才能说明相等。
  • 如果 equals() 返回 true,那么说明两个对象相等,则它们的 hashCode 必定相等。

常用类

String 为什么不可变?

String 内部使用 char[] 数组存储数据,该数组被声明为 final,这意味着 value 数组初始化之后就不能引用其他数组;并且 String 内部没有改变 value 数组的方法,因此可以保证 String 不可变。


intern() 方法的作用是什么?

str.intern() 会先检查 字符串常量池 中是否有 str 这个字符串,如果存在则 直接返回这个字符串的引用,否则将这个字符串 添加到字符串常量池中,然后再返回这个字符串的引用。

使用构造函数创建的字符串 new String("xxx") 不会添加到字符串常量池中,使用字面量 "xxx" 创建的字符串才会添加到字符串常量池中(如果常量池中已经存在该字符串,则直接返回这个引用)。

String str1 = "Rachael"; // 添加到常量池
String str2 = new String("Rachael");
str1 == str2; // false
str2.intern() == str1; // true

另外,使用多个字符串字面量拼接来创建字符串时,会将其拼接结果作为字面量来创建字符串。

String s1 = "abc";
String s2 = "ab" + "c";
s1 == s2; // true

对于 编译期可以确定值 的字符串,也就是常量字符串 ,jvm 会将其存入字符串常量池。并且,字符串常量拼接得到的字符串常量在编译阶段就已经被存放字符串常量池,这个得益于编译器的优化。


字符串拼接用 + 还是 StringBuilder

字符串对象通过 + 拼接时,会创建 StringBuilder 对象,调用 append() 方法来实现,拼接完成之后调用 toString() 得到一个 String 对象 。

不过,在循环内使用 + 进行字符串的拼接的话,存在比较明显的缺陷:StringBuilder 对象是在循环内部被创建的,这意味着每循环一次就会创建一个 StringBuilder 对象。


容器

HashMapHashTable 有什么区别?

  • 继承关系HashMap 继承自抽象类 AbstractMapHashTable 继承自 Dictionary 抽象类,该类已被废弃。
  • null 键和值HashMap 支持空键和空值,而 HashTable 会抛出空指针异常。因为 HashMapnullhashCode 定为了 0,从而将它放在哈希表的第 0 个桶中。
  • 数据结构:都用哈希表来存储键值对,哈希表用 Entry 类型的引用数组来实现,数组长度就是哈希桶的数量。数组中 每个 Entry 引用指向一个链表结点,这个结点又包含着下一个结点的引用。(使用拉链法解决散列冲突)JDK 8 开始,当 HashMap 的某条链表长度大于 8 之后,会将链表转化为红黑树。(转化为红黑树前会先判断,如果当前数组长度小于 64,会进行数组扩容;否则才进行转化。)
  • 初始容量和扩容HashTable 的默认初始大小为 11,每次扩容会将原容量 n 扩展为 2n+1HashMap 的默认初始大小为 16,每次扩容会将容量 翻倍

HashTable 已被淘汰,不要使用。


ConcurrentHashMapHashTable 有什么区别?

主要是 实现线程安全的方式 不同。

  • 底层数据结构:

    • JDK 7 的 ConcurrentHashMap 底层采用 分段的数组+链表 实现,JDK 8 采用的数据结构跟 HashMap 的结构一样,数组+链表/红黑树
    • Hashtable 和 JDK 8 之前的 HashMap 的底层数据结构类似都是采用 数组+链表 的形式,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的。
  • 实现线程安全的方式

    • 在 JDK1.7 的时候,ConcurrentHashMap 对整个桶数组进行了分段(segment),分段加锁,每一把锁只锁容器中一部分数据,多线程访问容器里不同数据段的数据,就不会存在锁竞争,提高并发访问率。

      Segment 的结构和 HashMap 类似,是一种数组和链表结构,一个 Segment 包含一个 HashEntry 数组,每个 HashEntry 是一个链表结构的元素。

    • 到了 JDK1.8 的时候,ConcurrentHashMap 已经摒弃了 Segment 的概念,而是直接用 Node 数组+链表/红黑树 的数据结构来实现,并发控制使用 synchronized 和 CAS 来操作。锁粒度更细,synchronized 只锁定当前链表或红黑树的首节点,这样只要 hash 不冲突,就不会产生并发,就不会影响其他 Node 的读写,效率大幅提升。

    • Hashtable 使用 synchronized 来保证线程安全,效率非常低下。当一个线程访问同步方法时,其他线程也访问同步方法,可能会进入阻塞或轮询状态。


ListSetcontains() 方法有什么区别?

  • HashSetcontains() 方法底部依赖的 HashMapcontainsKey() 方法,时间复杂度接近于 O(1)(没有出现哈希冲突的时候为 O(1)
  • ArrayListcontains() 方法是通过遍历所有元素的方法来做的,时间复杂度接近是 O(n)

将数组转换为 List 的方法有哪些?

  • List list = new ArrayList<>(Arrays.asList(arr));

  • 使用 Stream

    // 包装类型数组
    List list = Arrays.stream(arr).collect(Collectors.toList());
    // 基本类型数组
    List list = Arrays.stream(arr).boxed().collect(Collectors.toList());
    

Arrays.asList() 方法返回的不是 java.util.List 类型,而是一个 Arrays 的子类型。

标签:面试题,01,Java,String,对象,链表,数组,字符串,Integer
From: https://www.cnblogs.com/lzh1995/p/16758004.html

相关文章

  • 腾讯AI Lab的CVPR 2018文章解读
    今天和大家分享马上要召开的CVPR2018会议,这算殿堂级的会议,今天主要主角是我和腾讯,......
  • CVPR2018 ——(GAN)延时摄影视频的生成
    CVPR2018即将开始,陆陆续续很多优秀的作品被大家知晓。今天我们来说说又去的科研成果,也希望阅读您对此感兴趣~在户外拍摄一张照片之后,我们可以预测照片里面接下来发生的事情......
  • CVPR 2018论文解读 | 学习在黑暗中看世界(Learning to See in the Dark)
    好些天不和大家见面,还是怪想各位关注我们支持我们的你!由于“计算机视觉战队”创始人最近接近毕业阶段,所以很多事情要去处理,没有及时给大家带来好的分享,在此向大家表示由衷的......
  • [ZJOI2014]星系调查
    做题时间:2022.10.5\(【题目描述】\)给定一个点数为\(n(n\leq4\times10^5)\),边数为\(m(4\times10^5)\)的无向联通图,满足\(m\leqn\),对于第\(i\)个点,给定一个笛卡......
  • 【算法-简单01】合并2个有序数列
    合并2个有序数列结果:时间复杂度:O(N)空间复杂度:O(N)比较抽象的点结论:Node对象有3个属性:Node本身、val,以及Node.nextNode本身判空,结合while来进行遍历查询val......
  • java--while小练习和switch小练习
    while小练习动态录入学生个数,成绩,求总成绩和平均值packagelearnday2;importjava.util.Scanner;*@description:动态录入学生成绩,并求总分和平均值publicclasswhileDe......
  • P4384 [八省联考 2018] 制胡窜
    P4384[八省联考2018]制胡窜考虑先将问题转化为切断两个位置使得没有任何一段中包含\(t\)。则最终的答案为\(\dbinom{n}{2}-\text{ans}\)。计\(t\)按左端点排序后......
  • java课后反思
        在定义变量时,我们需要对变量进行初始化才可以继续进行使用,同时,对象变量如果不引用一个真实的值,则必须·对他声明为null;  对于原始数据类型变量,可以使用==......
  • day01
    markdown学习标题一级标题(#空格标题名字)二级标题(##空格标题名字)三级以下类推逐加#回车即可字体斜体:字体俩边加1星号(eg:hello)粗体:字体俩边加2星号(eg:hello)即粗又斜:......
  • P2305 [NOI2014] 购票
    P2305[NOI2014]购票设\(f_{x}\)表示从\(x\)点跳到\(1\)的最少费用。考虑\(x\)的一个祖先\(u\),有\[f_x=f_{u}+\text{dis}_{u,x}\timesp_x+q_x\]其中需要满足......