-
什么是jdk,jre,jvm?
1.1 jdk称为java开发工具 包含了jre…并且jdk的api
适合开发使用
1.2 jre称为java运行环境 包含了jvm…jre用于运行java
程序.
1.3 jvm称为java虚拟机 java程序运行的编译,运行的内存
分配…都是jvm来完成的
jdk包含jre包含jvm
-
== , equals区别?
2.1 原生类的== 比较值,且没有equals方法. 强类型的== 比较的是地址值.
2.2 equals方法默认为Object类的方法, 如果不重写, 其实现默认也为 == 判断.
2.3 String类已经重写了Object类的equals方法, 其实现为逐个比较字符,
也就是比较字符串的内容是否相等.
2.4 java建议重写equals的时候, 也重写hashcode方法.
因为jdk中带hash算法的对象, 底层会用到hashcode和equals来共同确认一个对象
是否重复/相等.
-
java程序的运行原理, 为什么能够跨平台?
3.1 跨平台指程序可以在不同的操作系统上运行…
3.2 java程序首先将.java文件编译为 .class字节码文件
3.3 该字节码文件可以运行在不同的操作系统上
3.4 因为不同的操作系统上有对应该操作系统的jvm,
会去把.class翻译为对应平台能够识别执行的机器码…总结: 先把.java文件 编译 为.class文件,
再把.class文件 翻译 成机器码,
再执行机器码…
-
包装类和基本数据类型的区别?
4.1 包装类可以为null ,原生类不可以为null.
4.2 包装类默认实现了一些方法,方便使用. 原生类没有方法.
4.3 包装类属于强类型, 引用传递. 原生类属于值传递.
(PS:如果包装类要和原生类比较数据, 那么按原生类比较,因为原生类没有地址.)
-
static关键字的作用
5.1 static可以修饰内部类,方法,属性,代码块,静态导入.
5.2 static修饰的属性和方法它们属于类的.不依赖对象.
且只有一份空间. 多个地方调用会有数据共享安全的问题.
一般在属性上面加上final使其只读.
5.3 static会最先执行.不需要依赖实例.
5.4 static不可以直接调用实例方法. 实例方法可以直接调用静态方法
-
重写和重载的区别?
6.1 重载发生在同一个类中, 方法名相同, 参数类型/列表个数不同,
和方法签名的其他任何关键字无关.
6.2 重写发生在子类继承父类的关系中, 方法名相同, 参数类型/列表也要相同,
权限访问修饰符不能比父类更严格(小);
返回值类型必须和父类相同或是父类返回值类型的子类/实现类.
声明的异常不能比父类更大
-
final修饰类: 该类不允许被继承
final修饰方法: 该方法不可以被重写,可以重载.
final修饰属性: 该属性的值不能变. 如果是强类型,
那么该地址值指向的对象里面的属性值是可变的.
-
instanceof的作用?
判断某个变量是否为某种类型.
应用场景: 不同的子类拥有不同的行为方法.
当使用父类作为变量引用子类对象的时候,要调用子类独有的方法,要先做
instanceof判断, 再强转回对应的子类调用该子类的独有方法…
如果不判断直接强转,可能会抛出ClassCastException(类型转换异常)
-
try中有return, finally会不会执行
9.1 必须执行
9.2 在return的中间执行
9.3 return的值会在临时空间, 然后去执行finally
9.4 如果finally中没有新的return, 那么最终返回的还是try里面的值
9.5 如果finally中有新的return, 那么会覆盖临时空间的值, 最终返回
finally里面的值
-
异常的理解?
一. 结构:
java中异常的基类为
Throwable
Exception
RuntimeException运行时异常
Null,Index…
!Runtime…(CheckedException)检查性异常
Error
错误
指编译错误的代码,内存溢出,硬件故障…等不可抗力错误.
程序自身一般无法修复.
-
运行时异常RuntimeException
2.1 该异常在程序运行的时候可能会抛出的异常,该异常jvm不要求一定处理.
(程序员可以选择处理或不处理)
3. 检查性异常"CheckedException"
3.1 该异常要求程序员必须处理的异常. 否则编译不通过.番外: 什么是处理? 处理的意思trycatch或继续往外声明throws
二. throws和throw的含义?
throws声明异常: 告诉调用方,我这个方法可能会抛出(报错)一个这样的异常.
当抛出的异常为检查性异常,那么调用方必须处理,或继续往外声明.
throw抛出异常 程序本来不报错的,手动让它报一个我们指定的异常
- 数据结构之线性表:
ArrayList顺序存储, 底层实现是数组,其内存地址空间是连续的,
可以通过地址索引直接定位到节点,所以访问效率高.
但是在靠前或中间的位置插入效率低, 因为被插入的后面所有的
节点都要往后移动.
LinkedList链式存储 该数据结构为双向链表, 每一个节点保存了前后节点的地址值.
所以在插入的时候,影响的节点只有前后两个节点, 性能高效.
但是读取非头尾数据效率较低. 适合频繁插入数据使用.
- hashCode方法的理解?
本地方法, 默认系统返回的逻辑地址. 该值可能重复.
- HashMap底层实现原理?
- HashMap底层采用数组加链表(单向)方式实现.
- 通过key的hashcode找到要存储的数组的具体位置.
- 判断该位置是否为null, 为null直接存储.
不为null,那么调用key的equals方法判断和已经存在的对象的key是否相等,
如果相等则覆盖,并且返回old值. 不相等则代表出现hash冲突,则接入到已存在节点的next的位置.(链表实现) - 当hash冲突的节点到达8的时候, 链表转为红黑树(因为小于8的时候,链表的时间查找复杂度性能比红黑树的要高)
- get的时候通过hashcode找到要存储的位置, 如果该位置为null,则返回null.
如果不为null,则调用equals和已经存在的节点的key判断是否相等, 相等则返回value.
不等则遍历链表的.next, 和下一个节点的key判断,以此类推, 找到后返回value;
15.
1). 内部比较器Comparable是写在要被排序的类上,实现并重写compare方法.
该方式统一了排序策略, 即所有地方的排序, 都按该默认策略排序.
2). 外部比较器Comparator是在Collections.sort方法,传入的. 适用于单独的比较.
每个不同场景,可以使用不同的排序策略排序.
- 创建多线程 3三种.
1). 继承Thread类
2). 实现Runnable接口
3). 实现Callable接口
加线程池4种- 单例线程池 SingleThreadExecutor
应用场景: 任务量不大, 然后不能影响主线程的时候. - 固定数量线程池 FixedThreadPool
应用场景: 任务量较大的时候. - 不限定数量/缓存线程池 CachedThreadPool
- 周期任务线程池(类似于setInterval)
- 单例线程池 SingleThreadExecutor
-
线程状态
新建, 就绪, 运行中, 等待/阻塞 , 死亡
-
解决线程安全问题?
- 多实例, 每个线程单独使用单独的实例(如果场景允许),
缺点比较耗资源 - 使用局部变量, 局部变量没有线程安全的问题.
- 使用synchronized同步锁, 或Lock对象
- 本地线程
- synchronized
在实例方法上的时候, 同步锁的对象为 this
在静态方法上的时候, 同步锁的对象为 类.class
- 什么是死锁?
一般发生在同步嵌套中, 多个线程相互等待对方释放同步对象.
或使用Lock对象的时候忘记释放锁,导致其他线程无法获取.
1.使用Lock对象的tryLock
2.可能发生死锁的代码块都按同一顺序加锁
- synchronized和Lock区别?
1.synchronized是java内置关键字,在jvm层面,Lock是个java API编程;
2.synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;
3.synchronized会自动释放锁,Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁;
4.synchronized获取不到锁会一直等待下去,而Lock可以尝试获取,如果获取不到锁,线程可以执行其他代码块或结束运行;
5.synchronized为非公平锁, 可能导致线程饥饿现象. Lock对公平/非公平锁都支持.
- sleep,yield和wait的区别?
1.sleep 属于 Thread类的静态本地方法. 需要指定睡眠的时间.
在此时间内,不会释放对象锁. 时间到,进入就绪状态,等待CPU调度执行.
2.wait 属于 Object类的实例本地方法. 可选择指定或不指定等待的时间.
持有锁对象的线程调用此方法,会释放对象锁, 并进入等待状态.(否则无法释放对象锁的线程调用则会抛出非法监视器状态异常)
需要被其他线程唤醒,才能进入就绪状态.
(如果wait指定了时间, 那么到达指定时间后, 进入等待锁池队列,重新尝试获取锁对象,获取到后会进入就绪状态,被CPU调度后,
,然后执行)
3.yield 代表退让, 意为让出cpu资源给同优先级的线程以执行机会
属于Thread类的静态本地方法.
效果和sleep类似, 只是时间由虚拟机来控制.
不会释放对象锁. 调用后进入就绪状态.
总结: yield和sleep可以在普通和同步方法中. wait必须运行在同步中.
- join方法的作用?
阻塞当前位置, 直到调用join的线程执行完毕才往下执行.
- interrupt
打断, 逻辑上中断一个正在执行的线程(非暴力).
给收到interrupt的线程设置一个boolean的标志为true,线程可以判断后手动结束.
如果该线程正在阻塞/等待中, 那么会抛出一个interrupt的异常…并重置isInterrupt
为false;
- volatile关键字的作用?能否保证线程安全?
1.volatile只能修饰属性, 期保证多线程运行间, 线程获取的属性是最新的.
不加的话,线程的独立空间会有缓存的值.
2.防止指令的重排序
3.不能保证安全,有…参考上面去.
25. 什么是IO? 什么是缓冲区?
1.IO 分为 输入流和输出流
输入流和输出流又细分为 字节流和字符流.
字节流一般用于操作文件, 对应的基类为InputStream和OutputStream
字符流一般用于操作文本, 对应的基类为Reader和Writer
2.缓冲区的作用是减少程序直接访问介质的次数,提升读写效率和性能.
缓冲区分为: 输入缓冲区和输出缓冲区. 使用输出流的缓冲区需要在结束前调用flush
方法把缓存中的数据写出去.
26.
什么是同步,异步? 阻塞,非阻塞?什么是BIO,NIO,AIO?
1.同步:客户端发送请求到服务器,假设服务器处理请求需要N秒时间,
那么客户端会一直等待.(无法做其他任务)
2.异步: 客户端发送请求到服务器, 假设服务器处理请求需要N秒时间,
那么客户端不会等待,可以先做其他任务.服务器响应后,会执行回调处理结果.
3.阻塞: 服务器只能处理一个客户端请求,处理完后接受第二个请求.
4.非阻塞: 服务器同时接受多个请求.
IO为分BIO, NIO, AIO
BIO 同步阻塞 客户端和服务器一对一交互. 效率较低.
NIO 同步非阻塞 客户端和服务器多对一交互. 服务器效率提升.
AIO 异步非阻塞 客户端和服务器多对多交互. 性能卓越.
- 什么是序列化? 怎么实现?
1.序列化就是把程序中的对象写入到临时存储或持久化的过程.
反序列化就是把临时存储和持久化的内容,反向写入程序中的过程.
2.实现序列化需要实现Serializable接口. 反序列化需要对比版本号.
每次修改版本号会变更.
3.static变量和transient修饰的属性不会被序列化.
4.通过Serializable接口实现的反序列化,
不会执行自身的构造器.但是会执行父类无参构造.
-
创建对象有几种方式?
1.new(执行构造) 2. 反序列化(Externalizable执行构造,seri…不执行)
3.反射(执行构造) 4. 克隆.
-
什么是反射?
1.在运行期间.
给任意一个类(com.seecen.pack.className),反射可以获取到该类的属性和方法
给任意一个对象,反射可以执行该对象的方法和获取该对象属性的值.
给任意一个类的路径, 可以创建该类的实例
2.有什么作用?应用场景?一般什么时候考虑使用反射呢?
使用在通用的模块上.
-
什么是socket?
套接字, 分为tcp和udp协议.
客户端和服务器端的长连接的通信. -
浅拷贝和深拷贝?
1.浅拷贝只拷贝对象本身,对象里面的组合对象直接是引用,赋值,没有创建新的对象,属于引用传递
2.深拷贝即拷贝对象本身,也拷贝对象里面的对象
-
tcp和udp?
1.tcp需要三次握手,四次挥手,需要建立连接,基于连接状态,udp无连接
2.tcp的数据更安全,也有序 udp不安全,可能丢包
3.tcp性能较低。udp性能更高
4.udp比tcp更适合传输数据量较大的情况
-
java内存区域(jvm内存模型)
属于内存的共享内存部分:
1.方法区(永久代)(元空间jdk1.8,直接使用内存,高效,避免OutOfMemoryError)
类,元数据,静态资源,常量池。。。
2.heap堆
new出来的对象
属于线程独享的内存部分:
1.程序计数器 记录每个线程的运行的行号位置。。。该区域是唯一不会抛出内存溢出异常的地方
2.虚拟机栈
2.1 局部变量表 存储方法运行的局部变量 如:方法中的变量和形参
2.2 操作数栈 存储变量使用运算符运算的结果 如:int c =a+b
2.3 动态/静态链接 对于static或者普通没有重写的方法使用静态链接方式保存方法调用链
对于重写,在编译器无法确定的,需要在运行期才能确定的方法,采用动态链接方式保存
2.4 方法的返回地址 记录方法返回后执行的位置
3.本地方法栈
原理参考虚拟机栈,只是该区域保存的方法都是native方法
- java内存模型:
主内存:java虚拟机规定所有的变量(不是程序中的变量)都必须在主内存中产生,为了方便理解,可以认为是堆区。可以与前面说的物理机的主内存相比,只不过物理机的主内存是整个机器的内存,而虚拟机的主内存是虚拟机内存中的一部分。
工作内存:java虚拟机中每个线程都有自己的工作内存,该内存是线程私有的为了方便理解,可以认为是虚拟机栈。可以与前面说的高速缓存相比。线程的工作内存保存了线程需要的变量在主内存中的副本。虚拟机规定,线程对主内存变量的修改必须在线程的工作内存中进行,不能直接读写主内存中的变量。不同的线程之间也不能相互访问对方的工作内存。如果线程之间需要传递变量的值,必须通过主内存来作为中介进行传递。
这里需要说明一下:主内存、工作内存与java内存区域中的java堆、虚拟机栈、方法区并不是一个层次的内存划分。这两者是基本上是没有关系的,上文只是为了便于理解,做的类比
- 垃圾回收算法:
jvm采用GC ROOT可达性算法确定要被回收的对象后,采用以下的算法进行回收如何判断对象是否存活/死活
JVM之GC算法、垃圾收集算法——标记-清除算法、复制算法、标记-整理算法、分代收集算法
1.标记-清除算法
2.复制算法
3.标记-整理算法
4.分代收集算法---->新生代采用复制算法,老年代采用标记-整理算法
关于JVM中Eden区、Survivor from区和Survivor to区的理解
-
什么是强引用,软引用,弱引用,虚引用
1.平时直接=赋值的对象,对象不可达才会被回收
2.软引用(SoftReference):内存不足,gc执行的时候会强制执行
3.弱引用(WeakReference):只要GC执行就会被回收
4.虚引用(PhantomReference):get始终返回null,虚拟的引用
-
GC是什么?什么时候执行?
1.GC为java中的一个守护线程,作用于垃圾回收
2.GC不确定在什么时候运行
3.程序员可以手动通知GC执行(system.gc()),但不保证一定执行(没人确定什么时候执行)
-
final、finally、finalize区别?
final:修饰类不可继承,方法不可重写 属性的值不可变(引用类型里面的属性可变)
finally:表示一定会执行的代码块,除了执行exit方法
finalize:GC在回收对象的时候,会先调用该被回收对象的finalize方法,但是只会被调用一次(我们通过在finalize中重新让对象可达,可第一次不被回收)
数据库篇
1.有哪些数据库类型:
1.1 关系型数据库:mysql、oracle、sqlsever、access、db2、postgresql
其中:mysql、access、postgresql开源免费
oracle和db2收费并且适用于大型商业应用项目
1.2nosql数据库:redis,memcached,mongodb
三大范式:
三大范式
第一范式(确保每列保持原子性)
第二范式(确保表中的每列都和主键相关)
第三范式(确保每列都和主键列直接相关,而不是间接相关)
2.关系型数据库使用的语言是什么
SQL:结构化查询语言
sql有分为:
1.DQL 数据查询语言 select
2.DDL 数据定义语言 create/alter/drop
3.DCL 数据控制语言 grant/revoke
4.DML 数据操纵语言 insert/update/delete
3.sql执行顺序:
from >where >group by>having>select>order by
4.IN,EXISTS,NOT IN,NOT EXISTS区别?
当主查询的结果集较大,子查询的结果较小,尝试使用in提升效率
反之,主查询结果较小,子查询的结果较大且含有索引,使用exists
not exists的子查询会用到索引,索引建议使用not exists代替not in
5.有哪些表连接的方式,区别是什么?
1.内连接:
主表和次表条件满足的,会显示,不满足/匹配的,都不显示
2.外连接:
左外连接:主表数据全部显示,次表数据满足/匹配的显示,不匹配的显示为null
右外连接:次表数据全部显示,主表数据满足/匹配的显示,不匹配的显示为null
全外连接:主次两张表数据全部显示,主次匹配的显示数据,不匹配的显示null
3.交叉连接:主表和次表产生笛卡尔积,即A*B的数据条数
6.union和union all的区别?
两个都是获取两个表的并集,union会默认去除重复行,而且排序。
union all的性能比union要高,不会去重,也不会排序,就是简单的直接合并
7.delete,truncate、drop的区别?
delete会记录日志,可回滚恢复;truncate截断表,不记录日志,不可恢复
delete删除速度慢,truncate删除速度快
delete可以加删除条件,truncate不能,只能全表删除
drop是连带表结构/定义和数据都删除,不可恢复
delete属于DML语句,truncate和drop属于DDL语句