Java面试常见问题

01对面向对象的理解
面向对象是以“组织者”的思维模式来考虑问题
面向过程是以“执行者”的思维模式来考虑问题
比如我们要做一些数据库的连接或者说封装操作。
    面向过程想的是我要怎么来创造一个连接池的对象,怎么去管理
    而面向对象的思维是市面上有哪些现成的连接池,我们拿来来用
再比如软件开发的三层结构(UI层、业务层、数据持久层)
    面向对象会去选市面上优秀的框架,做一个选择,而面向过程就是在造轮子。
面向对象有三大特性:封装继承和多态
继承为了复用,抽取共性的东西;多态父类引用指向子类对象,拿来解耦
02JDK,JRE,JVM的区别’
JDK(Java Development Kit) 是整个JAVA的核心,包括了Java运行环境(Java Runtime Envirnment),一堆Java工具(javac/java/jdb等)和Java基础的类库(即Java API 包括rt.jar)。
JRE(Java Runtime Environment,Java运行环境),包含JVM标准实现及Java核心类库。JRE是Java运行环境,并不是一个开发环境,所以没有包含任何开发工具(如编译器和调试器)
JVM(Java Virtual Machine),即java虚拟机, java运行时的环境,实现一次编译到处运行。
JVM不能单独搞定class的执行,解释class的时候JVM需要调用解释所需要的类库lib。
在JDK下面的的jre目录里面有两个文件夹bin和lib,在这里可以认为bin里的就是jvm,lib中则是jvm工作所需要的类库,而jvm和 lib和起来就称为jre。JVM+Lib=JRE。
总体来说就是:
    我们利用JDK(调用JAVA API)开发了属于我们自己的JAVA程序后,
    通过JDK中的编译程序(javac)将我们的文本java文件编译成JAVA字节码,
    在JRE上运行这些JAVA字节码,JVM解析这些字节码,映射到CPU指令集或OS的系统调用。
03 ==和equals的区别
两者默认情况下都是比较地址
==:在比较基本数据类型时,比较的是数值
    在比较引用类型时,比较的是引用指向的值(地址)
equals默认比较的是地址,如果要比较内容需要重写equals方法
04 final关键字的使用
final修饰类:表示类不可变不可被继承,比如String,不可变性
final修饰方法:表示该方法不可被重写,比如模版,固定的算法
final修饰变量:这个变量就为一个常量
修饰的是基本数据类型,这个值本身不可被修改
修饰的是引用类型,引用的指向(地址)不可被修改
使用final方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率
final, finally, finalize的区别
    final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。
    finally是异常处理语句结构的一部分,表示总是执行。
    finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。
05 String,StringBuffer,StringBuilder区别
String:是final类型,每次声明都是不可变的对象
        每次操作都会产生新的对象,然后指针也指向新的对象
(字符拼接问题)
StringBuffer和StringBuilder:是在原有对象上进行操作,都可进行修改
2.在单线程且操作大量字符串用StringBuilder,速度快,但线程不安全;
3.在多线程且操作大量字符串用StringBuffer,线程安全。
    为什么安全:因为他的每个方法都加了synchronized(同步)关键字
    考虑安全场景:多线程访问同一个共享资源时
线程安全:多线程条件下对这个对象访问不用加其他任何东西访问操作数据的结果依然是正确的
06接口和抽象类的区别
从语法上讲:
    抽象类:可以理解为声明方法的存在而不去实现它的类,
            其类中的方法可以有抽象的也可以有非抽象的和构造器
            其子类,要重写其所有的抽象方法否则它们也是抽象类为。
    接口:是抽象类的变体,他里面的方法都是抽象的,属性都是常量,默认有public static final修饰
从设计上讲:
    抽象类:是对同一类事物的抽取,比如在开发中我们在针对Dao层操作时会抽取一个基础的BaseDao,这样能做到复用效果
    接口:通常更像是一个标准的制定,定制系统间的对接
        比如:在单体架构中,我们进行分层开发,为了解耦我们会用接口作为各层间的纽带,绕
        在controller注入IUserService,在Service注入IuserDao,这样有利于我们开发中秉承高内聚低耦合的原则
    
