面试题

spring模块

一,什么是依赖注入,什么是控制反转(IOC),在spring中有几种依赖注入的方式

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。

把由程序代码操控的对象的调用权交给容器,通过容器实现对象组件的装配和管理。所谓的"控制反转"就是对组件对象控制权的转移,从程序代码本身转移到了外部容器,由容器来创建对象并管理对象之间的依赖关系。

其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)

依赖注入(DI)是spring核心,依赖注入早期叫反向控制,因为spring将类主动的加载依赖的对象的任务交给了容器负责,而类只需要使用这些类就行,

类也无需关心依赖对象的具体实现,实现了松耦合,方便进行模块测试。

注入方式:

构造函数注入。

set注入。

接口注入。

二,Spring中有几种配置bean的方式

基于XML的配置

基于注解的配置

基于java的配置

三。spring中一个bean的生命周期。

创建一个bean,首先需要实例化,然后设置属性值,设置bean的name,然后统通过一系列的初始化操作,bean就可以提供使用,当容器关闭时进行析构操作销毁bean。

这是beanFactory中简单bean的装配过程,若这个bean在spring的引用上下文中,则会在初始化的过程中,再调用一下setApplicationContext方法。

四,spring bean的作用。

spring中bean的作用域默认为单例的,singleton 。

prototype,与singleton相反,prototype是多例的,他为每一个bean请求单独创建一个实例,

但是既然是单例的怎么保证线程安全呢,spring是使用单实例,多线程的方式,不同请求同时访问时,调用的是同一个实例,但是具体方法在不同线程中执行,就是说

方法中的局部变量是线程安全的,类中的全局变量就需要进行线程安全的处理

五,spring自动装配的几种方式

1.no,spring 的默认装配方式,在该方式下,spring的自动装配功能是关闭的。

2.byName:spring会自动寻找beanId与实例对象名称相同的的配置bean并自动注入,若没有则报错。

3,.byType:spring会自动寻找与实例对象类型相同的配置bean并自动注入,若没有则报错

4.constructor :构造器的自动装配和 byType 模式类似,但是仅仅适用于与有构造器相同参数的 bean ,如果在容器中没有找到与构造器参数类型一致的 bean ,那么将会抛出异常 。

5.autodetect:spring会自动测试构造器自动装配或者 byType 类型的自动装配

六,说说BeanFactory和applicationContext的区别

beanfactory是底层的实例化接口,他只能提供简单的注入的功能,applicationContext则更多的提供了企业级的服务

两者的区别:其中BeanFactory是延迟加载,也就是说知道代码中调用了getBean,bean才会被spring装配,

而applicationContext则在项目启动时,就会装载所有的bean。当然,applicationContext它还可以为 Bean 配置 lazy-init=true 来让 Bean 延迟实例化。

延迟实例化的优缺点

优点:启动时占用资源较少,对于占用资源相对较多的应用比较有优势。

缺点:速度会相对来说慢一些 。 而且有可能会出现空指针异常的错误,并且在项目启动时就加载bean方便更早的查找出bean的配置问题。

web应用推荐启动时就把所有的bean都给加载了。

七.spring 管理事务的方式

编程式事务

声明式事务

其中声明式事务又被分为两类。

基于xml的声明式事务

基于注解的声明式事务

八,spring中的代理方式有哪些

1,若被代理对象是一个借口,则使用jdk中的java.long.reflect.proxy代理,生成实现它的实现类。

优点。因为使用接口,所以使系统更加松耦合

缺点。需要为每一个代理目标编写借口

2.若代理对象是一个java类,则使用 CGLIB 库生成目标对象的子类 。

优点。不需要接口的存在

缺点。松散耦合度没有使用接口的好

九,IOC容器的初始化过程

1.rescourse定位。

2.载入

3.注册

十,AOP的实现原理:动态代理,区别参考第八条

 十一,spring框架的事务管理的优点,支持声明式事务。

