Java八股文
Java基础
Java语言具有哪些特点?
-
Java为纯面向对象的语言。它能够直接反应现实生活中的对象。
-
具有平台无关性。java利用Java虚拟机运行字节码,无论是在Windows、Linux还是MacOS等其它平台对Java程序进行编译,编译后的程序可在其它平台运行。
-
Java为解释型语言,编译器把Java代码编译成平台无关的中间代码,然后在JVM上解释运行,具有很好的可移植性。
-
Java提供了很多内置类库。如对多线程支持,对网络通信支持,最重要的一点是提供了垃圾回收器。
-
Java具有较好的安全性和健壮性。Java提供了异常处理和垃圾回收机制,去除了C++中难以理解的指针特性。
-
Java语言提供了对Web应用开发的支持。
JRE和JDK的区别
• JDK:Java 开发工具包(Java Development Kit),提供了 Java 的开发环境和运行环境。
• JRE:Java 运行环境(Java Runtime Environment),提供了 Java 运行所需的环境。
• JDK 包含了 JRE。如果只运行 Java 程序,安装 JRE 即可。要编写 Java 程序
• 需安装 JDK.
简述自动装箱拆箱
对于 Java 基本数据类型,均对应一个包装类。
装箱就是自动将基本数据类型转换为包装器类型,如 int->Integer
拆箱就是自动将包装器类型转换为基本数据类型,如 Integer->int
简述 Java 基本数据类型
• byte: 占用 1 个字节,取值范围-128 ~ 127
• short: 占用 2 个字节,取值范围-215 ~ 215-1
• int:占用 4 个字节,取值范围-231 ~ 231-1
• long:占用 8 个字节
• float:占用 4 个字节
• double:占用 8 个字节
• char: 占用 2 个字节
• boolean:占用大小根据实现虚拟机不同有所差异
简述 Java 访问修饰符
• default: 默认访问修饰符,在同一包内可见
• private: 在同一类内可见,不能修饰类
• protected : 对同一包内的类和所有子类可见,不能修饰类
• public: 对所有类可见
String 类的常用方法都有那些?
•indexOf():返回指定字符的索引。
•charAt():返回指定索引处的字符。
•replace():字符串替换。
•trim():去除字符串两端空白。
•split():分割字符串,返回一个分割后的字符串数组。
•getBytes():返回字符串的byte 类型数组。
•length():返回字符串长度。
•toLowerCase():将字符串转成小写字母。
•toUpperCase():将字符串转成大写字符。
•substring():截取字符串。
•equals():字符串比较。
Java 语言中关键字 static 的作用是什么?
static 的主要作用有两个:
• 为某种特定数据类型或对象分配与创建对象个数无关的单一的存储空间。
• 使得某个方法或属性与类而不是对象关联在一起,即在不创建对象的情况下可通过类直接调用方法或使用类的属性。
面向对象
面向对象的三大特性?
继承:对象的一个新类可以从现有的类中派生,派生类可以从它的基类那继承方法和实例变量,且派生类可以修改或新增新的方法使之更适合特殊的需求。
封装:将客观事物抽象成类,每个类可以把自身数据和方法只让可信的类或对象操作,对不可信的进行信息隐藏。
多态:允许不同类的对象对同一消息作出响应。不同对象调用相同方法即使参数也相同,最终表现行为是不一样的。
重载(Overload)和重写(Override)的区别是什么?
方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。
• 重写发生在子类与父类之间, 重写方法返回值和形参都不能改变,与方法返回值和访问修饰符无关,即重载的方法不能根据返回类型进行区分。即外壳不变,核心重写!
• 重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。最常用的地方就是构造器的重载
• 构造器(constructor)是否可被重写(override)?
• 构造器不能被继承,因此不能被重写,但可以被重载。每一个类必须有自己的构造函数,负责构造自己这部分的构造。子类不会覆盖父类的构造函数,相反必须一开始调用父类的构造函数。
普通类和抽象类有哪些区别?
•普通类不能包含抽象方法,抽象类可以包含抽象方法。
•抽象类不能直接实例化,普通类可以直接实例化。
final 在java 中有什么作用?
•final 修饰的类不能被继承
•final 修饰的方法不能被重写。
•final 修饰的变量叫常量,只能被赋值一次。内部类只能访问被final修饰的局部变量。
抽象类(重点)
(1)多个类有相同的方法声明,但是方法体不一样。这个时候,我们考虑把方法声明进行抽取。让子类继承后,自己去实现方法体。没有方法体的方法,我们需要用抽象标志下。抽象的关键字是:abstract。
(2)抽象类:该方法称为抽象方法,包含抽象方法的类就是抽象类。
(3)抽象类的特点:
A:抽象类和抽象方法都要用abstract进行修饰
B:抽象类不能被实例化
C:抽象类中不一定有抽象方法,但是,有抽象方法的类一定是抽象类。
(4)抽象类中数据的特点
A:成员变量抽象类中可以有变量,也可以有常量。
B:成员方法抽象类中可以有抽象方法,也可以有非抽象方法。
C:构造方法抽象类是一个类,所以,它有构造方法。虽然本身不能实例化。但是可以给子类实例化使用。
接口和抽象类的相同点和不同点?
相同点:
• 都不能被实例化。
• 接口的实现类或抽象类的子类需实现接口或抽象类中相应的方法才能被实例化。
不同点:
• 接口只能有方法定义,不能有方法的实现,而抽象类可以有方法的定义与实现。
• 实现接口的关键字为 implements,继承抽象类的关键字为 extends。一个类可以实现多个接口,只能继承一个抽象类。
• 当子类和父类之间存在逻辑上的层次结构,推荐使用抽象类,有利于功能的累积。当功能不需要,希望支持差别较大的两个或更多对象间的特定交互行为,推荐使用接口。使用接口能降低软件系统的耦合度,便于日后维护或添加删除方法。
简述抽象类与接口的区别
抽象类:体现的是 is-a 的关系,如对于 man is a person,就可以将 person 定义为抽象类。
接口:体现的是 can 的关系。是作为模板实现的。如设置接口 fly,plane 类和 bird 类均可实现该接口。
一个类只能继承一个抽象类,但可以实现多个接口。
普通类和抽象类有哪些区别?
普通类不能包含抽象方法,抽象类可以包含抽象方法。
抽象类不能直接实例化,普通类可以直接实例化。
抽象类能使用 final 修饰吗?
不能,定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能修饰抽象
简述内部类及其作用
• 成员内部类:作为成员对象的内部类。可以访问 private 及以上外部类的属性和方法。外部类想要访问内部类属性或方法时,必须要创建一个内部类对象,然后通过该对象访问内部类的属性或方法。外部类也可访问 private 修饰的内部类属性。
• 局部内部类:存在于方法中的内部类。访问权限类似局部变量,只能访问外部类的 final 变量。
• 匿名内部类:只能使用一次,没有类名,只能访问外部类的 final 变量。
• 静态内部类:类似类的静态成员变量。
集合框架
Collection 和 Collections 有什么区别?
java.util.Collection 是一个集合接口(集合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式,其直接继承接口有List与Set。
Collections则是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。
Java中常见的容器有哪些?
常用容器可分为Collection和Map,Collection是存储对象的集合,而Map是存储键值对的集合。
其中,Collection又分为List、Set、Queue,而Map的实现类为HashMap、LinkedHashMap、TreeMap、HashTable。
List接口(有序,可重复):
ArrayList:底层是动态数组,支持随机访问。
LinkedList:底层是双向链表,只能顺序访问。
Set接口(不可重复):
HashSet(无序):基于哈希表。支持快速查找,但不支持有序性操作,且不维持插入顺序信息。
TreeSet(有序):底层是红黑树。支持快速查找(O(logn))但效率比HashSet(O(1))低。支持有序性操作,例如在一定范围内查找元素。
LinkedHashSet(有序):底层是链表+哈希表。使用哈希表存储元素,再维护一个双向链表保存元素的插入信息。
Queue接口:
LinkedList:可实现双向队列
PriorityQueue:基于堆结构的优先队列。
Map接口:
HashMap:基于哈希表。
LinkedHashMap:使用双向链表维护插入顺序。
HashTable:线程安全的HashMap,已淘汰。推荐ConcurrentHashMap。
TreeMap:基于红黑树。
常用集合的分类:
Collection 接口的接口 对象的集合(单列集合)
├——-List 接口:元素按进入先后有序保存,可重复
│—————-├ LinkedList 接口实现类, 链表, 插入删除, 没有同步, 线程不安全
│—————-├ ArrayList 接口实现类, 数组, 随机访问, 没有同步, 线程不安全
│—————-└ Vector 接口实现类 数组, 同步, 线程安全
│ ———————-└ Stack 是Vector类的实现类
└——-Set 接口: 仅接收一次,不可重复,并做内部排序
├—————-└HashSet 使用hash表(数组)存储元素
│————————└ LinkedHashSet 链表维护元素的插入次序
└ —————-TreeSet 底层实现为二叉树,元素排好序
Map 接口 键值对的集合 (双列集合)
├———Hashtable 接口实现类, 同步, 线程安全
├———HashMap 接口实现类 ,没有同步, 线程不安全-
│—————–├ LinkedHashMap 双向链表和哈希表实现
│—————–└ WeakHashMap
├ ——–TreeMap 红黑树对所有的key进行排序
└———IdentifyHashMap
————————————————
简述 Java 的 List
List 是一个有序队列,在 Java 中有两种实现方式:
ArrayList 使用数组实现,是容量可变的非线程安全列表,随机访问快,集合扩容时会创建更大的数组,把原有数组复制到新数组。
LinkedList 本质是双向链表,与 ArrayList 相比插入和删除速度更快,但随机访问元素很慢。
简述 Java 的 Set
Set 即集合,该数据结构不允许元素重复且无序。Java 对 Set 有三种实现方式:
HashSet 通过 HashMap 实现,HashMap 的 Key 即 HashSet 存储的元素,Value 系统自定义一个名为 PRESENT 的 Object 类型常量。判断元素是否相同时,先比较 hashCode,相同后再利用 equals 比较,查询 O(1)
LinkedHashSet 继承自 HashSet,通过 LinkedHashMap 实现,使用双向链表维护元素插入顺序。
TreeSet 通过 TreeMap 实现的,底层数据结构是红黑树,添加元素到集合时按照比较规则将其插入合适的位置,保证插入后的集合仍然有序。查询 O(logn)
简述 Java 的 HashMap
JDK8 之前底层实现是数组 + 链表,JDK8 改为数组 + 链表/红黑树。主要成员变量包括存储数据的 table 数组、元素数量 size、加载因子 loadFactor。HashMap 中数据以键值对的形式存在,键对应的 hash 值用来计算数组下标,如果两个元素 key 的 hash 值一样,就会发生哈希冲突,被放到同一个链表上。
table 数组记录 HashMap 的数据,每个下标对应一条链表,所有哈希冲突的数据都会被存放到同一条链表,Node/Entry 节点包含四个成员变量:key、value、next 指针和 hash 值。在 JDK8 后链表超过 8 会转化为红黑树。
若当前数据/总数据容量>负载因子,Hashmap 将执行扩容操作。默认初始化容量为 16,扩容容量必须是 2 的幂次方、最大容量为 1<< 30 、默认加载因子为 0.75。
简述 Java 的 HashMap
JDK8 之前底层实现是数组 + 链表,JDK8 改为数组 + 链表/红黑树。主要成员变量包括存储数据的 table 数组、元素数量 size、加载因子 loadFactor。HashMap 中数据以键值对的形式存在,键对应的 hash 值用来计算数组下标,如果两个元素 key 的 hash 值一样,就会发生哈希冲突,被放到同一个链表上。
table 数组记录 HashMap 的数据,每个下标对应一条链表,所有哈希冲突的数据都会被存放到同一条链表,Node/Entry 节点包含四个成员变量:key、value、next 指针和 hash 值。在 JDK8 后链表超过 8 会转化为红黑树。
若当前数据/总数据容量>负载因子,Hashmap 将执行扩容操作。默认初始化容量为 16,扩容容量必须是 2 的幂次方、最大容量为 1<< 30 、默认加载因子为 0.75。
HashMap 和 Hashtable 有什么区别?
hashMap去掉了HashTable 的contains方法,但是加上了containsValue()和containsKey()方法。
hashTable同步的,而HashMap是非同步的,效率上逼hashTable要高。
hashMap允许空键值,而hashTable不允许。
如何决定使用 HashMap 还是 TreeMap?
对于在Map中插入、删除和定位元素这类操作,HashMap是最好的选择。然而,假如你需要对一个有序的key集合进行遍历,TreeMap是更好的选择。基于你的collection的大小,也许向HashMap中添加元素会更快,将map换为TreeMap进行有序key的遍历。
说一下 HashMap 的实现原理?
HashMap概述: HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
HashMap的数据结构: 在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。
HashSet底层由HashMap实现
HashSet的值存放于HashMap的key上
HashMap的value统一为PRESENT
hashmap的实现:数组+链表+红黑树
数组+链表:数组寻址容易,插入删除难;链表寻址难,插入删除容易
链表长度超过8,转变为使用红黑树
存put(k,v):首先把(k,v)封装到Node对象;然后调用hashCode()方法计算k的hash值;最后通过哈希算法将hash值转换成数组下标,下标上如果没有元素就把Node添加到该位置,如果下标对应位置有链表,比较链表中每个key的equals()返回,若全为false则添加到链表末尾,若有一个返回true则覆盖
ArrayList 和 LinkedList 的区别是什么?
最明显的区别是 ArrrayList底层的数据结构是数组,支持随机访问,而 LinkedList 的底层数据结构是双向循环链表,不支持随机访问。使用下标访问一个元素,ArrayList 的时间复杂度是 O(1),而 LinkedList 是 O(n)。
如何实现数组和 List 之间的转换?
List转换成为数组:调用ArrayList的toArray方法。
数组转换成为List:调用Arrays的asList方法。
ArrayList 和 Vector 的区别是什么?
Vector是同步的,而ArrayList不是。然而,如果你寻求在迭代的时候对列表进行改变,你应该使用CopyOnWriteArrayList。
ArrayList比Vector快,它因为有同步,不会过载。
ArrayList更加通用,因为我们可以使用Collections工具类轻易地获取同步列表和只读列表。
Array 和 ArrayList 有何区别?
Array可以容纳基本类型和对象,而ArrayList只能容纳对象。
Array是指定大小的,而ArrayList大小是固定的。
Array没有提供ArrayList那么多功能,比如addAll、removeAll和iterator等。
在 Queue 中 poll()和 remove()有什么区别?
poll() 和 remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是 remove() 失败的时候会抛出异常。
哪些集合类是线程安全的?
vector:就比arraylist多了个同步化机制(线程安全),因为效率较低,现在已经不太建议使用。在web应用中,特别是前台页面,往往效率(页面响应速度)是优先考虑的。
statck:堆栈类,先进后出。
hashtable:就比hashmap多了个线程安全。
enumeration:枚举,相当于迭代器。
int与integer的区别
Integer是int提供的封装类,而int是java的基本数据类型
Integer默认值是null,而int默认值是0;
声明为Integer的变量需要实例化,而声明为int的变量不需要实例化
Integer是对象,用一个引用指向这个对象,而int是基本类型,直接存储数据
类似的还有:float Float;double Double;string String等
举个例子:当需要往ArrayList,HashMap中放东西时,像int,double这种内建类型是放不进去的,因为容器都是装 object的,这是就需要这些内建类型的外覆类了。
Java中每种内建类型都有相应的外覆类
IO流
什么是比特(Bit)?什么是字节(Byte)?什么是字符(Char)?以及他们的区别?
Bit 位,是计算机最小的二进制单位 ,取0或1,主要用于计算机操作。
Byte 字节,是数据的最小单位,由8位bit组成,取值(-128-127),主要用于计算机操作数据。
Char 字符,是用户可读写的最小单位,由16位bit(2个byte)组成,取值(0-65535),主要用于用户操数数据。
什么是IO流?
IO流就是以流的方式进行输入输出
主要用来处理设备之间的传输,文件的上传,下载和复制
流分输入和输出,输入流从文件中读取数据存储到进程中,输出流从进程中读取数据然后写入到目标文件
Java中有几种类型的流?
字符流和字节流。
字节流继承inputStream和OutputStream
字符流继承自InputSteamReader和OutputStreamWriter
Java 中 IO 流分为几种?
按功能来分:输入流(input)、输出流(output)。按类型来分:字节流和字符流。字节流和字符流的区别是:字节流按 8 位传输以字节为单位输入输出数据,字符流按 16 位传输以字符为单位输入输出数据。
BIO、NIO、AIO 有什么区别?
BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。
NIO:Non IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。
AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。
字节流和字符流哪个好?怎么选择?
1、大多数情况下使用字节流会更好,因为大多数时候 IO 操作都是直接操作磁盘文件,所以这些流在传输时都是以字节的方式进行的(图片等都是按字节存储的)
2、如果对于操作需要通过 IO 在内存中频繁处理字符串的情况使用字符流会好些,因为字符流具备缓冲区,提高了性能
如果要对字节流进行大量的从硬盘读取,要用那个流,为什么?
BufferedInputStream 使用缓冲流能够减少对硬盘的损伤
什么是缓冲区?有什么作用?
缓冲区就是一段特殊的内存区域,很多情况下当程序需要频繁地操作一个资源(如文件或数据库)则性能会很低,所以为了提升性能就可以将一部分数据暂时读写到缓存区,以后直接从此区域中读写数据即可,这样就显著提升了性。
对于 Java 字符流的操作都是在缓冲区操作的,所以如果我们想在字符流操作中主动将缓冲区刷新到文件则可以使用 flush() 方法操作。
字符流和字节流有什么区别?
字符流和字节流的使用非常相似,但是实际上字节流的操作不会经过缓冲区(内存)而是直接操作文本本身的,而字符流的操作会先经过缓冲区(内存)然后通过缓冲区再操作文件
什么是Java序列化,如何实现Java序列化?
1、序列化就是一种用来处理对象流的机制,将对象的内容进行流化。可以对流化后的对象进行读写操作,可以将流化后的对象传输于网络之间。序列化是为了解决在对象流读写操作时所引发的问题
2、序列化的实现:将需要被序列化的类实现Serialize接口,没有需要实现的方法,此接口只是为了标注对象可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,再使用ObjectOutputStream对象的write(Object obj)方法就可以将参数obj的对象写出
Files的常用方法都有哪些?
Files. exists():检测文件路径是否存在。
Files. createFile():创建文件。
Files. createDirectory():创建文件夹。
Files. delete():删除一个文件或目录。
Files. copy():复制文件。
Files. move():移动文件。
Files. size():查看文件个数。
Files. read():读取文件。
Files. write():写入文件。
简述Java异常的分类
Java异常分为Error(程序无法处理的错误),和Exception(程序本身可以处理的异常)。这两个类均继承Throwable。
Error常见的有StackOverFlowError,OutOfMemoryError等等。
Exception可分为运行时异常和非运行时异常。对于运行时异常,可以利用try catch的方式进行处理,也可以不处理。对于非运行时异常,必须处理,不处理的话程序无法通过编译。
简述throw与throws的区别
throw一般是用在方法体的内部,由开发者定义当程序语句出现问题后主动抛出一个异常。
throws一般用于方法声明上,代表该方法可能会抛出的异常列表。
Java中的泛型是什么 ?
泛型是 JDK1.5 的一个新特性,泛型就是将类型参数化,其在编译时才确定具体的参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
mysql
1.数据库三大范式
第一范式:强调的是列的原子性,即列不能够再分成其他几列。
第二范式:在第一范式基础上,必须有一个主键其他字段必须完全依赖于主键,而不能只依赖于主键的一部分。
第三范式:在前两个范式基础上,非主键列必须直接依赖于主键,不能存在传递依赖。
2.防止sql注入
代码层防止sql注入攻击的最佳方案就是sql预编译(preparestatement类)
规定数据长度,能在一定程度上防止sql注入
严格限制数据库权限,能最大程度减少sql注入的危害
3.索引
索引是帮助MySQL高效获取数据的数据结构,通俗来讲索引就好比书本的目录,加快数据库的查询速度。
分类
主键索引:加速查询 + 列值唯一(不可以有null)+ 表中只有一个
唯一索引:加速查询 + 列值唯一(可以有null)
普通索引:仅加速查询
组合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并
全文索引:对文本的内容进行分词,进行搜索
4.ACID
原子性:要么都发生,要么都不发生。
一致性:事务前后数据的完整性必须保持一致。
隔离性:一个事务不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
持久性:一个事务一旦被提交,数据不可再恢复
5.事务并发产生的三种问题
脏读:一个事务读取到了另外一个事务没有提交的数据
幻读:同一事务中,用同样的操作读取两次,得到的记录数不相同(数据条数)
不可重复读:在同一事务中,两次读取同一数据,得到内容不同(数据内容)
6.mysql的事务隔离级别
读未提交 Read uncommitted:一个事务还没有提交时,它做的变更就能被别的事务看到。
读提交 Read committed:一个事物提交之后,它做的变更才会被其他事务看到。
可重复读 Repeatable read:一个事物执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。未提交变更对其他事务也是不可见的。
串行化 serializable:对于同一行记录,写会加“写锁”,读会加“读锁”,当出现锁冲突时,后访问的事务需要等前一个事务执行完成,才能继续执行。
Spring
Spring的优点
轻量,基本版本大约2MB。
通过控制反转和依赖注入实现松耦合。
支持面向切面的编程,并且把应用业务逻辑和系统服务分开。
通过切面和模板减少样板式代码。
方便集成各种优秀框架。内部提供了对各种优秀框架的直接支持(如:Hibernate、MyBatis等)。
方便程序的测试。Spring支持Junit4,添加注解便可以测试Spring程序。
简单介绍Spring是什么?
1、Spring的核心是一个轻量级(Lightweight)的容器(Container)。
2、Spring是实现IoC(Inversion of Control)容器和非入侵性(No intrusive)的框架。
3、Spring提供AOP(Aspect-oriented programming)概念的实现方式。
4、Spring提供对持久层(Persistence)、事物(Transcation)的支持。
5、Spring供MVC Web框架的实现,并对一些常用的企业服务API(Application Interface)提供一致的模型封装。
6、Spring提供了对现存的各种框架(Structs、JSF、Hibernate、Ibatis、Webwork等)相整合的方案。
总之,Spring是一个全方位的应用程序框架。
1.IOC
控制反转,是一种设计思想。将原本在程序中手动创建对象的控制权,交由Spring框架的容器来管理,并且需要一种描述让容器知道要创建的对象间的关系。即IOC容器来管理对象及其依赖关系。
Spring 中的 IOC 容器有哪些?有什么区别?
spring 主要提供了「两种 IOC 容器」,一种是「BeanFactory」,还有一种是「ApplicationContext」
它们的区别就在于,BeanFactory「只提供了最基本的实例化对象和拿对象的功能」,而 ApplicationContext 是继承了 BeanFactory 所派生出来的产物,是其子类,它的作用更加的强大,比如支持注解注入、国际化等功能
那 BeanFactory 和 FactoryBean 又有什么区别?
这两个是「不同的产物」
「BeanFactory 是 IOC 容器」,是用来承载对象的
「FactoryBean 是一个接口」,为 Bean 提供了更加灵活的方式,通过代理一个Bean对象,对方法前后做一些操作。
IOC的优点是什么?
IOC 和依赖注入降低了应用的代码量。
松耦合。
支持加载服务时的饿汉式初始化和懒加载。
依赖注入的实现方法 什么是依赖注入?
在Spring创建对象的过程中,把对象依赖的属性注入到对象中
依赖注入(DI)是实现IOC的一种方法
• 构造器注入
• set方法注入
• 其他方式(接口注入、注解注入)
什么是AOP?
面向切面编程,作为面向对象的一种补充,将公共逻辑(事务管理、日志、缓存等)封装成切面,跟业务代码进行分离,可以减少系统的重复代码和降低模块之间的耦合度。切面就是那些与业务无关,但所有业务模块都会调用的公共逻辑。
AOP的术语
切面:切面泛指交叉业务逻辑。比如声明式事物处理,日志处理就可以理解为切面
通知:就是你想要的功能,即切面中的方法
连接点:可以使用通知的地方。如每个方法的前后
切入点:切面实际切入的地方
目标:要被通知的对象
AOP的实现方式
使用原生的Spring API接口(实现前置通知、后置通知、环绕通知等接口)
自定义类
注解实现(@Aspect)
bean的作用域
singleton:在Spring容器中仅存在一个实例,即Bean以单例的形式存在。
prototype:为每一个bean请求提供一个实例。
request :每次HTTP请求都会创建一个新的Bean。
session:同一个HTTP Session共享一个Bean,不同的HTTP Session使用不同的Bean。
globalSession:同一个全局的Session共享一个Bean,一般用于Portlet环境。
bean的生命周期
主要流程:实例化、属性赋值、初始化、销毁
1. 实例化(构造器)
通过构造器实例化,选择最佳构造方法
注意:实例化结束后对外暴露的是ObjectFactory(用于获取Bean的工厂类)而不是实例化对象本身,可以提供getObject() 来获取Bean实例。
2. 属性赋值(setter方法)
使用setter方法对属性进行赋值操作
3. 初始化
4.销毁(调用destroy)
实现DisposableBean接口调用destroy方法
SpringMvc的执行流程?
DispatcherServlet、HandlerMapping、Handler、HandlerAdapter、视图解析器
@Repository、@Service、@Compent、@Controller它们有什么区别?
这四个注解的「本质都是一样的,都是将被该注解标识的对象放入 spring 容器当中,只是为了在使用上区分不同的应用分层」
@Repository:dao层
@Service:service层
@Controller:controller层
@Compent:其他不属于以上三层的统一使用该注解
SpringMVC
MVC是一种设计模式,在这种模式下软件被分为三层,即Model(模型)、View(视图)、Controller(控制器)
Spring事务
ACID特性
1. 原子性
事务内的操作,要么全部执行,要么全部回滚。
2. 一致性(逻辑上的一致性)
强调数据库在逻辑上的一致性状态,依赖于原子性。
3. 隔离性
两个事务之间互不影响
4. 持久性(落库)
事务被提交之后,事务的一系列操作的结果是需要落库的
题外话:原子性和一致性的区别
一致性强调逻辑上一致,程序员可以写出原子性事务,但是在逻辑上是错误的代码(逻辑有问题,比如A转账给B,但代码只写了A扣钱,照样能符合原子性,但不符合一致性)。
一致性需要依赖于原子性,只有符合原子性的代码才可能有一致性
Spring中的隔离级别
- 默认(default):数据库的隔离级别为主
- 读未提交(read_uncommit)允许事务在执行过程中,读取其他事务未提交的数据
- 读已提交(read_commit)允许事务在执行过程中,读取其他事务已经提交的数据
- 不可重复读(repeat_table)在同一个事务内,任意时刻的查询结果都是一致的
- 串行化(serializable)所有事务逐个依次执行。
spring使用的设计模式
(1)工厂模式:Spring使用工厂模式,通过BeanFactory和ApplicationContext来创建对象
(2)单例模式:Bean默认为单例模式
(3)策略模式:例如Resource的实现类,针对不同的资源文件,实现了不同方式的资源获取策略
(4)代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术
(5)模板方法:可以将相同部分的代码放在父类中,而将不同的代码放入不同的子类中,用来解决代码重复的问题。比如RestTemplate, JmsTemplate, JpaTemplate
(6)适配器模式:Spring AOP的增强或通知(Advice)使用到了适配器模式,Spring MVC中也是用到了适配器模式适配Controller
(7)观察者模式:Spring事件驱动模型就是观察者模式的一个经典应用。
(8)桥接模式:可以根据客户的需求能够动态切换不同的数据源。比如我们的项目需要连接多个数据库,客户在每次访问中根据需要会去访问不同的数据库
Spring,Spring-mvc,Spring-boot的区别
Spring是一个IOC容器吗,提供了AOP机制。
Spring-mvc是spring整合servlet,用于返回前端请求,进行路由等操作。
Spring-boot是一套快速开发工具包,简化了spring和spring-mvc的整合开发,约定俗成了一些配置文件。
springboot基础
什么是SpringBoot?
SpringBoot是 Spring 开源组织下的子项目,是Spring组件一站式解决方案,主要是简化了使用Spring的难度,简省了繁重的配置,提供了各种启动器,开发者能快速上手
Spring Boot 有哪些优点?
容易上手,提升开发效率,为 Spring 开发提供一个更快、更广泛的入门体验。
开箱即用,远离繁琐的配置。
提供了一系列大型项目通用的非业务性功能,例如:内嵌服务器、安全管理、运行数据监控、运行状况检查和外部化配置等。
没有代码生成,也不需要XML配置。
避免大量的 Maven 导入和各种版本冲突。
谈谈你对Spring Boot的理解?
SpringBoot主要用来简化使用Spring的难度和繁重的XML配置,它是Spring组件的一站式解决方案,采取了习惯优于配置的方法。通过.properties或者.yml文件替代了Spring繁杂的XML配置文件,同时支持@ImportResource注解加载XML配置。Spring Boot还提供了嵌入式HTTP服务器、命令行接口工具、多种插件等等,使得应用程序的测试和开发简单起来
(Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的)介绍一下 @SpringBootApplication 注解
Spring Boot 的核心注解是@SpringBootApplication,它也是启动类使用的注解,主要包含了 3 个注解:
@SpringBootConfiguration:它组合了 @Configuration 注解,实现配置文件的功能。
@EnableAutoConfiguration:具有打开自动配置的功能,也可以关闭某个自动配置的选项。
@ComponentScan:用于Spring组件扫描。
Spring Boot 支持哪些日志框架?推荐和默认的日志框架是哪个?
Spring Boot 支持 Java Util Logging, Log4j2, Logback 作为日志框架,如果使用 Starters 启动器,Spring Boot 将使用 Logback 作为默认日志框架,推荐的日志框架是Log4j2。
Spring Boot 有哪几种读取配置的方式?
使用@Value注解加载单个属性值
使用@ConfigurationProperties注解可以加载一组属性的值,针对于要加载的属性过多的情况,比@Value注解更加简洁
Spring Boot 自动配置原理是什么?
@EnableAutoConfiguration注解、 @Configuration注解和 @ConditionalOnClass注解组成了Spring Boot自动配置的核心,首先它得是一个配置文件,其次根据类路径下是否有这个类去自动配置。具体是通过maven读取每个starter中的spring.factories文件,该文件配置了所有需要被创建在spring容器中的bean。
Spring 框架中都用到了哪些设计模式?
Spring设计模式的详细使用案例可以阅读这篇文章:Spring中所使用的设计模式
inux常用命令
1.目录切换
cd /:切换到根目录
cd …/:切换到上级目录
cd ~:切换到home目录
2.目录查看
ls:查看当前目录下的所有目录和文件
ls -a:查看当前目录下的所有目录和文件(包含隐藏文件)
ls -l:列表查看当前目录下的所有目录和文件(列表查看,显示更多信息)
3.目录操作
创建
mkdir 目录名
删除
rm -f: 强行删除,不询问
rm -r 目录名:递归删除目录
修改
mv 当前目录 新目录
查找
find 目录 参数 文件名称
示例:find /usr/tem -name ‘a*’ 查找/usr/tmp目录下的所有以a开头的目录或文件
4.文件操作
创建
touch 文件名
删除
rm -rf
修改
vi或者vim,分为三种模式
命令行模式
编辑模式
底行模式
查看
cat:看最后一屏
more:百分比显示
less:翻页显示
tail:指定行数或者动态查看
5.权限操作
chmod (u g o a) (+ - =) (r w x) (文件名)
u:文件的拥有者
g:与拥有者在同一组
o:其他用户
a:上面三者皆是
+:增加权限
-:撤销权限
=:设定权限
r:读权限
w:写权限
x:可执行(没有即代表不可cd进入这个目录)
6.打包和压缩
打包文件:tar -cvf 打包文件.tar 被打包的文件/路径…
解包文件:tar -xvf 打包文件.tar
参数说明
c:生成档案文件,创建打包文件
x:解开档案文件
v:显示过程
f:指定档案文件名称
压缩文件:tar -zcvf 打包文件.tar.gz 被压缩的文件/路径…
解压文件:tar -zxvf 打包文件.tar.gz
7.查找指令
grep:字符串匹配(从一个文件的内容中匹配一个字符串)
样例:ps -ef | grep sshd -c 查找指定进程ssh个数
-c:只输出匹配行的计数。
-i:不区分大小写。
-h:查询多文件时不显示文件名。
-l:查询多文件时只输出包含匹配字符的文件名。
-n:显示匹配行及 行号。
-s:不显示不存在或无匹配文本的错误信息。
-v:显示不包含匹配文本的所有行。
find:从指定的目录下查找文件或目录。
用法:find 路径 参数 文件名
样例:find /home/ygt -name test.txt查找自己账户下文件名为test.txt的文件
以文件名查找:find 目录 -name “文件名或者目录名”
以文件类型查找:find 目录 -type d(目录型文件)/f(普通文件)
以文件大小查找:find 目录 -size +nk(超过nk)/-n(小于nk)
按分钟查找:find 目录 -amin/-bmin/-mmin +n(n分钟之外)/-n(n分钟之内)
按天查找:find 目录 -atime/-ctime/-mtime +n(n天之外)/-n(n天之内)
locate:更快速的定位文件。(默认每天自动更新一次,若要查询最近更改的文件得先updatedb 来更新检索数据库)
样例:locate /etc/sh 搜索etc目录下所有以sh开头的文件
locate pwd 查找和pwd相关的所有文件
8.用户切换
su
sudo(为所有想使用root权限的普通用户设计的)
9.查看当前目录
pwd
10.查看进程
ps -ef
11.结束进程
kill