区分几个概念:
    多重继承:爷孙三代关系
    多实现:Person implement iruanble,ieateble
    多继承:接口可以,类不行    
07算法题
求N的阶乘
递归:方法内部调用该方法,注意找到规律和出口
    会出现的问题是:栈内存溢出,因为每次调用方法都会在栈内存开辟空间
必须要会自己手写
public static int getResult(int n){
    if(n<0){
        throw new ValitoExcption("非法参数");
    }
    if(n==0||n==1){
        return 1;
    }
    return getResult(n-1)*n
}
求斐波那切数列的地N个数是几
数字规律:1,1,2,3,5,8,13,21...
出口:第一项和第二项都等于1
public static int getResult(int n){
    if(n<0){
        throw new ValitoExctption("非法参数");
    }
    if(n==1||n==2){
        return 1;
    }
    return getResult(n-1)+getResult(n-2);
}
08Integer&int(缓存&自动装箱和拆箱)
Java是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入了基本数据类型
但是为了能够将这些基本数据类型当成对象操作,Java为每一个基本数据类型都引入了对应的包装类型
int的包装类就是Integer,从Java5开始引入了自动装箱/拆箱机制,使得二者可以相互转换。
Java 为每个原始类型提供了包装类型:
- 原始类型: boolean,char,byte,short,int,long,float,double
- 包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double
如果整型字面量的值在-128到127之间,那么不会new新的Integer对象,而是直接引用常量池中的Integer对象
09方法的重写和重载的区别
是Java多态性的不同表现
重载:发生在一个类里面,方法名相同,参数列表不同(跟返回型没关系)
重写:发生在父类子类之间,方法名相同,参数列表相同
10List和Set区别
List:有序,可重复(子类:ArrayList、Vector、LinkedList)
Set:无序,不可重复(子类:HashSet、TreeSet)
11Collection 和 Collections的区别
Collection是集合类的上级接口,继承与他的接口主要有Set 和List.
Collections是针对集合类的一个工具类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。
    常用方法有:sort()排序、shuffle()打乱、reverse()反转
Java中的工具类的命名习惯+s结尾
12ArrayList,Vector,LinkedList的存储性能和特性是什么?
ArrayList和Vector
ArrayList 和Vector都是使用数组方式存储数据,
此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,
但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,
Vector由于使用了synchronized(锁)方法(线程安全),通常性能上较ArrayList差,
ArrayList:线程不安全,效率高,常用
Vector:线程安全的,效率低
而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。
13ArrayList和LinkedList的区别
底层数据结构的差异:
    ArrayList:数组,连续一块内存空间,扩容是创建一个新数组长度为新数组的1.5倍(原数组定下来不变了)将原来的迁移过来
    LinkedList:双向链表,头尾都要加两个指针,内存空间更大点,不是连续的内存空间
常规结论:
    ArrayList:查找快,因为是连续的内存空间,方便寻址,但删除插入慢,因为需要发生数据的迁移
    LinkedList:查找慢,因为需要通过指针一个个寻找,但删除插入块,因为只要改变前后节点的指针偏向
