Java面试问题整理笔记-Java基础知识

1.面向对象的特征 ?

1.1抽象

抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。

1.2继承

继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的重要手段

1.3封装

通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口(可以想想普通洗衣机和全自动洗衣机的差别,明显全自动洗衣机封装更好因此操作起来更简单;我们现在使用的智能手机也是封装得足够好的,因为几个按键就搞定了所有的事情)。

1.4多态性

多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。

  • 方法重载(overload)实现的是编译时的多态性(也称为前绑定)

  • 方法重写(override)实现的是运行时的多态性(也称为后绑定)。运行时的多态是面向对象最精髓的东西,要实现多态需要做两件事:

    ​ 1). 方法重写(子类继承父类并重写父类中已有的或抽象的方法);

    ​ 2). 对象造型(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)

2.访问修饰符 public,private,protected,以及不写(默认default)时的区别?

修饰符当前类同 包子 类其他包
public
protected×
default××
private×××
  • 类的成员不写访问修饰时默认为 default。

  • 默认对于同一个包中的其他类相当于公开(public),对于不是同一个包中的其他类相当于私有(private)。

  • 受保护(protected)对子类相当于公开,对不是同一包中的没有父子关系的类相当于私有。

  • Java 中,外部类的修饰符只能是 public 或默认

  • 类的成员(包括内部类)的修饰符可以是以上四种

3.List、Set、Map

请添加图片描述

3.1List

List(对付顺序的好帮⼿): List接⼝存储⼀组不唯⼀(可以有多个元素引⽤相同的对象),有序的对象

3.2Set

Set(注重独⼀⽆⼆的性质): 不允许重复的集合。不会有多个元素引⽤相同的对象。

3.3Map

Map(⽤Key来搜索的专家): 使⽤键值对存储。 Map会维护与Key有关联的值。两个Key可以引⽤相同的对象,但Key不能重复,典型的Key是String类型,但也可以是任何对象。

3.3.1HashMap的底层实现

JDK1.8 之前 HashMap 底层是 数组和链表 结合在⼀起使⽤也就是 链表散列。

HashMap 通过 key 的hashCode 经过扰动函数处理过后得到 hash 值,然后通过 (n - 1) & hash 判断当前元素存放的位置(这⾥的 n 指的是数组的⻓度),如果当前位置存在元素的话,就判断该元素与要存⼊的元素的 hash值以及 key 是否相同,如果相同的话,直接覆盖,不相同就通过拉链法解决冲突。所谓扰动函数指的就是 HashMap 的 hash ⽅法。使⽤ hash ⽅法也就是扰动函数是为了防⽌⼀些现⽐较差的 hashCode() ⽅法 换句话说使⽤扰动函数之后可以减少碰撞。

JDK1.8 之前 HashMap 由数组+链表组成的,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突⽽存在的(“拉链法”解决冲突)。 JDK1.8 以后在解决哈希冲突时有了较⼤的变化,当链表⻓度⼤于阈值(默认为 8)将链表转换成红⿊树前会判断,如果当前数组的⻓度⼩于 64,那么会选择先进⾏数组扩容,⽽不是转换为红⿊树)时,将链表转化为红⿊树,以减少搜索时间

所谓 “拉链法” 就是:将链表和数组相结合。也就是说创建⼀个链表数组,数组中每⼀格就是⼀个链
表。若遇到哈希冲突,则将冲突的值加到链表中即可

JDK1.8之后,相⽐于之前的版本, Java8 对 HashMap 进行了一些修改, 最大的不同就是利用了红黑树,所以其由 数组+链表+红黑树组成 。 JDK1.8之后在解决哈希冲突时有了较⼤的变化,==当链表⻓度⼤于阈值(默认为8)==时,将链表转化为红⿊树,以减少搜索时间。

  • 顺着链表一个个比较下去才能找到我们需要的,时间复杂度取决于链表的长度,为O(n)
  • 为了降低这部分的开销,在 Java8 中, 当链表中的元素超过了 8 个以后,会将链表转换为红黑树,在这些位置进行查找的时候可以降低时间复杂度为 O(logN)

