纸上得来终觉浅,绝知此事要躬行
先从java基础来说:
一、java面向对象的三大特性,他们分别的含义是什么?
封装:
概念:封装,即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别;将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。在电子方面,封装是指把硅片上的电路管脚,用导线接引到外部接头处,以便与其它器件连接。(来自百度)
在将成员属性封装之后,我们应该提供相应的get/set方法进行访问此成员属性.
封装的好处是:属性进行了隐藏,不再是暴露在外的数据,使数据更加的安全可靠.
继承:概念:继承即从已有的类中派生一个新的类,已有的类成为父类(基类,超类),而派生的类成为子类(派生类).若类B继承了类A,则我们把类A称为类B的子类,反之同理,子类可以拥有自己本身的特有方法以及特有属性,而父类则必须是子类的共性抽取.如动物都有颜色,年龄,其颜色和年龄就是其共性
多态:
概念:同一个行为,对于传入不同的对象,实现不同的动作 多态需要记住的一个概念:父类引用指向子类对象
多态的好处:提高了代码的可复用性.
二、==和equals的区别
== 是用来比较两者引用内存地址是否相同,而equals是来比较两者值是否相同,而在object中equals就相当于==,但是String对其做了重写。
三、String 、StringBuffer、StringBuilder
String 是final的,你加一个字符串,其实是创建一个新的对象
StringBuilder 是线程不安全的,性能高
StringBuffer 是线程安全的,因为它的方法都有synchronized修饰,因此性能低
如果你需要经常修改字符,你可选择
StringBuffer或StringBuilder
四、ArraryList与LinkedList的区别
首先底层上的区别: ArraryList 的底层是动态数组形式,ArrayList可以存储不同类型的数据,扩容机制:因为数组长度固定,超出时需要创建新的数组,使用尾插法并且指定初始容量可以极大的提升性能
LinkedList底层是链表形式,适合做增删操作,不合适做查询,并且只能用iteartor来遍历
五、HashMap的特性与底层原理
HashMap特性:非同步,线程不安全、无序,key值不可重复,允许为null
基于hashing的原理,jdk8后采用数组+链表+红黑树的数据结构。我们通过put和get存储和获取对象。当我们给put()方法传递键和值时,先对键做一个hashCode()的计算来得到它在bucket数组中的位置来存储Entry对象。当获取对象时,通过get获取到bucket的位置,再通过键对象的equals()方法找到正确的键值对,然后在返回值对象。
六、如何实现一个IOC容器
1、配置文件配置包扫描路径
2、递归包扫描获取.class文件
3、反射、确定需要交给IOC容器管理的类
4、DI依赖注入
七、什么是spring?
Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。
它是一个容器框架,用来装javabean(java对象),中间层框架(万能胶)可以起一个连接作用,比如说把Struts和hibernate粘合在一起运用。简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
八、什么是IOC(控制反转)和什么是AOP
首先说AOP:AOP是一种面向切面的一种编程方式、例如我们的业务核心代码需要处理异常或者处理日志,这时我们就可以运用到AOP,还有什么遇到权限的时候都可以运用到AOP
再说IOC:所谓控制反转,就是把对象交给容器去处理
容器概念、控制反转、依赖注入
九、简述JDK8的新特性
①接口中可以添加default
修饰的非抽象方法,可以有方法体和内容。②可以使用lambda表达式,减少代码冗余。③函数式接口,使用@FunctionalInterface
注解标明,该接口有且仅有一个抽象方法。④方法引用,可以直接引用已有Java类或对象的方法或构造器,进一步简化lambda表达式。⑤stream流,用于解决已有集合/数组类库的弊端,简化其操作,有foreach
遍历、filter
过滤、map
映射、concat
合并等功能。⑥增加日期相关的API。
十、反射与注解
简述反射的基本概念,优缺点和使用场景。
答:①在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java的反射机制。② 优点是运行时动态获取类的全部信息,缺点是破坏了类的封装性,泛型的约束性。③是框架的核心灵魂,动态代理设计模式采用了反射机制,还有 Spring、Hibernate 等框架也大量使用到了反射机制。
获取Class对象有哪几种方式?能通过Class对象获取类的哪些信息?
答:①通过类名.class
②通过对象.getClass()
③通过Class.forName(类的全限名);
④可以通过Class对象获取类的成员变量,方法或构造器。带declared的获取方法可以获取到类的一个或全部成员变量,方法,构造器,不带declared的方法只能获取到类的public修饰的成员变量、方法或构造器,包括父类public修饰的成员变量、方法或构造器。
注解是什么,元注解是什么,有什么作用?
答:①注解是一种标记,可以使类或接口附加额外的信息,是帮助编译器和JVM完成一些特定功能的。②元注解就是自定义注解的注解,包括@Target
:用来约束注解的位置,值是ElementType
枚举类,包括METHOD
方法、VARIABLE
变量、TYPE
类/接口、PARAMETER
方法参数、CONSTRUCTORS
构造器和LOACL_VARIABLE
局部变量;@Rentention
:用来约束注解的生命周期,值是RetentionPolicy
枚举类,包括:SOURCE
源码、CLASS
字节码和RUNTIME
运行时;@Documented
:表明这个注解应该被javadoc工具记录;@Inherited
:表面某个被标注的类型是被继承的。
十一、IO流
简单说说File对象表示的是什么?File类有哪些常用方法?
答:①File对象表示的是操作系统上的文件或目录。②获取:getAbsolutePath()
获取绝对路径;getPath()
获取文件定义时使用的路径;getName()
获取文件名,带后缀;length()
返回文件长度,单位是字节。③判断:exists()
判断File对象表示的文件或目录是否存在;isDirectory()
判断是否是目录; isFile()
判断是否是文件。④创建和删除:createNewFile()
不存在时创建新文件;delete()
删除文件,目录(非空目录不能删除);mkdir()
创建一级目录;mkdirs()
创建多级目录,推荐使用;⑤遍历:list
获取当前目录下所有一级文件名称到一个字符串数组并返回;listFiles
获取当前目录下所有一级File对象到File数组返回。
英文、数字和中文字符在文件中分别占多大的空间?
答:①英文和数字在任何编码中都占1个字节。②中文字符在GBK编码下占2个字节,在UTF-8编码下占3个字节。
简述传统IO有哪些分类?
答:①按流的方向:输出流:把内存中的数据写出到磁盘文件或网络介质中;输入流:把磁盘文件或网络介质中的数据读取到内存中。②按流的内容:字节流:流中数据的最小单位是字节;字符流:流中数据的最小单位是字符(针对文本内容)。顶层的抽象类包括InputStream、OutputStream、Reader、Writer,它们都实现了Closeable接口。③缓冲流(BufferedInputStream/BufferedOutputStream/BufferedReader/BufferedWriter):自带一个8KB大小的缓冲池,可以将字节/字符流为缓冲字节/缓冲字符流。④字符转换流(InputStreamReader/OutputStreamWriter):可以将对应的字节流转换为字符流。⑤打印流:PrintStream,方便快速打印数据,参数是什么就打印什么。
简述BIO、NIO、AIO的区别和原理
答:①BIO是同步阻塞的,数据的读写会阻塞在一个线程中,适用于连接数目比较小且固定的架构,对服务器资源要求高,JDK1.4前的唯一选择。②NIO是同步非阻塞的,通过Selector监听Channel上事件的变化,在Channel上有数据发生变化时通知该线程进行读写操作。适用于连接数目比较多且连接比较短的架构,如聊天服务器,从 JDK1.4开始支持。③AIO是异步非阻塞的,异步是指服务端线程接收到客户端管道后就交给底层处理IO通信,自己可以做其他事情。适用于连接数目比较多且连接比较长的架构,从JDK1.7开始支持。
Q5:序列化和反序列化是什么,有什么要求?
答:①Java在JVM运行时被创建、更新和消耗,当JVM退出时,对象也会随之销毁。可以通过Java序列化实现持久化存储,保存对象及其状态信息到字节数组中。②反序列化就是再将字节数组中存储的信息转换回Java对象。③要求类必须实现序列化接口,并且序列化和反序列化必须保持序列化的ID一致。④静态变量和被transient修饰的变量不会被序列化。
十二、springMVC的流程?
(1)用户发送请求至前端控制器DispatcherServlet;
(2)DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handler;
(3)处理器映射器根据请求url找到具体的处理器Handler,生成处理器对象及处理器拦截器(如果有则生成),一并返回给DispatcherServlet;
(4)DispatcherServlet 调用 HandlerAdapter处理器适配器,请求执行Handler;
(5)HandlerAdapter 经过适配调用 具体处理器进行处理业务逻辑;
(6)Handler执行完成返回ModelAndView;
(7)HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
(8)DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
(9)ViewResolver解析后返回具体View;
(10)DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
(11)DispatcherServlet响应用户。
十三、Redis 16
Q1:什么是NoSQL?列举几个你知道的NoSQL数据库。
答:①许多网站在海量用户访问的高并发情况下出现崩溃问题,根本原因是关系型数据库。关系型数据库有性能瓶颈:磁盘IO性能低下、扩展瓶颈:数据关系复杂,扩展性差,不便于大规模集群。②NoSQL即Not-Only SQL,泛指非关系型数据库,作为关系型数据库的补充,降低了磁盘IO次数——使用内存存储、去除数据间关系——不存储关系,仅存储数据。③NoSQL的特征:特征:可扩容,可伸缩;大数据量下高性能;灵活的数据模型;高可用。④常见的NoSQL数据库:Redis、memcache、HBase、MongoDB。
简单讲讲Redis的含义
答:①Redis (REmote DIctionary Server) 是用 C 语言开发的一个开源的高性能键值对(key-value)数据库。②Redis数据库中的数据间没有必然的关联关系,内部采用单线程机制进行工作,性能比较高,支持持久化存储。③支持多种数据类型,包括字符串类型 string、列表类型 list、散列类型 hash、集合类型 set、有序集合类型 sorted_set。
Redis有哪些应用场景?
答:①为热点数据加速查询(主要场景),如热点商品、热点新闻、热点资讯、推广类等高访问量信息等。②应用于任务队列,如秒杀、抢购、购票排队等。③即时信息查询,如排行榜、各类网站访问统计、公交到站信息、在线人数信息(聊天室、网站)、设备信号等。④时效性信息控制,如验证码控制、投票控制等。⑤分布式数据共享,如分布式集群架构中的 session 分离以及消息队列、分布式锁等。
简述string类型的基本操作和注意事项
答:①存储的数据:单个数据,最简单常用的数据存储类型。存储数据的格式:一个存储空间保存一个数据。存储内容:通常使用字符串,如果字符串以整数的形式展示,可以作为数字操作使用。②添加/修改数据:set key value
、获取数据:get key
、删除数据:del key
、添加/修改多个数据:mset key1 value1 key2 value2 ...
、获取多个数据:mget key1 key2 …
、获取数据字符个数(字符串长度):strlen key
、追加信息到原始信息后部(如果原始信息存在就追加,否则新建):append key value
。③string在redis内部存储默认就是一个字符串,当遇到增减类操作incr
,decr
时会转成数值型进行计算。redis所有的操作都是原子性的,采用单线程处理所有业务,命令是一个一个执行的,因此无需考虑并发 带来的数据影响。注意:按数值进行操作的数据,如果原始数据不能转成数值,或超越了redis 数值上限范围(java中long型数据最大值,Long.MAX_VALUE)将报错。
简述list类型的基本操作和注意事项
答:①存储需求:存储多个数据,并对数据进入存储空间的顺序进行区分。存储结构:一个存储空间保存多个数据,且通过数据可以体现进入顺序。保存多个数据,底层使用双向链表存储结构实现。②添加/修改数据:lpush key value1 [value2] …
,rpush key value1 [value2] …
、获取数据:lrange key start stop
,lindex key index
,llen key
、获取并移除数据:lpop key
,rpop key
。获取数据时可以设置等待时间,list为空时等待获取。移除指定数据:lrem key count value
。③list中保存的数据都是string类型的,数据总容量是有限的,最多2^32- 1 个元素(4294967295)。list具有索引的概念,但是操作数据时通常以队列的形式进行入队出队操作,或以栈的形式进行入栈出栈操作。获取全部数据操作结束索引设置为-1。list可以对数据进行分页操作,通常第一页的信息来自于list,第2页及更多的信息通过数据库的形式加载。
简述set类型的基本操作和注意事项
答:①存储需求:存储大量的数据,在查询方面提供更高的效率。存储结构:能够保存大量的数据,高效的内部存储机制,便于查询。与hash存储结构完全相同,仅存储键,不存储值(nil),并且值是不允许重复的。②添加数据:sadd key member1 [member2]
、获取全部数据:smembers key
、删除数据:srem key member1 [member2]
、获取集合数据总量:scard key
、判断集合中是否包含指定数据:sismember key member
。③set 类型不允许数据重复,如果添加的数据在 set 中已经存在,将只保留一份。set 虽然与hash的存储结构相同,但是无法启用hash中存储值的空间。
答:①Jedis是一种利用Java语言连接redis的服务,需要依赖redis.clients下的jedis包。②通过new Jedis(String address,int port)创建一个操作redis数据库的对象,第一个参数是字符串类的ip地址,第二个参数是int类型的端口号。③之后通过Jedis类实例对象调用相关API实现对redis数据库的操作。
说说redis是单线程但为什么这么快?
redis是内存存储的,相比于写磁盘,要快很多,并且是运行在内存中的
(以下单线程仅指Redis负责存取这块的线程只有一个,而非Redis中只有一个进程)
数据结构简单
单线程能处理高并发请求吗?
当然可以了,Redis都实现了。有一点概念需要澄清,并发并不是并行。
讲一讲缓存穿透,缓存雪崩以及缓存击穿吧
缓存穿透:就是客户持续向服务器发起对不存在服务器中数据的请求。客户先在Redis中查询,查询不到后去数据库中查询。
缓存击穿:就是一个很热门的数据,突然失效,大量请求到服务器数据库中
缓存雪崩:就是大量数据同一时间失效。
打个比方,你是个很有钱的人,开满了百度云,腾讯视频各种杂七杂八的会员,但是你就是没有netflix的会员,然后你把这些账号和密码发布到一个你自己做的网站上,然后你有一个朋友每过十秒钟就查询你的网站,发现你的网站没有Netflix的会员后打电话向你要。你就相当于是个数据库,网站就是Redis。这就是缓存穿透。
大家都喜欢看腾讯视频上的《水果传》,但是你的会员突然到期了,大家在你的网站上看不到腾讯视频的账号,纷纷打电话向你询问,这就是缓存击穿
你的各种会员突然同一时间都失效了,那这就是缓存雪崩了。
放心,肯定有办法解决的。
缓存穿透:
1.接口层增加校验,对传参进行个校验,比如说我们的id是从1开始的,那么id<=0的直接拦截;
2.缓存中取不到的数据,在数据库中也没有取到,这时可以将key-value对写为key-null,这样可以防止攻击用户反复用同一个id暴力攻击
缓存击穿:
最好的办法就是设置热点数据永不过期,拿到刚才的比方里,那就是你买腾讯一个永久会员
缓存雪崩:
1.缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
2.如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。