14如何在双向链表A和B中插入C
C.pre=A
c.next=B
A.next=C
A.next.pre=C
15.HashSet的存储原理
HashSet底层采用的是HashMap来实现存储,其值作为HashMap的Key
为什么采用Hash算法,有什么优势解决什么问题
解决的问题是当我们往数组放数据时,如何判断是否唯一,传统方法时遍历
存储原理
object中有个hashcode方法,通过计算存储对象的hashcode,在于数组的长度-1做位运算,得到我们要存储在那个数组的坐标下,这样提高效率
但是随着元素的不断添加,就可能出现哈希冲突,即不同对象计算出来的hash值相同
这个时候才需要用到equals方法
哈希表是一张什么表
本质是一个数组,而数组的本质是链表
在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使每个关键字和结构中一个唯一的存储位置相对应。
16.HashTable&HashMap&ConcurrentHashMap
HashMap和Hashtable都实现了Map接口,三者在开发中的选择:HashMap>ConcurrentHashMap>hashtable
HashTable
线程安全的对象,内部有上锁的控制(synchronized),性能不高
HashMap
线程不安全对象,内部无上锁,put和get可以同时不会阻塞。
优点:效率高
缺点:如果有多个线程同时操作这一个hashmap,可能出现线程不安全,甚至是死锁(整个都锁住了)
容量: 2^n是为了让散列更加均匀
ConcurrentHashMap
分段锁,将锁的力度变小,兼顾两者保证线程安全和性能,将原先的哈希表拆成好几段
采用Segment + HashEntry的方式进行实现的,lock加在Segment上面。
17.如何写一个栈stack
1.数组
2.先进后出
3.出栈(取末尾的元素)
4.入栈(默认加到末尾)
18.IO流的分类及选择
按方向分:输入流和输出流(站在程序的角度看)
按读取的单位分:字节流(二进制文件)、字符流(文本文件)有BUffer缓冲区
按处理的方式分:节点流、处理流
IO流的4大基类:InputStream、OutputStream、Reader、Writer
19.serialVersionUID的作用
当执行序列化时,我们写对象到磁盘中,会根据当前这个类的结构生产一个版本号ID
当反序列化是,程序会比较磁盘中的序列化版本ID跟当前类结构生成的版本号ID是否一致,一致的话则反序列化成功
加上版本号,有助于我们的类结构发生变化时,依然可以与之前已经序列化的对象反序列化成功
20.异常体系(保证健壮性)
常见的五个运行时异常
通常此类异常成为逻辑异常:
    算数异常
    空指针异常
    类型转换异常
    数组越界
    数字格式异常
常见的五个非运行时异常
IOException
SQLException
FileNotFoundException
NoSuchFileException
NoSuchMethodException
21.Throw跟Throws的区别
throw作用于方法内,用于主动的抛出异常
throws作用于方法声明上,声明该方法有可能会抛出某些异常
自定义异常一般继承RunnTimeException(运行期异常)
    框架:制定一系列规则,如果没按照规则做即是逻辑错误-->运行期异常
22.创建线程的方式
常用有三种方式:
    1.继承Thread
    2.实现Runable接口
    3.实现Callable接口(可以获取线程执行之后的返回值)
    本质上就是继承Thread,实现接口还需要通过创建Thread对象来实现,如new Thread(new Runnable(){}).start()
    在实际开发中,通常采用线程池的方式来完成Thread的创建。
        Thread:启动线程创建对象后,调用对象  .start
        接口:创建对象后, newThread(对象).start
    runable与callable 的区别是有无返回值的区别
GC垃圾回收线程:后台线程
23.线程安全问题
当多个线程访问一个对象时,如果不用进行额外的同步控制或其他的协调操作
调用这个对象的行为都可以得出正确结果,则就叫做线程安全
比如:
    StringBuffer,我们多个线程在执行什么append等操作时,我们不需要加额外的控制如锁,就可以正常执行不发生错乱,这就是一个线程安全的对象
如何做到线程安全:
    最常见的方式是:采用synchronized关键字给代码块或方法加锁,StringBuffer的源码就是这样
如果在开发中需要拼接字符串,使用的是StringBuffer还是StringBuilder
场景一:
    如果多个线程访问同一个资源,那么久需要上锁,保证数据的安全性。
    这个时候如果使用非线程安全的对象,比如StringBuilder,那么这个时候就得借助外力:如加synchronized关键字
场景二:
    如果每个线程访问的是各自的资源,那么久无需考虑线程安全问题。
    这个时候就可以使用非线程安全对象StringBuilder
总之,要先确定访问的资源是否是共享资源(成员变量),且该资源是有状态的,即数据会有变化。
如果是就需要考虑线程安全问题
24.Sleep和wait的区别
1.所属类不同:
    sleep方法定义在Thread上
    wait方法定义在Object上
