2022-JAVA面试必背

一、什么是面向对象?

1. 把具体的事物抽象成类,封装事物的特征。

2. 面向对象的特征:封装、继承、多态

封装:外部调用者无需关注内部细节

继承:子类继承基类的共同属性,并作出个性化扩展

多态:外部调用一个方法时,可以有不同的执行逻辑和结果,继承、重写、父类引用指向子类对象

二、JDK、JRE、JVM

JDK:java开发环境

JRE:java运行环境

JVM:java虚拟机

三、==和equals

==是运算符,对比的是栈中的值,equals比较的是对中对象的内存地址

常见于与String相关的笔试题,Object类提供的equals方法底层使用的是==,而String类重写了equals方法,没重写就是比地址,重写了就是比值

例如

str1在常量池中指向“Hello”,str2在常量池和堆空间中都创建了对象,str3指向了str2的引用(内存地址),所以

str1 == str2 str1在常量池中,str2在堆空间中,==比地址,false

str1 == str3 str1在常量池中,str3在堆空间中,==比地址,false

str2 == str3 str2在堆空间中,str3在堆空间中,str2传递引用给str3,==比地址,true

str1.equals(str2) 已重写,equals比较值,str1=“Hello”,str2=“Hello”,true

str1.equals(str3) 已重写,equals比较值,str1=“Hello”,str3=str2,true

str2.equals(str3) 已重写,equals比较值,str3 = str2,true

四、final

1.用法

修饰类:这个类不能被继承

修饰方法:这个方法不能被重写,但能重载

修饰变量:修饰基本数据类型时,这个变量不能被修改;修饰引用类型时,不能更改引用,可以更改属性值

2.成员变量声明时要赋初值,局部变量使用前要赋初值

3.局部内部类和匿名内部类只能访问外部的final变量(lamda表达式),因为

五、String、StringBuffer、StringBuilder

StringStringBufferStringBuilder
有啥用创建和操作字符串
有啥区别创建的字符串不能修改,只会修改引用可以修改字符串内容单线程
线程安全线程安全线程不安全
性能等级321
使用场景多线程共享变量使用优先使用

六、重载和重写

重载:同一个类中,方法名必须相同

重写:父类和子类中,方法名、参数列表必须相同,访问修饰符和返回值类型要小于父类

private和protected不允许重写

七、接口和抽象类的区别

语法上:

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

2.接口中的成员变量只能是public static final ,抽象类中随便

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

使用场景上,接口更偏向于做什么,抽象类偏向于事物的本质是什么

八、List和Set的区别

List:有序,可重复。

Set:无序,不可重复;只能用Iterator取出所有元素。

九、hashCode和equals

1.hashCode()获取到一个int型的hashcode,这个哈希码的作用是确定该对象在哈希表中的索引位置,哈希表存储的是散列结构即k-v,能够通过key快速检索对象在堆空间的位置。

2.在存储数据时,发生hash冲突时会调用equals检查两个对象是否相同。

十、ArrayList和LinkedList

ArrayList:数组队列,在内存中是连续的存储空间,随机访问速度较快,适合做查询操作。扩容时,新建一个数组,把老数组的数据拷贝过去

LinkedList:双向链表,可以在内存中分散存储,需要遍历,适合做插入和删除操作,遍历时使用迭代器Iterator,如果在循环中使用get(i)方法,每次循环都遍历一次,极其消耗性能

十一、HashMap和HashTable

HashMapHashTable
线程安全不安全安全
key允许为null不允许为null
底层结构数组+链表+红黑树,jdk8中,当数组长度超过64,链表长度达到8,链表就会转化为红黑树

存储过程:

(1)计算key的hashcode

(2)根据hashcode计算元素在数组中的索引

(3)如果发生hash冲突,进行equals比较,相同取代,不同插入则链表

(4)如果key为null,,存在下标为0的位置

底层主数组如何扩容?

和ArrayList扩容机制一样,但加入了加载因子=0.75

十二、ConcurrenHashMap

线程安全的HashMap,替代HashTable,因为不仅线程安全,效率还更高

jdk7

底层结构:ReentranLock + Segment + HashEntry,一个Segment中包含一个HashEntry数组,每个HashEntry又是一个链表

Segment是分段锁。继承了ReentranLock,锁定操作的Segment,其他Segment不受影响,并发数为segment的个数,可以通过构造函数指定,数组扩容不会影响其他segment。

HashTable操作时会整个锁起来,ConcurrenHashMap里有许多的Segment,互不影响。

查询是会二次hash,第一次定位Segment位置,第二次定位到元素所在的链表头部。

jdk8

底层结构:synchronized+CAS(乐观锁)+Node+红黑树,Node的value和next都用volatile修饰。

替换、查找、赋值操作都是用CAS。读操作是无锁的。

十三、如何实现一个IOC容器(控制反转)

思路:

(1)配置文件配置包扫描路径

(2)定义一些注解,比如说@Controller、@Service、@Mapper、@Autowire等

(3)从配置文件中获取需要扫描的包路径,获取这个路径下面的文件信息,把已.class结尾的文件添加到Set集合中

(4)遍历这个Set集合,获取在类上有指定注解的类,并交给IOC容器,定义一个安全的Map来存储这些对象

(5)遍历这个IOC容器,获取到每个类的实例,判断是否有依赖其他类的实例,然后递归注入

十四、字节码

字节码是jvm能够识别解释的文件,任何操作系统上只要安装了jvm,就可以执行任何.class文件。使用字节码的好处是跨平台、可移植的优点。

十五、类加载器

JDK自带三种类加载器:bootStrap ClassLoader、ExtClassLoader、AppClassLoader

bootStrap ClassLoader负责加载%JAVA_HOME%lib下的jar包和类文件

ExtClassLoader负责加载%JAVA_HOME%lib/etc下的jar包和类文件

AppClassLoader负责加载classpath下的类文件,即程序员自定义的类库

继承ClassLoader可以实现自定义类加载器

十六、双亲委派模型

就是向上委派,向下查找

每一个类加载器执行后,都会将加载过的类放进缓存,子加载器在加载新类时,先向上查找缓存有没有被加载过,如果没有,就查找自己的加载路径,如果还没有就向下继续查找加载路径。

向上直到顶层为止,向下直到发起加载的加载器。

好处:

(1)安全,避免用户自己编写的类替换了java核心类,比如String

(2)防止类重复加载,jvm中区分不同类,不仅是根据全路径类名,相同的class文件背不同的classLoader加载就是两个不同的类

十七、JAVA异常体系

所有的异常都来自顶级父类:Throwable

Throwable下面有两个子类:Exception、Error

Error:程序无法理解的错误,发生这类错误程序立刻停止运行

Exception:分为两种,RunTimeException运行时异常,发生时线程停止运行;和CheckedException检查异常,发生时编译不通过

十八、GC如何判断对象可以被回收

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值