Java面试题-02

目录

13.List和Set的区别

14.String,StringBuffer,StringBuilder的区别

15.Jdk1.7到Jdk1.8 HashMap发生了什么变化(底层)?

16.接口和抽象类的区别

多说几句:我们这里接口中为什么必须要直接进行初始化?

17.泛型中extends和super的区别

18.深拷贝和浅拷贝

 ​编辑

 19.什么是面向对象?谈谈你对面向对象的理解

面向对象的三大特征

20.重写和重载的区别

 21.为什么用线程池?解释下线程池参数

 22.简述线程池的处理流程


13.List和Set的区别

List:有序,可重复。

有序是指按对象进入的顺序进行保存对象,允许多个Null元素对象,可以使用iterator取出所有元素。

在逐一遍历时,我们知道List是有序的,所有我们可以通过get(int index)的方式获取指定下标的元素

Set:无序,不可重复,

最多允许有一个Null元素对象,我们前面的题分析过,HashSet底层是HashMap,HashMap的put方法中表示如果key为null,那么直接加在第一个索引位置,所以最多有一个Null元素

其次取元素时,只能用iterator接口取得所有元素,不可以用for循环是因为Set没有get(int index)方法,因为Set它是无序的,所以我们无法根据index下标去获取正确的值

14.String,StringBuffer,StringBuilder的区别

1.String是被final修饰的,是不可变的,如果尝试去修改时,是会新生成一个字符串对象,而不是把原来的字符串进行修改。即不是在原对象上进行操作的

 但是StringBuffer,StringBuilder是可变的,是在原对象上进行操作的

2.StringBuffer是线程安全的,源码可知:有锁,使得线程同步

 StringBuilder是线程不安全的,

使用场景:

如果在单线程的环境下选择效率更高的StringBuilder。

但是多线程并发的时候为了线程安全则应该使用StringBufer

性能:

StringBuilder>StringBuffer>String

15.Jdk1.7到Jdk1.8 HashMap发生了什么变化(底层)?

 1.   1.7中底层是数组+链表,然而1.8底层是数组+链表+红黑树,增加红黑树的目的是提高HashMap进行插入或查询元素时的整体效率。【因为如果链表的长度过长,那么遍历起来的效率过低】

2.    1.7中链表插入使用的是头插法,每一次插入元素时插入到链表的头部。但是Jdk1.8中链表插入元素使用的是尾插法,原因是1.8中插入key和value时需要判断链表的元素个数【因为达到一定数量之后会进行树化,转化为红黑树】,所以使用尾插法

3.   1.7中哈希算法比较复杂,存在各种右移或异或运算,但是1.8进行了简化,因为复杂的哈希算法目的就是为了提高散列性【减少哈希冲突】以此来提高HashMap的整体效率。

但是1.8中引入了红黑树,所以适当简化哈希算法【因为这个算法运算也会消耗很多的CPU资源】

16.接口和抽象类的区别

1.抽象类可以存在普通成员函数,而接口中只能存在public abstract方法

2.抽象类中的成员变量可以是各种各样的,而接口中的成员变量只能是public static final类型的,因此接口中的成员变量必须赋初值进行初始化

3.抽象类只能继承一个,接口可以实现多个

4.抽象类可以有抽象的方法也可以有非抽象的方法,而接口中只可存在public abstract方法

多说几句:我们这里接口中为什么必须要直接进行初始化?

如果final修饰的是类变量(即是静态变量),我们只能在静态初始化块中指定初始值或者声明的时候就初始化。

原因:因为类变量(即是静态变量)是当类加载时就应该进行完初始化操作,

如果我们放在构造器中进行初始化的话,就会报错,因为只有创建对象时才会进行构造器初始化。

我们new 一个对象分为两大步:1.进行类加载 2.才是进行new对象(即是创建对象)
但是接口中不可以有static代码块,所以必须在申明成员变量时就直接进行初始化赋值

深度回答如下:

17.泛型中extends和super的区别

1.<? extends T>表示包括T在内的任何T的子类

2.<? super T>表示包括T在内的任何T的父类 

18.深拷贝和浅拷贝

深拷贝和浅拷贝就是指对象的拷贝,

一个对象中存在两种类型的属性:一种是基本数据类型,一种是实例对象的引用

1.浅拷贝是指,只会拷贝基本数据类型的值,以及实例对象的引用地址。并不会赋值一份引用地址指向的对象,也就是说我们浅拷贝之后的对象,内部类的属性指向的是同一个对象

2.深拷贝是指,即会拷贝基本数据类型的值,也会针对实例对象的引用地址所指向的对象进行复制,深拷贝出来的对象,内部类的属性指向的不是同一个对象

 

 19.什么是面向对象?谈谈你对面向对象的理解

 

面向对象的三大特征

多态:基于对象引用所属类不同,外部对同一个方法的调用,实际执行的逻辑不同。

【意思就是说基于这个对象引用对应的运行类型的不同,当这个对象引用对同一个方法进行调用时根据动态绑定机制,运行时看右,实际执行的代码不同】 

 多态的条件:继承,方法重写,父类引用指向子类对象

格式:

父类类型 变量名=new 子类对象;

变量名.方法名();

注意:我们无法调用子类特有的功能,只可以调用子类和父类公有的方法。

编译时看左边的编译类型,如果父类没有这个方法,那么编译的时候就会直接报错。

运行时看右边的运行类型,也就是子类类型,调用方法时发生运行时绑定,调用同一个方法所展现出结果的多样性,这就是多态

20.重写和重载的区别

 重载:

发生在同一个类中,方法名必须相同,

参数类型不同,个数不同,顺序不同。三者中至少有一样不同

方法返回值和访问修饰符可以不同,也可以相同【无要求】,发生在编译时

重写:

发生在父子类中,方法名,参数列表必须相同

返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类;

如果父类的方法修饰符为private时,则子类不能重写该方法

例子:

编译报错,因为对于重载而言返回值和访问修饰符无要求,可以相同也可以不同

 21.为什么用线程池?解释下线程池参数

 1.降低资源消耗;提高线程利用率,降低创建和销毁线程所带来的消耗

2.提高响应速度;任务来了,直接有线程可用可执行,而不是先创建线程,再执行

3.提高线程的可管理性;线程是稀缺资源,使用线程池可以统一的分配调优监控

 22.简述线程池的处理流程

 

 线程池执行任务,当任务进入时先判断核心线程是否已满,

如果核心线程未满,那么创建核心线程执行任务。如果已满,去看看任务队列是否已满。

如果任务队列未满,那么将任务放进任务队列。如果已满,去看看是否已达到最大线程数

如果最大线程数未达到,那么创建临时线程执行。如果已达到,那么根据拒绝策略处理执行任务

 多说一嘴:

当这个临时线程处理完一个任务之后,它会去看任务队列中是否存在等待被处理的任务,如果存在,那么取出来进行执行这个任务。如果不存在,那么它会进行等待,当等待到一定时间间隔【即是keepAliveTime】之后,临时线程就会销毁。

 整理不易,希望对大家有帮助。也希望看到的兄弟能给一个点赞,谢谢啦哈哈哈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值