2.对于锁资源的处理方式不同:
    sleep不会释放锁,抱着睡
    wait会释放锁
3.使用范围:
    sleep可以使用在任意代码块
    wait必须在同步方法或同步代码块
4.生命周期的状态:
    sleep会进入到time waiting状态
    wait会进入到waiting状态
为什么wait在object里,而不定义在Thread上:
    在同步代码块中,我们需要一个对象锁来实现多线程的互斥效果
    也就是说,java锁是一个对象级别的,而不是线程级别的
    (sleep是线程休眠)
为什么wait必须在同步代码块中使用:
    避免cpu切换到其他线程,而其他线程又提前执行了notify
    (就是还没生产就被消费了,然后之后就没人给唤醒了)
    所以需要一个同步锁来保护
25.ThreadLocal的理解
ThreadLocal作用:
   为每个线程创建一个副本 实现线程在上下文传递对象
每个线程都有一个map
    key:thread     value:具体存放的东西
ThreadLocal在实际开发中解决什么问题
mybatis管理sqlsession,管理connection
26.JDK类加载机制
什么是类加载机制
JVM在使用java类的程序为:
    1.Java源文件-->编译-->class文件
    2.类加载其ClassLoader读取这个类文件,并将其转换为java.lang.Class的实例
    有了该实例,JVM就可以使用他来创建对象、调用方法等操作
Class文件的来源
1.java自身内部的核心类:在jre/lib/rt.jar
2.java的扩展类,位于jre/lib/ext目录
3.我们自己开发的类或项目开发用到的第三方jar包
JDK如何加载这些类
针对不同来源,java分了不同的ClassLoader来加载
1.核心类:Java运行的基础类,由一个BootstrapClassLoader的加载器负责实现。根加载器或引导加载器
JVM内部实现对,java程序访问不到
2.Java扩展类。是由ExtClassloader实现的,扩展类加载器
3.项目编写的类,由appClassLoader实现,系统类加载器
双亲委托机制
27.Ajax的工作原理
三个要素:异步交互,XMLHttpRequest对象,回调函数
异步刷新,注册(用户名唯一)
28.JavaScript原型机制
javascript的原型有一个关键作用就是扩展其原有类的特性
29.JSP和Servlet的区别
技术的角度:
    JSP本质就是一个Servlet
    JSP的工作原理:JSP-->编译-->Servlet(java)-->编译-->class(最终跑的文件)
应用的角度:
    JSP=HTML+Java
        <html>
            <%  java  %>
        </html>
    Servl=Java+HTML 
        out.write("<html>")
    jsp的特点在于实现视图,servlet的特点在于实现控制逻辑
    MVC模型
        M:模型
        V:视图      JSP
        C:控制器    Servlet
30.Servlet的生命周期
单实例的
生命周期:
    创建对象-->初始化-->service()-->doXXX-->销毁
创建对象的时机:
    1.默认是第一次访问该Servlet的时候创建
    2.也可以通过配置web.xml,来改变创建时机,比如容器启动的时候区创建
        DispatchServlet(springMVC前端控制器)
        <load-on-startup>1</load-on-startup>
执行次数:
    对象的创建只有一次,单例
    初始化一次,销毁一次
线程安全问题:
    构成线程不安全的因素:
        1.多线程环境(多个客户端,同时访问Servlet)
        2.多个线程共享资源,比如一个单例对象
        3.这个单例对象是有状态的
31.Session跟Cookie的区别
都有key-value结构
1.存储位置不同:
    Session:服务器端
    Cookie:客户
2.存储的数据格式不同:
    Session:value为对象,Object为类型
    Cookie:value为字符串,如果要存储一个对象,则需要将对象转为json
3.存储数据的大小
    Session:受服务器限制
    Cookie:一般来说,最大为4k