总结:

Spring框架优点:

方便解耦,简化开发:

Spring就是一个大工厂,可以将所有对象创建和依赖关系维护,交给Spring管理(代码没有入侵性)

1.AOP编程的支持:

Spring提供面向切面编程,可以方便的实现对程序进行权限拦截、运行监控等功能(便于功能扩展)

2.声明式事务的支持:

只需要通过配置就可以完成对事务的管理,而无需手动编程

3.方便程序的测试:

Spring对Junit4支持,可以通过注解方便的测试Spring程序

方便集成各种优秀框架:

数据库模块

基本的增删改查sql语句

select * from table where 

update table set colum1=1,colum2=2...where...

insert into table(colum1.2.3...)value(1.2.3..)

delete from table where..

CREATE TABLE `NewTable` (
`id` int NOT NULL AUTO_INCREMENT ,
`name` varchar(255) NULL ,
PRIMARY KEY (`id`)
)

一,什么是存储过程,他的优缺点是什么

存储过程是预编译的sql语句,优点是允许模块化的设计,就是说只需要创建一次,就可以在程序中可以使用存储过程名多次调用,如果程序中多次执行sql语句,存储过程比单纯执行sql语句效率高

好处:因为是预编译的sql语句,所以执行效率高

   存储语句是直接放在数据库中,所以减少了网络通讯。

   使用需要权限,所以安全性高

   一次创建多次调用,减少了开发者的工作量

缺点:移植性差

二,为什么使用自增列作为主键。

首先主键必须确保非空和唯一性。这两点自增列都能满足。

并且当一页数据填满后,会自动开启新的一页

第二,若使用类似身份证或者学号这种编号,生成记录是可以说是随机的,就是说有可能会插入数据到现有索引列的中间的某个位置,这样mysql会为了将数据插入到合适位置,不得不移动数据,

这样增加了许多的开销

三,什么叫视图

视图是一种虚拟的表,他和物理表有一样的功能,都可以进行增删改查,视图通常包含一个或多个表中行或列的子集,对视图的修改会影响基本表,方便我们查询和修改数据库

四,drop,delete,truncate的区别

drop:直接删除整表,

delete:仅删除表中的数据

truncare:删除表中数据,并让自增列从1开始

五,关系型数据库和非关系型数据库的区别

非关系型数据库,通常采用键值对的形式存储数据,因此执行效率更快

因为数据之间没有耦合,所以方便水平扩展,扩展性高。

关系型数据库:安全新高,可以使用复杂的sql语句做复杂的数据查询

六,什么是内连接,左外连接,右外连接,笛卡尔积等

内连接:只查询匹配的行即可

SELECT a.,b. FROM luntan as a, usertable as b ON a.username=b.username

左外连接:包含左边表的全部行(不管右边的表中是否存在与它们匹配的行),以及右边表的匹配行
SELECT a.,b. FROM luntan as a LEFT JOIN usertable as b ON a.username=b.username

右外连接:包含右边表的全部行(不管左边的表中是否存在与它们匹配的行),以及左边表的匹配行

SELECT a.,b. FROM luntan as a RIGHTJOIN usertable as b ON a.username=b.username

全外连接:包含左右两表的全部行,不管另外一边的表中是否存在与它们匹配的行。

SELECT a.,b. FROM city as a FULL OUTER JOIN user as b ON a.username=b.username

交叉连接: 生成笛卡尔积(笛卡尔积,左边表中的每一行记录,匹配右边表的所有记录,当多表联查未做外键关联时,会自动做笛卡尔积)

SELECT type,pub_name FROM titles CROSS JOIN publishers ORDER BY type

七,什么是临时表

当查询语句设计多个表时,都会生成一张中间临时表,再把这个临时表反馈给用户,临时表只在当前连接可见,当数据库连接关闭时,mysql会自动删除并释放所有临时表空间