3.3.2ConcurrentHashMap 的存储结构是怎样的?

  • Java7 中 ConcurrnetHashMap 使用的分段锁, 也就是每一个 Segment 上同时只有一个线程可以操作, 每一个 Segment 都是一个类似 HashMap 数组的结构, 它可以扩容,它的冲突会转化为链表。 但是 Segment 的个数一但初始化就不能改变, 默认 Segment的个数是 16 个。
  • Java8 中的 ConcurrnetHashMap ==使用的 Synchronized 锁(==synchronized 只锁定当前链表或红⿊⼆叉树的⾸节点,这样只要 hash 不冲突,就不会产⽣并发,效率⼜提升 N 倍。 )加 CAS 的机制,保证并发安全。 结构也由Java7 中的 Segment 数组 + HashEntry 数组 + 链表 进化成了 Node 数组 + 链表 / 红黑树, Node 是类似于一个 HashEntry 的结构。 它的冲突再达到一定大小时会转化成红黑树, 在冲突小于一定数量时又退回链表。

3.3.3有没有可能两个不相等的对象有相同的hashcode

有可能.在产生hash冲突时,两个不相等的对象就会有相同的 hashcode 值.当hash冲突产生时,一般有以
下几种方式来处理:

  • 拉链法:每个哈希表节点都有一个next指针,多个哈希表节点可以用next指针构成一个单向链表,被分配到同一个索引上的多个节点可以用这个单向链表进行存储.
  • 开放定址法:一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入
  • 再哈希:又叫双哈希法,有多个不同的Hash函数.当发生冲突时,使用第二个,第三个….等哈希函数计算地址,直到无冲突

3.3.4LinkedHashMap

LinkedHashMap 继承⾃ HashMap ,所以它的底层仍然是基于拉链式散列结构即由数组和链表或红⿊树组成。另外, LinkedHashMap 在上⾯结构的基础上,增加了⼀条双向链表,使得上⾯的结构可以保持键值对的插⼊顺序。同时通过对链表进⾏相应的操作,实现了访问顺序相关逻辑

3.3.5HashMap 多线程操作导致死循环问题

主要原因在于并发下的 Rehash 会造成元素之间会形成⼀个循环链表。不过, jdk 1.8 后解决了这个问题,但是还是不建议在多线程下使⽤ HashMap,因为多线程下使⽤ HashMap 还是会存在其他问题⽐如数据丢失。并发环境下推荐使⽤ ConcurrentHashMap 。

3.4Arraylist 与 LinkedList 区别?

3.4.1是否保证线程安全

ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全;

3.4.2底层数据结构

  • Arraylist 底层使⽤的是 Object 数组
  • LinkedList 底层使⽤的是双向链表 数据结构(JDK1.6之前为循环链表, JDK1.7取消了循环。注意双向链表和双向循环链表的区别,下⾯有介绍到!)

3.4.3插⼊和删除是否受元素位置的影响

  • ArrayList 采⽤数组存储,所以插⼊和删除元素的时间复杂度受元素位置的影响。 ⽐如:执⾏ add(E e) ⽅法的时候, ArrayList 会默认在将指定的元素追加到此列表的末尾,这种情况时间复杂度就是O(1)。但是如果要在指定位置 i插⼊和删除元素的话( add(int index, E element) )时间复杂度就为 O(n-i)。因为在进⾏上述操作的时候集合中第 i 和第 i 个元素之后的(n-i)个元素都要执⾏向后位/向前移⼀位的操作。

  • LinkedList 采⽤链表存储,所以对于 add(E e) ⽅法的插⼊,删除元素时间复杂度不受元素位置的影响,近似 O(1),如果是要在指定位置 i 插⼊和删除元素的话( (add(int index, E element) ) 时间复杂度近似为 o(n)) 因为需要先移动到指定位置再插⼊。

3.4.4是否⽀持快速随机访问

  • LinkedList 不⽀持⾼效的随机元素访问
  • ArrayList ⽀持。快速随机访问就是通过元素的序号快速获取元素对象(对应于 get(int index) ⽅法)。

