导图社区 JAVA 校招面试 基础
这是一篇关于JAVA 校招面试 基础的思维导图,想要了解JAVA校招面试的同学们可以先来参考一下此图。
编辑于2021-12-27 11:37:38JAVA
设计模式
单例模式
特点
从系统启动到终止,整个过程只会产生一个实例。
分类
饿汉式
但是由于他在类加载时就进行初始化,容易浪费内存,但他是线程安全的,它基于类加载机制避免了多线程的同步问题,也因为没有加锁,所以执行效率会提高。
懒汉式
懒汉式默认不会实例化,什么时候要用,就什么时候初始化。所以这种模式是非线程安全的。因为有可能很多线程来访问实例的时候,懒汉式还没有把这个实例new出来,导致有多少线程就会new出多少个实例,也因此,懒汉式需要加锁,所以他的性能不如饿汉式
异常处理
概述
程序执行中发生的不正常情况,不是开发过程中的语法错误和逻辑错误
分类
Error
JVM无法解决的严重问题
JVM系统内部错误、资源耗尽
无法预防解决处理
Exception
编译时异常
IO
FileNotFound
ClassNotFound
运行时异常
数组下标越界、空指针、输入类型异常
处理方法
抛
一旦出现异常,就会在异常代码处生成一个对应异常类的对象,并将此对象抛出
一旦抛出异常对象,其后的代码就不再执行了
抓:异常的处理方式
try-catch-finally
预先写好catch方法,自行处理
finally方法体中写的是一定会执行的代码
throws+异常类型
常见异常举例
空指针
调用的对象、数组为空
数组下标越界
输入类型异常
要求用户输入整型,用户给我输了个字母
类的成员
成员变量
成员方法
内部类
成员内部类
分类
静态
非静态
内容
可以定义属性、方法、构造器等
局部内部类
方法内
代码块内
构造器内
多线程
生命周期
新建
被声明并创建
就绪
线程被start(),但是还没被分配到资源
可能因为yield()方法等,失去CPU执行权而返回
notify()/notifyAll()
sleep()时间到,返回就绪态
获取同步锁
运行
获得CPU资源,开始运行
执行run()方法中的内容
阻塞
在特殊情况下,被人为挂起,或者执行IO操作时,由CPU临时中止线程的执行
由运行态进入阻塞态
如果无法恢复运行,就出现了故障
sleep()
join()
a调用b的join(),a阻塞
join()结束,返回就绪态
wait()
等待同步锁
死亡
完成全部工作后终止,或因被强制中止或出现异常导致结束
线程的安全问题
写冲突
当多个线程同时共享,同一个全局变量或者静态变量,做写的操作时,可能会发生数据冲突问题,做读操作时不会发生数据冲突问题的。
死锁
两个线程之间相互等待对方占用的资源,但又不肯让出自己的,都想自己先执行,最终导致谁都无法执行
活锁
正在运行的线程并没有阻塞,它始终在运行中,却一直得不到结果
队列的重试机制导致错误消息被不断地重试,致使线程忙碌却无法完成
饥饿
线程需要某些资源时始终得不到,尤其是CPU 资源,就会导致线程一直不能运行而产生的问题
可能是优先级导致长时间无法得到CPU资源,也可能是因为需要的锁被其他线程长期占用导致了饥饿
安全问题的解决办法
隐式锁
将方法或代码块用synchronized修饰
显式锁
显式定义同步锁对象来实现同步
锁提供了对共享资源的独占访问,线程开始访问共享资源之前需要先获得Lock对象
各线程方法
sleep、wait
都可以使线程阻塞
sleep方法定义在Thread类中
使用比较随意,想让线程休眠就可以调用
不会释放锁
wait方法定义在Object类中
需要在同步方法、同步代码块中使用(由同步监视器调用)
会释放锁
常用类
String
不可变
每次对String类型的修改,其实都等于新建了一个String对象,然后将指针指向新的String对象。效率低下、浪费内存空间
StringBuilder
可变,线程不安全,效率较高
适用于单线程需要大量修改数组的情况
特别的是,StringBuilder类在创建时不可以空赋值
StringBuffer
可变,线程安全,效率较低
适用于多线程需要频繁修改的情况
可变是在栈上进行的复制操作,没有到堆中
集合类
List
特征
存储有序的、可重复的数据
分类
ArrryList
优点
由于是采用数组形式进行存储的列表,所以便于随机访问,但是插入和删除时
LinkedList
优点
基于双向链表
便于元素插入和删除,而在随机访问时效率较低。
Vector
优点
线程安全,常用于存储大量数据
Set
特征
Set接口要求存储无序、不可重复的数据
分类
HashSet
HashSet是Set接口的主要实现类,它是线程安全的,并且可以存储Null值
LinkedSet
TreeSet
Map
特征
他是双列集合,存储一个键值对
没有重复的Key,全都是唯一且无序的
每个key只能对应一致Value,但是一个Value可以对应多个Key
分类
TreeMap
LinkedHashMap
HashTable
线程安全
HashMap
原理
HashMap是用哈希表(直接一点可以说数组加单链表),也就是用了拉链法的哈希表
因为拉链法本身的问题,即时哈希函数和负载因子设计得再合理,也难免会出现拉链过长的情况,而这会导致HashMap的性能下降
在JDK1.8之后,HashMap引入了红黑树结构,一般来说,当链表长度超过8以后,会将链表转换为红黑树,利用红黑树高效增删改查的特性来优化性能。
拉链法是对哈希冲突的一种处理办法,当出现哈希冲突的时候,冲突的数据将会保存至一个单向链表当中,并把链表的头结点保存在哈希表内,而这种链式结构,在链表长度过长时,势必会导致数据查询性能的下降
方法重写
要求
方法名、参数列表必须相同
访问权限不能小于父类被重写的方法
子类无法重写父类中为private权限的方法
返回值类型不能大于父类被重写的方法
方法重载
定义
在同一个类中,允许存在一个以上的同名方法,只需要他们的参数个数或者参数类型不同即可
两同一不同:在同一个类,有同方法名;参数列表不同(不同参数类型或参数个数)
面向对象的理解
对比
面向对象,将功能封装进对象,强调具备了功能的对象,以类/对象作为最小单位,强调由谁来做
面向过程强调的是功能行为,以函数为最小单位,考虑怎么做
总结:面向对象,是将过程、功能封装进对象中,由对象去使用
思想
抽象、分类、继承、聚合、多态
实践
当我们考虑用面向对象编程时,我们第一要找出问题中涉及的行事主体
第二要抽象出他们各自具备的属性、行为、功能
优点
易维护
面向对象的设计思想更接近生活思维,这样设计出来的代码可读性高,同时,由于继承的存在,局部模块的维护是比较方面的
质量高
主要体现在可重用性好,模块移植性强
易扩展
面向对象继承、封装、多态的特性
封装
定义
封装就是隐藏对象的属性和实现细节,仅对外公开接口
目的
增强安全:以特定的访问权限来使用类的成员。
简化编程:使用者不必了解具体的实现细节,而只是要通过外部接口,
实现方法
控制属性、方法的读和修改的访问级别
继承
定义
继承就是子类继承父类的特征和行为
继承机制允许创建分等级层次的类
目的
提高代码复用率,提高编程效率
为多态的实现提供了基础
多态
实现前提
存在继承关系
子类要重写父类的方法
父类数据类型的引用指向了子类对象:Animal am=new Cat()
语句在堆内存中开辟了子类Cat的对象,并把栈内存中的父类(Animal)的引用指向了这个Cat对象。
多态成员访问的特点
主要是可以运行子类重写的父类方法
成员变量
编译看左边(父类),运行看左边(父类)
成员方法
编译看左边(父类),运行看右边(子类),实现动态绑定
静态方法
编译看左边(父类),运行看左边(父类)
静态和类相关,算不上重写,所以访问还是左边的,只有非静态成员的方法,编译看左边运行看右边
缺点
父类引用不能使用子类特有的属性和方法
把这个父类引用强制变回子类类型。这样他就是子类类型的引用了,指向的也是子类对象了
很容易设计出高内聚、低耦合的系统结构,这就使系统变得更加地灵活、易于扩展
关键字
super
this
final
适用范围
类、对象、变量
作用
使其不可修改
修饰类时,该类不可再被继承
String、System、StringBuffer
修饰方法时,表示该方法不可被子类重写
修饰变量时,使其不可被修改
abstract
适用范围
类、方法
作用
使类不可实例化
抽象类与抽象方法
定义
抽象类
不可以实例化
有对象构造器
构造器可以被子类调用
抽象方法
只有方法的声明,没有方法体
包含抽象方法的类,一定是一个抽象类,反之却未必
子类必须重写了父类中所有的抽象方法后,该子类才可实例化,否则也是抽象类
接口
作用
实现多重继承
内容
全局常量
抽象方法
有方法声明,无方法体,继承接口的类必须将这些抽象方法全部实现才可以实例化
静态方法
默认方法
没有构造器
抽象类有,接口没有
构造器用于初始化成员变量,接口没有,只有全局常量
类可以实现多个接口,如果多个接口都有自己的构造器,容易冲突
接口本身只是 一个规范,一个标准,不需要考虑具体实现,所以有没有构造器意义不大
使用方法
让类去实现(implments)