java面试(基础篇)

1.谈谈对面向对象的理解?

面向对象是相对于面向过程来说的,所谓面向过程就是将解决方法的过程罗列出来,然后一步一步的去实现,面向对象则是将解决方法的步骤以及相关的数据组织成一个整体来看的。

2.抽象类和接口的区别?

抽象类有构造方法,接口没有。
抽象类里面的变量既可以为普通变量也可以为常量,接口只能是常量。
抽象类的方法既可以是抽象的,也可以不是的。
抽象类只支持单继承,接口可以多实现。

3.面向对象的三大特征?

封装:将对象里的属性进行私有化,不直接对外提供修改和读取的功能,保护对象属性,但对外提供了可操控的接口。
继承:一个类体对象可以通过相应的关键字来与其他类体发生继承关系,子类继承父类后可以获取父类的相应属性数据和方法函数,并可以对其进行扩展操作
多态:当一个父类对象被多个子类对象所继承,父类级引用可以指向特定的子类方法函数。

4.final和finalize();的区别?

final是关键字,被修饰的变量不能修改,类不能继承,方法不能重写。
finalize();是一个方法,用于垃圾回收,通常不用我们手动调用,因为在JVM垃圾回收的时候自动调用,如果手动调用就会回收两次,资源被二次释放就会报错。

5.super和this的概念。

两者都是指对象。
This指的是当前自己对象的引用,super指的是父类直接引用。
Super()调用基类中的某一个构造函数,放在方法第一位,this是调用本身的。
两者不能出现在同一个构造函数。不可在static中使用。

6.Comparator和Conparable区别?

Comparator外部比较器,Conparable内部比较器。
类已经无法被修改使用Comparator接口,重写Conparable实现排序。
创建类的时候,继承Conparable,重写compareTo实现排序。

7.包装类的优点?

作为基本类型的对应的类,方便直接操作对象。
包含每种基本数据类型的最大值和最小值,以及相关的操作方法。
在-128到128直接可以直接比较,因为放在缓存中了。

8.讲讲String字符串?

1:底层是final char[]数组,所以是不可变的。
原因:实现字符串池,保证线程安全,同一个字符串实例可以被多个线程共享,实现hashCode()不可变性。
2:和StringBuffer还有StringBuild之间的区别?以及怎么使用?
在字符串拼接大于2的时候采用StringBuffer或者StringBuild。
如果考虑到线程安全的情况下选择StringBuffer,如果在考虑效率的情况下选择 StringBuild。

9.int 和 Integer 有什么区别?

Integer是int的包装类;int是基本数据类型;
Integer变量必须实例化后才能使用;int变量不需要;
Integer实际是对象的引用,指向此new的Integer对象;int是直接存储数据值 ;
Integer的默认值是null;int的默认值是0。

10.线程相关的wait和notify还有notifyAll?

Wait指的是让线程一直等待,直到获得锁,或者被中断。
notify指的是唤醒该对象上等待的某个线程。
notifyAll唤醒该对象上等待的所有线程。

11.深浅拷贝?

浅拷贝指的是对基本类型拷贝字面量值,对对象而言拷贝的是对象的引用内存地址,没有创建对象。
深拷贝引用类型被创建了新的对象,并且对复制了内部的成员变量。深拷贝的方法是对当前对象使用clone();方法,对内部的引用变量再次使用clone()方法。

12.讲讲ArrayList和LinkedList之间的区别?

1:ArrayList底层是一个数组,LinkedList是双向链表。
2:在ArrayList的末尾部增删方便O(1),LinkedLits较为方便复杂度是O(n)。
3:ArrayList支持随机访问,但是LinkedList不支持。
4:ArrayList空间花费在列表结尾预留一定的容量空间,LinkedList在每一个元素上都需要预留一个前驱和后继的空间

13.ArrayList扩容原理?

1:使用无参构造创建时,初始化一个空数组。
2:添加第一个值的时候,容量扩充为10。
3:当添加元素达到扩容条件时,每次扩容1.5倍,就是将oldcapacity+(oldcapacity>>1),就是原来的1.5倍。

14.hashmap的底层?

底层是什么组成的?
是由数组加链表,1.8后引入了红黑树化的功能。
底层数组是一个entry对象类型的数组,存放元素的地方被称为桶(bucket),初始化容量时16,有一个扩容因子时75%,就是边界为12,也就是当数组存放的数量快达到12的时候就会对其进行扩容。扩容时按照2的n次幂来扩容。

15.hashmap的put过程?

首先对存放的key值进行hash运算,也就是hash算法,通过hash算法来计算出存放在哪一个下标的位置,如果该位置没有元素的话,那就直接存放在这个位置,如果有的话那就会发生hash冲突,因此就需要采用链式地址法,也就是链表,采用链表指向功能来解决冲突问题,当链表的长度超过8的时候就会转换为红黑树,小于等于6就会转换为链表。

16.为什么扩容因子时0.75,以及为什么是要用2的n次幂来扩容?

如果扩容的因子更大,这样虽然可以让空间得到有效利用,但是更容易产生hash冲突, 如果扩容的因子更小,这样虽然可以减少hash冲突,但是扩容的话就会很频繁,造成 空间的浪费。因此经过一些数学计算折中出一个界限值就是0.75.
2的n次幂是因为让元素存取更加均匀,数据高分布率,以及减少hash冲突。

17.hash算法(hash函数)是怎么实现的?

首先对Key值进行hash运算 h = key.hashCode() ^ (h>>>16)高16位不变,低16位bit和高16位bit做出异或运算获得hash值,然后进行取模操作(n - 1) &hash获得下标。n表示的是数组长度。
为什么是n - 1操作?
因为n绝大多数情况下是小于2的16次方,所以hash值也是低16位甚至更低,这样的参与运算会使得下标更加散列。
为什么是 &而不是直接%来求余数?
因为长度的2的n次幂,n - 1的所有二进制都是1,这种情况下取余比%来的快。