3.4.5内存空间占⽤

ArrayList的空间浪费主要体现在list列表的结尾会预留⼀定的容量空间,⽽LinkedList的空间花费则体现在它的每⼀个元素都需要消耗⽐Array 为要存放直接后继和直接前驱以及数据)。

4.equals与==的区别

4.1==

== 比较的是变量(栈)内存中存放的对象的==(堆)内存地址==,用来判断两个对象的地址是否相同,即是否是指相同一个对象。比较的是真正意义上的指针操作。
1、比较的是操作符两端的操作数是否是同一个对象。
2、两边的操作数必须是同一类型的(可以是父子类之间)才能编译通过。
3、比较的是地址,如果是具体的阿拉伯数字的比较,值相等则为true,如:
int a=10 与 long b=10L 与 double c=10.0都是相同的(为true),因为他们都指向地址为10的堆。

4.2equals

equals用来比较的是两个对象的内容是否相等,由于所有的类都是继承自java.lang.Object类的,所以
适用于所有对象,如果没有对该方法进行覆盖的话,调用的仍然是Object类中的方法,而Object中的
equals方法返回的却是==的判断。

4.3总结

所有比较是否相等时,都是用equals 并且在对常量相比较时,把常量写在前面,因为使用object的equals object可能为null 则空指针

在阿里的代码规范中只使用equals ,阿里插件默认会识别,并可以快速修改,推荐安装阿里插件来排
查老代码使用“==”,替换成equals

5.String、String StringBuffer 和 StringBuilder 的区别是什

么?

5.1String

String是只读字符串,它并不是基本数据类型,而是一个对象。从底层源码来看是一个final类型的字符数组,所引用的字符串不能被改变,一经定义,无法再增删改。每次对String的操作都会生成新的String对象。

private final char value[];

每次**+**操作 : 隐式在堆上new了一个跟原字符串相同的StringBuilder对象,再调用append方法 拼接+后面的字符。

5.2StringBuffer和StringBuilder

他们两都继承了AbstractStringBuilder抽象类,从AbstractStringBuilder抽象类中我们可以看到

/**
* The value is used for character storage.
*/
char[] value;

他们的底层都是可变的字符数组,所以在进行频繁的字符串操作时,建议使用StringBuffer和StringBuilder来进行操作。 另外StringBuffer对方法加了同步锁或者对调用的方法加了同步锁(所以速度慢),所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。

6.深拷贝和浅拷贝的区别是什么?

  • 浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象.
  • 深拷贝:被复制对象的所有变量都含有与原来的对象相同的值.而那些引用其他对象的变量将指向被复制过的新对象.而不再是原有的那些被引用的对象.换言之.深拷贝把要复制的对象所引用的对象都复制了一遍.

7.Java创建对象有几种方式?

java中提供了以下四种创建对象的方式:

7.1new创建新对象

7.2通过反射机制

7.3采用clone机制

7.4通过序列化机制

8.JAVA 异常分类及处理

8.1概念

如果某个方法不能按照正常的途径完成任务,就可以通过另一种路径退出方法。在这种情况下会抛出一个封装了错误信息的对象。此时,这个方法会立刻退出同时不返回任何值。另外,调用这个方法的其他代码也无法继续执行,异常处理机制会将代码执行交给异常处理器。
请添加图片描述

Java 中Throwable 是所有异常和错误的超类,两个直接子类是 Error( 错误) 和Exception( 异常) :

  • Error 是程序无法处理的错误, 由 JVM 产生和抛出, 如 OOM、 ThreadDeath 等。 这些异常 发生时, JVM 一般会选择终止程序。
  • Exception 是程序本身可以处理的异常, 又分为运行时异常(RuntimeException)(也 叫Checked Eception)和 非 运 行 时 异 常(不 检 查 异 常 Unchecked Exception)。 运行 时 异 常 有NullPointerException\IndexOutOfBoundsException 等, 这些异常一般是由程序逻辑错误引起 的, 应尽可能避免。 非运行时异常有IOException\SQLException\FileNotFoundException 以及 由用户自定义的
    Exception 异常等。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值