学习过程中收集到的面试题小汇总:
Spring
IoC和DI
-
在平时的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容器,它就是一个专门用来创建对象的工厂,你要什么对象,它就给你什么对象,有了 IoC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖IoC容器了,通过IoC容器来建立它们之间的关系。
DI(依赖注入)其实就是IOC的另外一种说法,DI是由Martin Fowler 在2004年初的一篇论文中首次提出的。他总结:控制的什么被反转了?就是:获得依赖对象的方式反转了。
- IoC是设计思想,IoC有三个核心:
BeanFactory
、反射
、DI
。BeanFactory
利用反射实现对象的创建,DI实现对象关系管理。 - Ioc与Dl创建bean的过程
自动装配
利用注解方式,我们只需要写@Autowired
注解,底层就会去容器中找对应的对象,如果有获取到,反射调用其对应的set方法
,设置。而这个调用过程都是自动,我们没有手工去写set方法。所以这个过程也称为自动装配。
Java基础
Java中操作字符串都有哪些类?它们之间有什么区别?
- String、StringBuffer、 StringBuilder。
- String和StringBuffer、StringBuilder 的区别在于String声明的是不可变的对象,每次操作都会生成新的String对象,然后将指针指向新的String 对象,而StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用String。
StringBuffer
和StringBuilder
最大的区别在于,StringBuffer
是线程安全的,而StringBuilder
是非线程安全的,但StringBuilder
的性能却高于StringBuffer
, 所以在单线程环境下推荐使用StringBuilder
,多线程环境下推荐使用StringBuffer
。
抽象类能使用final修饰吗?
不能。定义抽象类就是让其他类继承的,而final修饰的类不能被继承。
static关键字5连问
(1) 抽象的(abstract) 方法是否可同时是静态的(static) ?
- 抽象方法将来是要被重写的,而静态方法是不能重写的,所以这个是错误的。
(2)是否可以从一一个静态(static) 方法内部发出对非静态方法的调用?
- 不可以,静态方法只能访问静态成员,非静态方法的调用要先创建对象。
(3)static可否用来修饰局部变量?
- static不允许用来修饰局部变量
(4)内部类与静态内部类的区别?
- 静态内部类相对与外部类是独立存在的,在静态内部类中无法直接访问外部类中变量、方法。如果要访问的话,必须要new一个外部类的对象,使用new出来的对象来访问。但是可以直接访问静态的变量、调用静态的方法;
- 普通内部类作为外部类一个成员而存在,在普通内部类中可以直接访问外部类属性,调用外部类的方法。
- 如果外部类要访问内部类的属性或者调用内部类的方法,必须要创建一个内部类的对象,使用该对象访问属性或者调用方法。
- 如果其他的类要访问普通内部类的属性或者调用普通内部类的方法,必须要在外部类中创建一个普通内部类的对象作为一个属性,外同类可以通过该属性调用普通内部类的方法或者访问普通内部类的属性。
- 如果其他的类要访问静态内部类的属性或者调用静态内部类的方法,直接创建一个静态内部类对象即可。
(5) Java中是否可以覆盖(override)一-个private或者是static的方法?
Java中static方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而static方法是编译时静态绑定的。static方法跟类的任何实例都不相关,所以概念上不适用。
Collection和Collections有什么区别?
- Collection是一个集合接口,它提供了对集合对象进行基本操作的通用接口方法,所有集合都是它的子类,比如List、Set 等。
- Collections是一个包装类,包含了很多静态方法,不能被实例化,就像一个工具类,比如提供的排序方法: Collections. sort(list)。
浅谈HashMap的实现原理
HashMap
基于Hash算法实现的,我们通过put(key,value)存储,get(key)来获取
。 当传入key时,
HashMap会根据key. hashCode()
计算出hash值,根据hash值将value保存在bucket
里。当计算出
的hash值相同时,我们称之为hash冲突,HashMap的做法是用链表和红黑树存储相同hash值的
value。当hash冲突的个数比较少时,使用链表否则使用红黑树。
浅谈HashSet的实现原理? .
HashSet
是基于HashMap
实现的,HashSet 底层使用HashMap来保存所有元素,因此HashSet的实
现比较简单,相关HashSet的操作,基本上都是直接调用底层HashMap的相关方法来完成,HashSet
不允许重复的值。
为何Map接口不继承Collection接口?
- 尽管Map接口和它的实现也是集合框架的一部分,但Map不是集合,集合也不是Map。因此,Map继 Collection毫无意义,反之亦然。
- 如果Map继承Collection接口,那么元素去哪儿? Map包含key-value对,它提供抽取key或value列表集合的方法,但是它不适合”一组对象”规范。
ArrayList和Vector有何异同点?
ArrayList和Vector在很多时候都很类似。
(1)两者都是基于索引的,内部由-一个数组支持。
(2)两者维护插入的顺序,我们可以根据插入顺序来获取元素。
(3) ArrayList和Vector的迭代器实现都是fail-fast的。
(4) ArrayList和Vector两 者允许null值,也可以使用索引值对元素进行随机访问。
ArrayList和Vector的不同点。
(1) Vector 是同步的,而ArrayList不是。 然而,如果你寻求在迭代的时候对列表进行改变,你应该使
用CopyOnWriteArrayList。
(2) ArrayList比Vector快, 它因为有同步,不会过载。
(3) ArrayList更加通用,因为我们可以使用Collections具类轻易地获取同步列表和只读列表。
Array与ArrayList的区别
- Array可以存储基本数据类型和对象,ArrayList 只能存储对象。
- Array是指定固定大小的,而ArrayList大小是自动扩展的。
- Array内置方法没有ArrayList多,比如addAll、removeAll、 iteration 等方法只有ArrayList有。
HashMap的底层实现原理? (高频 )
浅拷贝实现 Cloneable,深拷贝是通过实现 Serializable 读取二进制流
String str = new String(“abc”) 创建了几个字符串对象?
1 个或者 2 个。
- 如果字符串常量池中已经有"abc"存在,这种情况只需要新建1个对象,否则就需要新建2个对象。
- 当字符串常量池没有
"abc"
,此时会创建如下两个对象:
一个是字符串字变量 “abc” 所对应的、驻留(intern)在一个全局共享的字符串常量池中
的实例,此时该实例也是在堆中,字符串常量池只存放引用。
另一个是通过new String()
创建并初始化的,内容与"abc"相同的实例,也是在堆
中。
总结:new String("xxx")
; 如果字符串常量池intern中没有对应的xxx
那么就需要在字符串常量池新建,然后再在堆上new 一个对象。
Java中静态变量/成员变量、静态内部类/成员内部类的区别
静态内部类和内部类的关系
- 只有内部类才能被声明为静态类,即静态内部类;
- 只能在内部类中定义静态类;
- 静态内部类与外层类绑定,即使没有创建外层类的对象,它一样存在;
- 静态类的方法可以是静态的方法也可以是非静态的方法,静态的方法可以在外层通过静态类调用,而非静态的方法必须要创建类的对象之后才能调用;
- 静态内部类只能引用外部类的static成员变量(也就是类变量)
如果一个内部类不是被定义成静态内部类,那么在定义成员变量或者成员方法的时候,是不能够被定义成静态的;
总结:
- 是否能拥有静态成员:静态内部类可以有静态成员(方法,属性),而非静态内部类则不能有静态成员(方法,属性)
- 访问外部类的成员是否有限制:静态内部类只能够访问外部类的静态成员,而非静态内部类则可以访问外部类的所有成员(方法,属性)
- 静态内部类和非静态内部类在创建时有区别:
静态变量/成员变量
- 成员变量存在于堆内存中。
- 静态变量存在于方法区中。
- 成员变量与对象共存亡,随着对象创建而存在,随着对象被回收而释放。
- 静态变量与类共存亡,随着类的加载而存在,随着类的消失而消失。
- 成员变量所属于对象,所以也称为实例变量。
- 静态变量所属于类,所以也称为类变量。
- 成员变量只能被对象所调用 。
- 静态变量可以被对象调用,也可以被类名调用。