4.生命周期不同:
    Session:服务器端控制,默认30min,当用户关闭浏览器,session并不会小事
    Cookie:客户端控制,就是一个文件
        1.默认的是会话级的cookie,这种随着浏览器的关闭而关闭,比如保存sessionID的cookie
        2.非会话级的cookie,通过设置有效期来控制,比如"7天免登陆”设置:setMaxAge
5.两者间的联系
    http协议是一种无状态协议,服务器为了记住用户的状态,采用的是Session的机制
    而Session机制背后的原理是,服务器会自动生成会话级的cookie来保存Session的标识
32.转发和重定向的区别
转发:
    发生在服务器内部的调转,对于客户端来说,至始至终就是一个请求,所以在这期间,保存在request对象中的数据可以传递
重定向:
    发生在客户端的调转,是多次请求,如果需要在多次请求之间传递数据,需要调用session对象。
33.谈谈三层架构
web层:负责与用户交互并对外提供服务接口(springMVC,Struts2,Struts1)
业务逻辑层:实现业务逻辑(spring)
数据存取层:将业务逻辑层处理的结果持久化,方便后续查询(mybatis,Hibernate、springJDBC)
34.谈谈对MVC的理解
Model(模型)代表一个存取数据的对象或JAVA POJO
View(视图)代表模型包含的数据的可视化比如HTML,JSP,FREEMAEKER
Controller(控制器)控制器作用于模型和视图上,控制数据流向模型对象,并在数据变化时更新视图。
    如Servlet、Controller
常见MVC框架:Struts1,Struts2.SpringMVC
比如SpringMVC分为两个控制器
    DispatchServlet:前端控制器,由他来接收客户端的请求,
    在根据客户端请求的URL的特点,分发给对应的业务控制器(XXXController)
35.jsp 9大内置对象
内置对象:对于开发者自身无需创建,可以直接使用,因为内部已经帮我们创建了
request-------HttpServletRequest
response--------HttpServletResponse
config---------ServletConfig
application----ServletContext
session
exception
page
out
pageContext
36.JSP四大域对象
ServletContext context域:只能在同一个web应用中使用(全局的)
HttpSession session域:只能在同一个会话中使用
HttpServletRequest request域:只能在同一个请求中使用
PageContext page域:只能在当前的jsp页面使用
37.并发和并行的区别
并发:同一个CPU执行多个任务,按细分的时间片交替执行
并行:再过个cpu上同时处理多个任务
38.数据库设计的三大范式和反范式
数据库的三大范式:
    第一范式:列不可分
    第二范式:要有主键
    第三范式:不可存在传递依赖(避免产生冗余信息)比如名字、地址、省份、城市这就有依赖,应该分开成名字、地址;地址、省份、城市
反范式设计(第三范式)
为什么:
    1.提高查询效率(读多写少)
    2.保存历史快照信息
39.聚合函数
聚合函数结合分组查询
count()sum()avg()max()min()
40.左连接、右连接、内连接,他们的区别是什么
左连接:以左表为主
    select a.*,b.* from a left join b on a.b_id=b.id;
右连接:以右表为主
内连接:只列出两张表管理查询符合条件的记录
    select a.*,b.* from a inner join b on a.b_id=b_id
区别:左右连接会一个表全出,然后连接另一个表符合条件的数据
内连接就是符合两者条件的数据
41.SQL注入
是指通过字符串凭借的方式构成了一种特殊的查询语句,会错误的变成另一种条件的查询语句
解决方案:
    预处理对象:采用PreparedStatement对象
    可以提高执行效率,因为是预先编译执行
mybatis采用#解决
42.JDBC如何实现对事务的控制及事务边界
基于Connection进行控制
    connection.setAutoCommit(false)
    取消自动提交
事务的边界放在业务层进行控制,因为业务层包含多个dao层的操作
43.事务的特性
简称ACID
    原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)