八,on和where的区别

举个栗子,在left join中

on:on是在生成临时表时使用的条件,不管on后面的条件是否为真,都会将左边的记录返回

where:where是在临时表生成之后进行筛选的条件。

java基础

一,基础变量和引用变量

基础变量:int char long double short float byte boolean

引用类型是用类的编译器定义的,他用于访问对象

二,Switch是否可以用String做参数

因为String是引用数据类型

在JDK1.7之前Switch只支持int,byte,short,chat这几个基本数据类型

在1.7之后允许使用整形,枚举,字符串都可以

三,equals和==的区别

==用于比较内存地址是否相同,equals用户比较内存中的值是否相同

基础数据类型创建时会在常量池中寻找是否存在,若不存在则创建并返回引用,所以基础数据类型用==比较,而引用数据类型,类似String会在每次创建时生成新的引用对象,内存地址都不同,所以用equals比较值是否相同

四,自动装箱和常量池

常量池用于存放常量

byte,short,char,float,int,double,long,boolean八大基础数据类型生成的变量都是常量

首先会在常量池中寻找是否存在,若存在则返回引用,若不存在则创建并返回引用

int a = 1;创建普通变量

Integer b = a;自动装箱

int c = b;自动拆箱

Integer b = 100;自动装箱

自动装箱是将一个java定义的基本数据类型赋值给相应封装类的变量。 拆箱与装箱是相反的操作,自动拆箱则是将一个封装类的变量赋值给相应基本数据类型的变量。

五,java中多线程实现的方式,以及使用

两种常见的实现方式,继承Thread类或者实现Runable接口

继承Thread本质上就是一个实现了Runable接口的一个实例:

重写run方法,并通过start执行run方法

public class MyTthread extends Thread(){

  public void run(){

    system.out.printl("线程执行");

  }

}

MyThread thread1 = new MyThread();

MyThread thread2 = new MyThread();

thread1.start();

thread2.start();

实现Runable接口

public class MyThread extends OtherClass implements Runable(){

  public void run(){

    system,out.printl("线程执行");

  }

}

MyThread myThread= new MyThread();

Thread thread = new Thread(myThread);  

thread.start();  

在多线程中,不推荐使用循环创建线程然后start调用,因为创建和销毁线程非常的消耗资源,一般使用线程池

https://www.cnblogs.com/wxd0108/p/5479442.html

synchronized的使用

synchronized通过锁,来保证一段代码或代码块只有一个线程在执行,是高并发实现的基础

java中每一个对象都可以作为锁,

不用static修饰的方法的锁叫普通同步锁,锁属于创建的对象

用static修饰的锁叫静态方法锁,静态方法属于类,所以锁属于类

六,java的四种引用类型,以及适用场景

从高到低分别为强引用,弱引用,软引用,虚引用

强引用:java中最常用的引用类型,直接使用=连接的引用, 只要强引用存在垃圾回收机制就不会销毁引用。

弱引用:可以说是一种有用但是不是必须的引用对象,若内存够,则不会回收,若内存不会,则被回收,一般用于实现内存敏感的高速缓存

软引用:软引用是只要被垃圾回收检测到,不管内存是否够,都会被回收。

虚引用:虚引用和其他引用不同,不存在生命周期,虚引用就和没有引用一样,任何时候都有可能被回收,虚引用一般用来跟踪被垃圾回收器回收的活动。

七,HashCode的理解

hash,通常翻译成散列,是将任意长度的输出通过散列算法转化成固定长度输出,这个输出就是hashcode,hashcode相同,就会被放到同一个散列中。

hashCode通常的作用是保证查找的快捷性,经常用于确定对象的存储地址

在list和set中,list元素有序,并且可重复,但是set元素是无序并且不可重复的。

若每次添加元素,都要调用equals判断是否相等,当元素一多,效率就变得非常慢。