18.如何解决hash冲突的几种方法?

开放地址法。
链地址法。
再次哈希。
建立公共溢出区。

19.hashmap线程并发安全。

1:多个线程同时put,当其他线程put一个相同key的时候可能会造成数据的覆盖。
2:多个线程多个线程同时检测到元素个数超过数组的*loadFactor,同时对Node数组进行扩容,都重新计算元素位置和复制数据,最终只有一个线程会成功,其他线程丢失,并且put的数据丢失。

20.HashMap扩容(resize)的优化。

1.7是直接扩展容量为原来的两倍,所有元素都需要重新计算hash值,位置发生变化,比较耗性能
1.8不像1.7重新计算hash,hash对象新增bit是0,索引不变,是1变成“原索引+oldcap”

21.hashmap和hashtable之间的区别?

hashtable线程安全,不准许有unll值或者null键,hashtable直接使用hashCode不重新计
Hash值,hashtable扩容初始11,每次2old+1.

22.序列化和反序列化?

前者:将对象写入IO中,后者从IO中恢复对象。
用处:
1:可以将对象转换为字节序列,保存在磁盘中或网络传输。
2:使对象可以脱离程序运行而存在
注意点:实现Serializable接口,对象的类名,实例变量都会被实例化,引用类型变量必须也是可序列化的,反序列化需要class文件。同一个对象被多次序列化只有第一次会转换为二进制流,其他的都只保存序列化版本号。

23.泛型是什么?

1.5后就提出了泛化参数,有了泛型后,创建容器的时候指定容器为何种类型,可以在编译期间保证类型正确,不会留到运行期间,泛型的主要目的就是为了更好的创建容器。

24.什么是异常体系?

异常体系分为程序错误和异常(Error和Exception)
Exception分为受检时异常,非受检时异常。
错误和异常的区别
错误一般是程序出现了比较严重的问题,大多数可能与编程者编写的程序无关,可
能时代码运行时的jvm出现了问题。
异常:程序出现的可预测问题,可以恢复,通常时轻度或者重度。

25.谈谈IO流?

同步异步,阻塞和非阻塞?
一句话:同步异步是看调用者等结果不返回,还是先返回在通知。
阻塞和非阻塞就是看在这段时间里面能不能做其他事情。

同步:指用户发起IO请求后需要等待IO操作结束后才能继续指向其他的内容。
异步:指用户发起IO请求后仍然继续执行,当内核IO操作完成之后会通知用户线程,或者调用用户线程注册回调函数。

阻塞:指内核空间IO操作需要等待知道把数据返回给用户空间。
非阻塞:指的是IO操作被调用后会立即返回给用户一个状态值,无需等待IO操作彻底完成

BIO:一个连接一个线程(同步阻塞)
Acceptor线程监听客户端的连接,接受到客户端的请求后创建一个线程进行处理
处理完成之后,通过输出流返回应答用户,线程销毁。
–造成不必要的开销,严重会造成服务器内存泄露。

NIO:一个请求一个线程(同步非阻塞)
请求会注册到多路复用器Selector上,多路复用器轮询到连接有IO请求时才会
启动线程处理。
优点:单线程轮询事件的机制,通过高校的定位就绪Channel来决定做什么,仅仅 selecct阶段时阻塞的,可以有效的避免大量客户端连接,频繁切换线程带来 的问题,应用扩展能里得到了提高。
核心组件:Channel通道,Buffer缓存,selector选择器(监听多个通道事件)

与IO之间的区别: 1:多复路用的IO模型,多路复用效率更高。
2:标准的IO基于字节流和字符流来进行操作,NIO采用了通道和缓冲 区的形式以块的方式来进行处理数据,效率高。
3:通道可以是双向的,通道只能是单向的。

AIO:异步非阻塞(一个有效请求一个线程)
客户端的IO请求是都是有OS先完成的,在通知服务器应用区启动线程处理。

应用场景:并发数不多的时候建议使用BIO,因为他的编程和调试都非常简单。
并发数高的情况下使用 NIO或者AIO,更好的建议是使用成熟的网络通信 框架Netty。

26.Java为什么要分字节流和字符流?

一个字符等于两个字节。
字节流在处理的时候是逐个字节读取,读取汉字时会出现乱码。
音频,图片,媒体文件有=用字节流比较好一点。涉及字符的话建议用字符流好一点。

27.谈谈反射的理解?

概念:就是说程序在运行的时候动态的获取类的方法的属性信息。对于对象而言可以调 用他的任意方法和属性。提高代码的灵活度。

缺点:性能瓶颈,反射相当于一种解释操作,通知JVM要做的事,性能不如直接的Java 代码,动态改变类的属性加大了安全隐患。

28.谈谈class.forName()和ClassLoader之间的区别?

前者除了将类加载到jvm中,还会对类进行解析,执行类中的static块。
后者只负责加载到jvm中,并不会执行static代码块,只有调用newInstance()方法才
去区执行。

29.说说new和newinstance()之间的区别?

New创建对象的时候不需要将.class文件加载到JVM中。
Newinstance则需要先通过class.forName()和ClassLoader加载到JVM中才可以使用,而且只能创建无参对象。

30.谈谈注解在Java中的用处?

注解在Java中一般起到说明和配置的作用,注解不会影响代码的实际逻辑,只会对代
码起到辅助的作用。

31.浅谈注解的基本原理?

注解的本质时继承了一个Annotation的特殊接口,其具体实现类时JAVA中运行生成的动态代理类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值