原子性是基础,隔离性是手段,一致性是约束条件,持久性是目的
原子性:事务是数据库的逻辑工作单位,要么都成功要么都失败
一致性:数据库中的数据在事务操作前后都必须满足业务规则约束
隔离性:一个事务的执行不能被其他事务干扰。不同的隔离级别,互相干扰的程度不同
持久性:事务一旦提交,结果就是永久性的。及时发生冗积,也可以依靠事务日志完成数据的持久化
44.事务的隔离级别
解决并发情况下,数据的安全性问题
存在问题:
	1. 脏读:一个事务,读取到另一个事务中没有提交的数据
	2. 不可重复读(虚读):在同一个事务中,两次读取到的数据不一样。
	3. 幻读:一个事务操作(DML)数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改。
 隔离级别:
	1. read uncommitted:读未提交
		* 产生的问题:脏读、不可重复读、幻读
	2. read committed:读已提交 (Oracle)
		* 产生的问题:不可重复读、幻读
	3. repeatable read:可重复读 (MySQL默认)
		* 产生的问题:幻读
	4. serializable:串行化
		* 可以解决所有的问题
45.synchronized和lock的区别
1.作用位置不同
    synchronized可以给方法,代码块加锁
    lock只能给代码块枷锁
2.锁的获取锁和释放锁的机制不同
    synchronized无需手动获取锁和释放锁,发生异常会自动解锁,不会出现死锁
    lock需要自己枷锁和释放锁,如lock()和unlock(),如果忘记使用unlock会出现死锁
synchronized修饰成员方法时,默认的锁对象,就是当前对象
synchronized修饰静态方法时,默认的锁对象是当前类的class对象
synchronized修饰代码块时,可以自己设置锁对象
46.TCP和UDP的区别
两者都是传输层协议
TCP提供可靠的传输协议,传输时需要建立连接(三次握手),面向字节流,传输慢
UDP无法保证传输的可靠性,无需创建连接,以报文的形式传输,效率高
三次握手:
    1.客户端发送syn=随机数x给服务端要建立连接
    2.服务端反馈确认接收到请求发送syn ack=x+1 和随机数y 给客户端,告诉客户端准备好连接了
    3.客户端再向服务端发送ack=x+1,y+1。表示真的要建立连接
四次挥手:
    1.客户端发生关闭连接指令:FIN=1 seq=random x
    2.服务端确认收到指令发送:ACK=1 ack=x+1 seq=random y。关闭服务端的输入流
    3.服务端也要关闭连接发送:FIN=1 seq=random z ack=ack+1。关闭服务端的输出流
    4.客户端确认收到消息,关闭连接:ACK=1 seq=x ack=z+1
Http在应用层
47.什么是死锁?如何防止?
死锁就是线程A和线程B同时持有对方需要的锁,从而发生阻塞,最终变为死锁
防止:
    尽量采用trylock方法,设置超时时间主动退出
    减少同步代码块的嵌套使用
    降低锁的使用粒度
48.反射
反射是一种能力,一种在程序运行时
    1.可以对任意一个类,动态获取当前类对象的所有属性和方法的能力,
    2.对于任意一个对象,都可以调用他的任意一个方法和属性
可以动态执行方法,给属性赋值等操作的能力
class代表的就是所有字节码对象的抽象类
Class.forName()
一个类的组成部分有哪些:
    1.属性
    2.方法
    3.构造方法
    4.接口
    5.注解
在许多框架中都采用了反射的机制来实现动态效果
比如@Autowrite就能实现自动注入
    注解的解析程序会扫描当前的包下有哪些属性加了这个注解,一旦有注解
    就会去容器里面获取对于的类型的实现,然后给这个属性赋值(这就是反射机制)