所以先调用hashcode若这个hashcode不相等,则直接添加,若相同,则说明两元素在同一个散列中,再调用equals判断是否相等。

因此hashcode一般用于定位,equals用于判断是否相等,若hashcode重写,equals也最好重写。

通常情况下是不需要重写hashcode方法的,当数据需要放在hashmap,hashtable中时,可能会根据业务需要重写hashcode和equals方法

八,list的三个子类

list的三个子类,ArrayList,LInkedList,Vector

ArrayList:底层数据结构是数组,查询快,增删慢

线程是不安全的,效率高

LinkedList:底层数据结构是链表,查询慢,增删快。

线程是不安全的,效率高

Vector:底层数据结构是数组,查询慢,增删快

线程是安全的,效率低

Vector相比ArrayList查询更慢

Vector相比LinkedList增删更慢

ArrayList和LinkedList的区别:

ArrayList查询更快,LInkedList增删更快

ArrayList底层数据结构是数组,LinkedList底层数据结构是链表

共同点:都是线程安全的

ArrayList和Voctor的区别

ArrayList是线程不安全的,Voctor是线程安全的

ArrayList的效率比Voctor的效率更高

共同点:底层的数据结构都是数组

九,String,StringBuilder,StringBuffer三者的区别,

三者之中,String的效率最低,原因是String的不可变性,每次修改值都需要创建新的引用,因此String适合少量操作的时候。

StringBuilder适合单线程情况下需要大量数据操作的时候,因为他是线程不安全的

StringBuffer适合多线程情况下需要大量数据操作的时候,因为他是线程安全的

StringBuffer中的很多方法都带有synchronized关键字,而StringBuilder则没有

 十,inertface和abstract的区别

inertface中只能有成员常量和方法的声明,abstract class可以拥有成员变量并且可以声明普通方法和抽象方法。

inertface是接口,所有的声明默认前缀都是public static final 接口不能实例化自己

abstract是抽象类,至少包含一个抽象方法的类叫抽象类,抽象类不能被自身实例化,并且需要被abstract修饰

一个类遵循单继承,多实现。

十一,描述Cookie和Session的作用,区别和各自的应用范围,Session工作原理

Cookie是在客户端开辟的一块可长期存储用户信息的地方;Session是在服务器内存中开辟的一块存储用户信息的地方;

当客户第一次访问服务器时,服务器在内存创建对应的Session给访问客户,当客户离开或时间过期时;服务器自动销毁Session; Session是由容器管理的

十二,override和overload的区别

override:重写,子类重写的方法必须 和父类的返回值,参数,方法名一样

不能缩小父类方法的访问权限

不能抛出比父类更多的异常

若父类的方法被定义为了final,则不可以被重写

overload:重载

在同一个类中,方面名必须一致

参数的类型,个数,顺序至少一个不同

不能重载只有返回值不同的方法

十三,java中xml的解析方式

DOM,SAX这两种是系统自带的,还有JDOM和DOM4J需要导入jar包

DOM通过层次结构(树)解析xml,将整个xml解析后以树的形式放在内存中。效率较低

SAX,是使用流模型,每发现一个节点,效率较高

十四,面向过程和面向对象的区别

面向过程的性能由于面向对象,因为类再调用时需要实例化,消耗资源,因此如果性能是第一考量时,会选择面向过程开发,但是面向过程没有面向对象的易复用,易扩展,易维护的有点

面向对象开发因为有封装,继承,多态的特性,可以开发出低耦合的系统。

* 但是这个并不是根本原因,面向过程也需要分配内存,计算内存偏移量,Java性能较低的原因java是半编译语言,最后的执行代码并不是并不是cpu可以直接执行的二进制机械码。

而面向过程语言大多直接编译成机器码在电脑上运行。

https://blog.csdn.net/as6757uyy65uy75/article/details/79370686

原文地址:https://www.cnblogs.com/jinsheng1027/p/11615503.html