面试题
面试题
Q01:
面向对象的三大特性?
说一下ACID是什么(事务的四大特性)?
A01:
OOP:
- 封装
是面向对象方法的重要原则,就是把对象的属性和操作(或服务)
结合为一个独立的整体,并尽可能隐藏对象的内部实现细节。
- 继承
是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,
新的类能吸收已有类的数据属性和行为,并能扩展新的能力。
- 多态。
是同一个行为具有多个不同表现形式或形态的能力。
多态就是同一个接口,使用不同的实例而执行不同操作。
事务:
1)A —— 原子性(不可分割)
2)C —— 一致性(操作前后总量不变)
3)I —— 隔离性(同时操作同一条记录,他们之间是不会产生影响的)
4)D —— 持久性(事务提交后,表数据会真正发生改变)
Q02:
访问权限修饰符有哪些?
包访问权限的修饰范围是怎样的?
A02:
访问权限 同一个类 同一个包 子父类 不同包
public √ √ √ √
protected √ √ √ ×
default √ √ × ×
private √ × × ×
- 包访问权限:同类、同包可访问,子父类、不同包不可访问。
Q03:集合ArrayList和LinkedList的区别?
A03:
- ArrayList:底层是数组,所以对于查询来说更快;
- LinkedList:底层是链表(双链表),对于增删改操作更快。
Q04:HashMap和Hashtable的区别?
A04:
- 父类不同
- HashMap继承自AbstractMap类
- Hashtable继承自Directory类
- 对null的支持不同
- HashMap的key可以为null但这样的key只能有一个
- Hashtable的key和value都不能为null
- 安全性不同
- HashMap线程不安全(效率高)
- Hashtable线程安全(效率较低)
- 初始容量大小、每次扩充容量大小不同
- HashMap(初始:16 扩充:2倍)
- Hashtable(初始:11 扩充:2n+1)
- 计算hash值的方法不同
Q05:String、StringBuffer、StringBuilder的区别?
A05:
- String对象是不可变的,对String对象的增删改,实际上是创建了一个新的对象。
- StringBuffer是可变的,对StringBuffer对象的增删改是不会创建新对象的,并且它是线程安全的。
= StringBuilder是可变的,对StringBuilder对象的增删改是不会创建新对象的,它不是线程安全的。
Q06:使用泛型的好处?
A06:
以集合来举例,使用泛型的好处是我们不必因为添加元素类型的不同而定义不同类型的集合,
如整型集合类,浮点型集合类,字符串集合类,我们可以定义一个集合来存放整型、浮点型,
字符串型数据,而这并不是最重要的,因为我们只要把底层存储设置了Object即可,
添加的数据全部都可向上转型为Object。
更重要的是我们可以通过规则按照自己的想法控制存储的数据类型。
Q07:
String是基本数据类型吗?
Java中有几种数据类型?
如何判断一个字符串是否为空串?
A07:
String不是基本数据类型,是引用类型。
byte、short、int、long、float、double、boolean、char。
判断空串:
1、使用equals:"".equals(str.trim()
2、使用length():str.trim().length() > 0
Q08:什么是拆箱、装箱?
A08:
拆箱:包装数据类型 转换为 基本数据类型(Integer -> int)
装箱:基本数据类型 装换为 包装数据类型(int -> Integer)
Q09:
重载和重写的区别?
构造方法可以重写?重载?
A09:
- 重写:
1、发生在父类与子类之间;
2、方法名,参数列表,返回类型(除过子类中方法的返回类型是父类中返回类型的子类)必须相同
(子类方法的返回类型必须是父类方法返回类型的同类或者派生类);
3、访问修饰符的限制一定要大于被重写方法的访问修饰符(public > protected > default > private);
4、重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常。
- 重载
1、重载Overload是一个类中多态性的一种表现;
2、重载要求同名方法的参数列表不同(参数类型,参数个数甚至是参数顺序);
3、重载的时候,返回值类型可以相同也可以不相同。无法以返回型别作为重载函数的区分标准。
- 构造方法可以重载,不可以重写(因为构造方法不能被继承,只能调用one)。
Q:java 中 IO 流分为几种?
A:
1)按流划分,可以分为输入流和输出流;
2)按单位划分,可以分为字节流和字符流;
字节流:inputStream、outputStream;
字符流:reader、writer;
Q10:
说说IOC、AOP?
Java创建对象的方法?
A10:
- IOC
Spring 框架的核心是 Spring 容器。容器创建对象,将它们装配在一起,
配置它们并管理它们的完整生命周期。Spring 容器使用依赖注入
来管理组成应用程序的组件。容器通过读取提供的配置元数据来接收对象进行实例化,
配置和组装的指令。该元数据可以通过 XML,Java 注解或 Java 代码提供。
- AOP
AOP(Aspect-Oriented Programming), 即面向切面编程,
它与OOP( Object-Oriented Programming,面向对象编程) 相辅相成,
提供了与OOP 不同的抽象软件结构的视角.
在 OOP 中, 我们以类(class)作为我们的基本单元,
而 AOP 中的基本单元是 Aspect(切面)
- 创建对象的方法:
1、构造方法(new)
2、反射
先创建Class对象,再使用newInstance()方法,
通过调用所对应类的空参数构造方法,创建类的对象。
3、反序列化
把磁盘中的对象数据或者网络节点上的对象数据,恢复成Java对象模型的过程。
通俗来说就是将序列化生成的二进制串转化为对象。
4、克隆
也分为深拷贝和浅拷贝,通过调用对象的clone方法,进行对象的克隆(拷贝)创建。
5、动态代理
使用Proxy类的静态方法,创建代理对象
6、IoC(容器创建)
通过DI(依赖注入)来创建对象
Q:AOP有哪些实现方式?
A:
实现 AOP 的技术,主要分为两大类:
1、静态代理 - 指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强;
- 编译时编织(特殊编译器实现)
- 类加载时编织(特殊的类加载器实现)。
2、动态代理 - 在运行时在内存中“临时”生成 AOP 动态代理类,因此也被称为运行时增强。
- JDK 动态代理
- CGLIB
Q:说说SpringMVC的转发和重定向?
A:
- 转发(forward):
客户端一次访问实现资源的访问,转发可以是WEB-INF中的资源。(可以访问受保护资源)
比如:将用户对当前处理的请求转发给另一个视图或处理请求,以前的 request 中存放的信息不会失效。
- 重定向(redirect)
客户端多次访问实现资源的访问,重定向不可是WEB-INF中的资源。(不能访问受保护资源)
比如:将用户从当前处理请求定向到另一个视图或处理请求,
以前的请求(request)中存放的信息全部失效,并进入一个新的 request 作用域。
- 转发是服务器行为,重定向是客户端行为。
Q:Spring AOP and AspectJ AOP 有什么区别?
A:
Spring AOP 基于动态代理方式实现;AspectJ 基于静态代理方式实现。
Spring AOP 仅支持方法级别的 PointCut;提供了完全的 AOP 支持,它还支持属性级别的 PointCut。
Q11:@Autowired注解有什么用?@Qualifier注解有什么用?
A11:
@Autowired
可以更准确地控制应该在何处以及如何进行自动装配。
此注解用于在 setter 方法,构造函数,具有任意名称或多个参数的属性
或方法上自动装配bean。默认情况下,它是类型驱动的注入。
@Qualifier
容器中可能存在同类型的多个Bean,
假如只是一个简单的@Autowired,Spring根本不知道你要注入哪个bean。
这就需要@Qualifier(value =“beanName”)协作.
Q12:为什么使用SpringBoot?SpringBoot的优点?
A12:
- 独立运行
Spring Boot而且内嵌了各种servlet容器,Tomcat、Jetty等,
现在不再需要打成war包部署到容器中,Spring Boot只要打成一个
可执行的jar包就能独立运行,所有的依赖包都在一个jar包内。
- 简化配置
spring-boot-starter-web启动器自动依赖其他组件,简少了maven的配置。
- 自动配置
Spring Boot能根据当前类路径下的类、jar包来自动配置bean,
如添加一个spring-boot-starter-web启动器就能拥有web的功能,无需其他配置。
- 无代码生成和XML配置
Spring Boot配置过程中无代码生成,
也无需XML配置文件就能完成所有配置工作,
这一切都是借助于条件注解完成的,
这也是Spring4.x的核心功能之一。
- 应用监控
Spring Boot提供一系列端点可以监控服务及应用,做健康检测
Q13:你如何理解 Spring Boot 中的 Starters?
A13:
Starters可以理解为启动器,它包含了一系列可以集成到应用里面的依赖包,
你可以一站式集成 Spring 及其他技术,而不需要到处找示例代码和依赖包。
如你想使用 Spring JPA 访问数据库,只要加入
spring-boot-starter-data-jpa 启动器依赖就能使用了
Q14:大概说一下SpringBoot集成MyBatis的过程?
A14:
1、添加mybatis的starter maven依赖
(org.mybatis.spring.boot mybatis-spring-boot-starter 1.2.0)
2、在mybatis的接口中添加@Mapper注解
3、在application.yml配置数据源信息
Q15:Spring Boot、Spring MVC 和 Spring 有什么区别?
A15:
- Spring
Spring最重要的特征是依赖注入。
所有 SpringModules 不是依赖注入就是 IOC 控制反转。
当我们恰当的使用 DI 或者是 IOC 的时候,我们可以开发松耦合应用。
松耦合应用的单元测试可以很容易的进行。
- SpringMVC
Spring MVC 提供了一种分离式的方法来开发 Web 应用。
通过运用像:
DispatcherServelet
SpringWebMVC的集中访问点,而且负责职责的分派(将请求进行映射),
ModelAndView
适用于返回数据的同时又要在资源之间进行跳转(forward)
ViewResolver
逻辑视图名称解析为对象的 View 对象。
View 接口的主要作用是用于处理视图,然后返回给客户端。
等一些简单的概念,开发 Web 应用将会变的非常简单。
- SpringBoot
Spring 和 SpringMVC 的问题在于需要配置大量的参数。
Spring Boot 通过一个自动配置和启动的项来目解决这个问题。
Q16:简单说一下spring中常有的几个advice?
A16:
1)@Before————public void myBefore(){}
前置通知(方法无返回值,方法参数可有可无)
2)@AfterReturning————public void myAfterReturning(Object res){}
后置通知(方法无返回值,方法有参数(推荐:Object))
3)@Around————public Object myAround(ProceedingJoinPoint pjp)
环绕通知(方法有返回值(推荐:Object),方法有参数(ProceedingJoinPoint))
常用来做事务,方法执行前开启事务,执行完毕后提交事务。
方法有参数:ProceedingJoinPoint(等同于JDK动态代理中的Method)。
特点:
· 功能最强的通知
· 在目标方法前/后进行功能增强
· 控制目标方法是否被调用执行
· 修改返回结果,影响目标方法的调用。
目标方法调用:
pjp.proceed(); < —— > method.invoke();
4)@AfterThrowing
异常通知(方法无返回值,方法有参数(Exception))
try……catch……
5)@After
最终通知
总是会被执行的代码,一般做资源清除工作。
try……catch……finally……
Q17:简述SpringBoot自动装配?
A17:
SpringBoot启动类
@SpringBootApplication
@SpringBootConfiguration
通过@SpringBootConfiguration注解标识SpringBootApplication是一个SpringBoot配置类
@EnableAutoConfiguration注解
通过此注解实现自动装配
@AutoConfigurationPackage注解SpringBoot启动类
通过@AutoConfigurationPackage注解将添加,
该注解的类所在的package作为自动配置package进行管理
@EnableAutoConfiguration
AutoConfigurationImportSelector.class,将需要装配的类装配到IoC容器中。
Q18:线程有几个状态?分别是什么?
A18:
• NEW:初始状态,线程被创建出来但没有被调用 start()。
• RUNNABLE:运行状态,线程被调用了 start()等待运行的状态。
• BLOCKED :阻塞状态,需要等待锁释放。
• WAITING:等待状态,表示该线程需要等待其他线程做出一些特定动作(通知或中断)。
• TIME_WAITING:超时等待状态,可以在指定的时间后自行返回而不是像 WAITING 那样一直等待。
• TERMINATED:终止状态,表示该线程已经运行完毕。
Q19:开发过程中,什么时候考虑使用多线程?
A19:
异步处理时候需要使用多线程比如:
1、记录日志
2、发短信
3、推送场景
Q20:列举Java线程创建的几种方式?
A20:
1、继承Thread类创建线程
2、实现Runnable接口创建线程
3、实现Callable接口创建线程(通过Callable和Future创建线程)
4、基于线程池创建线程
Q21:sleep()和wait()的区别?
A21:
1、sleep()方法,是属于 Thread 类中的。而 wait()方法,则是属于Object 类中的。
2、sleep()方法导致了程序暂停执行指定的时间,让出 cpu 该其他线程,
但是他的监控状态依然保持着,当指定的时间到了又会自动恢复运行状态。
3、在调用 sleep()方法时,线程不会释放对象锁。
4、在调用 wait()方法时,线程会放弃对象锁,进入等待此对象的等待锁定池,
只有针对此对象调用 notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
Q22:Thread类中的start()和run()方法有什么区别?
A22:
start()方法被用来启动新创建的线程,而且start()内部调用了run()方法,
这和直接调用run()方法的效果不一样。
当你调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,
start()方法才会启动新线程。
Q23:什么是乐观锁?
A23:
乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,
每次去拿数据的时候都认为别人不会修改,所以不会上锁,
但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,
采取在写时先读出当前版本号,然后加锁操作(比较跟上一次的版本号,如果一样则更新),
如果失败则要重复读-比较-写的操作。
Q24:什么是悲观锁?
A24:
悲观锁是就是悲观思想,即认为写多,遇到并发写的可能性高,
每次去拿数据的时候都认为别人会修改,所以每次在读写数据的时候都会上锁,
这样别人想读写这个数据就会 block 直到拿到锁。
java中的悲观锁就是Synchronized。
AQS框架下的锁则是先尝试cas乐观锁去获取锁,获取不到,才会转换为悲观锁,如 RetreenLock。
DJOSIMON