49.SpringIOC的知识
SpringIOC的理解
是一种设计思想模式
在平时的java应用开发中,我们要实现某一个功能或者说是完成某个业务逻辑时至少需要两个或以上的对象来协作完成,
在没有使用Spring的时候,每个对象在需要使用他的合作对象时,自己均要使用像new object() 这样的语法来将合作对象创建出来,这个合作对象是由自己主动创建出来的,
创建合作对象的主动权在自己手上,自己需要哪个合作对象,就主动去创建,创建合作对象的主动权和创建时机是由自己把控的,
而这样就会使得对象间的耦合度高了,A对象需要使用合作对象B来共同完成一件事,A要使用B,那么A就对B产生了依赖,也就是A和B之间存在一种耦合关系,并且是紧密耦合在一起,
而使用了Spring之后就不一样了,创建合作对象B的工作是由Spring来做的,Spring创建好B对象,然后存储到一个容器里面,
当A对象需要使用B对象时,Spring就从存放对象的那个容器里面取出A要使用的那个B对象,然后交给A对象使用,
至于Spring是如何创建那个对象,以及什么时候创建好对象的,A对象不需要关心这些细节问题(你是什么时候生的,怎么生出来的我可不关心,能帮我干活就行),A得到Spring给我们的对象之后,两个人一起协作完成要完成的工作即可。
所以控制反转IoC(Inversion of Control)是说创建对象的控制权进行转移,
以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方,比如转移交给了IoC容器BEAN,
它就是一个专门用来创建对象的工厂,你要什么对象,它就给你什么对象,有了IoC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖IoC容器了,通过IoC容器来建立它们之间的关系。
SpringIOC的运用场景
在应用开发中,当我们在设计组件时,往往需要引入和调用其他组件的服务时,
这种依赖关系如果固化在组件设计中就会导致组件之间的耦合和维护难度的增大,
这个时候如果使用 IoC 容器,把资源获取的方式反转,让 IoC 容器主动管理这些依赖关系,
将依赖关系注入到组件中,那么这些依赖关系的适配和管理就会更加灵活。
IOC容器如何实现
使用方式:
    1.配置文件的方式
        <bean>
    2.注解的方式
        @Autowrite
完成两个事情:
    1.解析2.实现复制
配置方式:
        1.解析ML--》Dom4j
        2.调用方法实现注入
注解方式:
        1.解析类:这个类归Spring管理,获取到该类的注解信息和属性的注解信息(反射)
        2.赋值
50.Spring的bean作用域有哪些
应用程序的主体及由SpringIoC容器所管理的对象,被称之为bean
1.默认是singleton,即单例模式
2.prototype,每次从容器调用bean时都会创建一个对象
3.request,每次http请求就创建一个对象
4.session,同一个session共享一个对象
5.global-session
51.Spring的bean是线程安全的嘛
bean模式是单例的,是后端程序必然处于多个线程的工作环境下
但是bean基本是无状态的,所以从这个点来说是安全的
无状态就是没有存储数据
52.什么是事物的传播特性,Spring支持的特性有哪些
我们一般将事物的边界设置在service层
当我们调用service层的一个方法时,它能够保证我们的这个方法中执行的所有对数据库的更新操作保持在一个事务中
要么一起成功要么一起失败
如果在调用service层中的多个service方法,那么这个事务如何规定,才能使得其为同一个事务,这就是事务传播特性
spring支持的传播特性:
    PROPGATION_REQUIRED :支持当前事务,如果当前没有事务,就创建一个(默认的)
    PROPGATION_MANDATORY:支持当前事务,如果没有,就抛出异常
    PROPGATION_REQUIRES_NEW:新建事务,如果当前存在就给她挂起
    PROPGATION_NOT_SUPPORTED:以非事务方式操作
    PROPGATION_NEVER:以非事务方式操作,如果存在事务抛异常
53.什么是悲观锁,什么是乐观锁
悲观锁:
每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻止,直到这个锁被释放。
利用数据库本身的锁机制来实现,会锁记录
    实现方式:select *from table where id = 1 for update
乐观锁:
每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。
数据库的乐观锁需要自己实现,是一种不锁记录的实现方式,采用CAS(compare and set)模式,建议采用version字段作为判断依据
update t set store=store+1,version=version+1 where id=1 and version=old_version
每次对数据更新操作,都会对version+1,这样提交更新操作时,如果version已被更改就操作失败
    为什么使用version字段
        如果选择其他字段,如业务字段store,那么可能会出现ABA问题(初始时A但是在过程中出现了B用B操作了数据,但是结束时又是用A,这样操作就有问题)
