java面向对象的特征,如何应用
- 面向对象编程是利用类和对象的编程思想
- 万物皆成类,对象是类的具体体现,面向对象的三大基础特性,继承封装多态。、
- 封装:封装隐藏了类的具体内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据,因为他对外只是提供了访问方法。
- 继承:Java中通过extends关键字实现继承。从已经有的类派生出的新类,新类能够吸收已有类的一些成员变量和方法,并且可以扩展新的方法,提高代码的复用性。关于子类能从父类中继承什么?子类不能继承父类的构造方法,私有方法(变量),
- 多态:堕胎表示当同一个操作作用在不体哦那个的对象时,会有不同的语义,从而产生不同的结果。在JAVA中主要有两种表现方式,‘方法的重载,方法的覆盖’
HashMap的原理是什么,jdk1.7和jdk1.8有什么区别?
-
- HashMap首先是通过哈希表和链表来实现的,具体的实现过程,拿到一个数据,首先计算他的hash值,然后找到对应的位置,如果为空就将该数据放在这里,如果该位置不为空,就将该数据放在链表头。如果容量达到某个阈值,会自动增长。Hash非线程安全的,即任意时刻可能有多个线程同时写HashMap,可能导致数据不一致的问题,我们可以用Collections的synchronizedMap方法时HashMap有更强的安全性,或者使用ConcurrentHashMap。
-
- 1.7
宏观来看,HashMap是一个数组,然后数组中每个元素是一个单项链表。当数组容量到达某个阈值的时候既可以扩容,扩容之后是当前数组大小的2倍。其中有一个负载因子。阈值就等于当前数组容量乘以负载因子
- 1.8
改进之处,将java7中的单向链表变成了红黑树,所以Java8的数据结构是数组+链表+红黑树构成,
为什么将红黑树引入呢?我们在java7中查找一个数据根据hash值就可以定位到在哪个链表中,然后顺着链表比下去,时间复杂度是O(N),所以我们引入红黑树,当链表中的元素超过8个的时候,就可以将链表转换成红黑树,改进之后的时间复杂度是O(logN).
ArrayList和LinkedList的区别
- ArrayList的底层是数据,他的查找通过索引就可以找到,速度快
- linkedList的底层是链表,查找的时间度是O(N)
- ArrayList的删除和添加会更慢,当ArrayList添加或者删除的时候,他会重新的标注索引,并且需要移动位置。
- LinkedList比ArrayList更加的占内存,因为LinkedList为每个节点存储了两个引用,一个只想前面一个元素,另外一个指向了后面的元素。
- 更加适合使用LinkedList
1, 当你的应用不需要随机访问,频繁的查找数据
2, 当你的应用有更多的插入和删除操作的时候更适合
jdk1.8的新特性有哪些?
- 接口的默认方法
Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可
2. Lambda表达式
3. 函数式接口
每一个lambda表达式都对应一个类型,通常是接口类型。而“函数式接口”
是指仅仅只包含一个抽象方法的接口,每一个该类型的lambda表达式都会被匹配到这个抽象方法。
接口和抽象类有那些区别?
- 不同
抽象类
-
抽象类中可以定义构造器
-
可以有抽象方法和具体方法
-
抽象类中可以定义成员变量
-
由抽象方法的类必须被声明为抽象类,而抽象类未必要有抽象方法
-
抽象类中可以包含静态方法
-
一个类中只能继承一个抽象类
接口
- 接口中不能定义构造器
- 接口中全都是抽象方法
- 接口中定义的成员变量都是常数
- 接口中不能有静态方法
- 一个类可以继承多个接口
怎么声明一个类不会被继承,什么场景下会用
如果一个类被final修饰,此类不能有子类,如果一个类中的所有方法都没有重写的需求,并没有子类,就可以使用final修饰
Java中的==和equals有那些区别?
- 最大的区别就是一个是运算符,另外一个是方法
==
:如果比较的是基本数据类型就是比较数值是否相等,如果比较的是引用数据类型,则比较的是对象的地址值是否相等- equals():用来比较方法两个对象的内容是否相等
注意:equals方法不能用于基本数据类型的变量,如果没有对equal方法进行重写,则比较的是引用类型的变量所指向的对象的地址
String StringBuffer StringBuilder区别及使用场景
- String是只读字符串,也就意味着String引用的字符串内容是不能被改变的。这个不能改变并不是指引用的对象不能改变,而是指对象里面的内容不能改变
- StringBuilder/StringBuffer表示的字符串对象可以直接进行修改
- StringBuilder 是 Java5 中引入的,它和 StringBuffer 的方法完全相同,区别在于它是在单线程环境下使用的,因为它的所有方法都没有被 synchronized 修饰,因此它的效率理论上也比 StringBuffer 要高。
Java异常处理
- 抛出异常:throw
- 捕获异常:try,catch,finally
- 声明异常:throws
常见的运行时异常
- 空指针异常
- 算术运算异常
- 下标越界异常
- 类型强制转换异常
常见的编译时异常
- 未发现文件异常
- 类为发现异常
- SQL异常
说一下你对Spring的理解?
Spring 使创建 Java 企业应用程序变得更加容易。它提供了在企业环境中接受 Java 语言所需的一切,,并支持 Groovy 和 Kotlin 作为 JVM
Spring支持各种应用场景, 在大型企业中, 应用程序通常需要运行很长时间,而且必须运行在 jdk 和应用服务器上,这种场景开发人员无法控
Spring 是开源的。它拥有一个庞大而且活跃的社区,提供不同范围的,真实用户的持续反馈。这也帮助Spring不断地改进,不断发展。
你觉得spring的核心是什么?
- spring是一个开源的框架
- spring是为了简化企业开发而生成的
- spring是一个IOC和AOP的容器框架
- IOC:控制反转
- AOP:面向切面编程
SPring的IOC实例对象的三种方式分别是?
- 构造方法
- 静态工厂
- 实例工厂
redis为何这么快?
- 基于内存
- 单线程减少上下文切换,同时保证了原子性
- IO多路复用
为什么采用单线程?
- 因为Redis是基于内存来操作,CPU不会成为Redis的瓶颈,而最有可能的是及其内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章的使用单线程的方案了。
缓存的三大问题
- 缓存穿透:缓存穿透是指当用户查询某个数据时,Redis 中不存在该数据,也就是缓存没有命中,此时查询请求就会转向持久层数据库 MySQL,结果发现 MySQL 中也不存在该数据,MySQL 只能返回一个空对象,代表此次查询失败。如果这种类请求非常多,或者用户利用这种请求进行恶意攻击,就会给 MySQL 数据库造成很大压力,甚至于崩溃,这种现象就叫缓存穿透。
- 缓存空对象,当MYSQL返回空对象的时候,Redis将该对象缓存起来,同时为其设置一个过期时间,当用户再次发起相同请求时,就会从缓存中拿到一个空对象,用户的请求被阻断在了缓存层,从而保护了后端数据库,但是这种做法也存在一些问题,虽然请求进不了 MSQL,但是这种策略会占用 Redis 的缓存空间。
- 布隆过滤器:布隆过滤器判定不存在的数据,那么该数据一定不存在,利用它的这一特点可以防止缓存穿透。
- 缓存空值
- key值校验
- 缓存击穿:缓存击穿是指用户查询的数据缓存中不存在,但是后端数据库却存在,这种现象出现原因是一般是由缓存中 key 过期导致的。比如一个热点数据 key,它无时无刻都在接受大量的并发访问,如果某一时刻这个 key 突然失效了,就致使大量的并发请求进入后端数据库,导致其压力瞬间增大。这种现象被称为缓存击穿。
- 改变过期时间:设置热点数据永不过期
- 分布式锁:上锁:当我们通过 key 去查询数据时,首先查询缓存,如果没有,就通过分布式锁进行加锁,第一个获取锁的进程进入后端数据库查询,并将查询结果缓到Redis 中。
解锁:当其他进程发现锁被某个进程占用时,就进入等待状态,直至解锁后,其余进程再依次访问被缓存的 key。
- 缓存雪崩:缓存雪崩是指缓存中大批量的 key 同时过期,而此时数据访问量又非常大,从而导致后端数据库压力突然暴增,甚至会挂掉,这种现象被称为缓存雪崩。它和缓存击穿不同,缓存击穿是在并发量特别大时,某一个热点 key 突然过期,而缓存雪崩则是大量的 key 同时过期,因此它们根本不是一个量级。
- 缓存雪崩和缓存击穿有相似之处,所以也可以采用热点数据永不过期的方法,来减少大批量的 key 同时过期。再者就是为 key 设置随机过期时间,避免 key 集中过期。(这里的永不过期指的是如果查询到这条数据,发现他过期了,缓存区就会向mysql服务器发送请求,但同时缓存区还是会把过期的数据返回)
Redis有那些数据结构?
- 字符串
- 字典
- 列表
- 集合
- 有序集合
什么是微服务?
MySQL的主从复制
Mysql的主从复制,就是将Mysql主数据库上的数据复制到从数据库上
- 主从复制的目的是未来实现数据库的读写分离,写操作和实时性较强的读操作则访问主数据库;度操作则访问从数据库,从而使数据库具有更加强大的访问负载能力,支撑更多的用户访问
我的那个秒杀功能是怎么实现的?
- 全局ID生成器,解决了自增的id的规律性太强
超卖问题,多线程安全的问题?
- 悲观锁:人文线程安全问题一定会发生的,因此在操作数据之前先获取锁,确保线程串行执行。例如Synchronized,lock都属于悲观锁。优点使简单粗暴,缺点使性能一般
- 乐观锁:认为线程安全问题不一定会发生,因此不加锁,只是在更新数据的时候去判断有没有卡线程对数据做了修改。如果没有修改则认为是安全的,自己才会去更新数据,如果已经被其他线程修改说明了安全问题,因此可以重试或异常。优点性能好,缺点使成功率低的问题
JVM跨平台原理
- 一次编译到处运行,每个操作系统都有JVM,但是可以执行同一份字节码文件
字节码的作用是什么?
代码-》字节码-》机器指令
- 编译成字节码,加快了解释成机器指令的速度。
JVM的整体结构
- 字节码-》类加载子系统-》方法区
- 程 序计数器不会出现内存溢出的情况