优缺点:
乐观锁:性能高、重试失败成本不高建议乐观
悲观锁:性能低,但安全,失败成本高建议悲观,使用不当有死锁风险
54.Mybatis的缓存机制
缓存主要作用是提高查询的性能,减少跟数据库交互的次数,从而减轻数据库的承受压力
适用于多读少写的常见,若数据变化频率高不适应
mybatis的缓存分为一级缓存和二级缓存
    一级缓存:
        1.一级缓存模式是开启状态
        2.一级缓存作用域在sqlsession
        3.如果中间有对数据的更新操作,则清空一级缓存
    二级缓存:
        使用:
            1.开启二级缓存
                <setting name="cacheEnabled"value="true"/>
            2.在mapper.xml中配置二级缓存
                在<mapper>下面添加<cache/>标签
        默认的二级缓存的特点:
            1.所有的select语句会被缓存
            2.所有的更新语句将会刷新保存
            3.缓存将采用LRU算法来回收
            4.缓存会存储1024个对象的引用
            回收算法建议采用LRU
55.MyBatis分页方式
分为逻辑分页和物理分页
逻辑分页:就是一次性查出多条数据,然后在检索分页中的数据,具体一次性查询几条由JDBC配置的fetch-size决定
物理分页:从数据库中取出指定条数进行查询,我们所用的分页插件pageHelper实现的就是物理分页
56.请求到响应经历了什么
浏览器:
    1.检查输入的UOL格式是否正确
    2.解析域名、端口、路径
    3.检查当前有没有缓存,如果有,就直接使用缓存
    4.如果没有发起请求
    DNS:域名--->ip
网络是分层的:TCP/IP协议
    应用层:http协议
    传输层:TCP协议(三次握手,四次挥手)
    网络层:IP-->MAC物理地址
    数据链路层:MAC
到服务器反向解析
57.synchronized的底层原理
同步代码块:synchronized(){
自动上锁--------monitorenyer
自动解锁-------monitorexit
}
monitor的实现方式:偏向锁、轻量锁和重量锁
锁会根据情况逐步升级到轻量锁和重量锁级别。这就是锁升级
偏向锁和轻量锁为用户态,重量锁为内核态
任何锁对象中都有一个Object字段叫threadID,默认情况为空
当第一次有线程访问时,则该threadid设置为当前线程的id,这个为偏向锁,当线程执行结束后,重新置空
之后线程再次进入时,会判断threadid是否与该线程一致,如果一致,则可以获取该对象,不一致就会发生锁升级,从偏向锁升级为轻量锁
轻量锁的工作模式是通过自选循环的方式来获取锁,看对方的线程是否已经释放了锁,如果执行一定次数之后,还没有获取到锁,则发生锁升级,升级为重量锁
synchronized如何保证可见性的:
    可见性原理:
        两个线程如何保证变量信息的共享可见性?
            线程A--》本地内存A(共享变量副本)--》主内存(共享变量)
            如果有变更,则需将本地内存的变量写到主内存,对方才可以获取到更新
    synchronized就是当获取到锁之后,每次读取都是从内存读取
    当释放锁的时候,都会将本地内存的信息写到主内存,从而实现可见 
58.synchronized和volatile的区别
作用的位置不同:
    synchronized是修饰方法和代码块
    volatile(没有上锁)是修饰变量的
作用不同:
    synchronized:可以保证修改的可见性及原子(要么完整执行,要么完整失败)性,但可能会造成线程堵塞
    volatile:仅能实现变量修改的可见性,无法保证原子性,但不会造成线程堵塞
59.公司采用什么样的开发模式?前后端如何对接
前后端分离的模式,后端负责接口开发
接口文档(1.URL,2.请求方式3.请求参数4.返回参数5.实例)
一般才有swagger生成接口文档
团队的配比:职能模式,产品维度

初学者,欢迎指正!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值