面试题库
5.常规技术面试题(数据库)
1. 触发器的作用?
触发器是一个特殊的存储过程,主要是通过事件来触发而被执行的。它可以强化约束,来维护数据的完整性和一致性,可以跟踪数据库内的操作从而不允许未经许可的更新和变化。可以联级运算。如,某表上的触发器上包含对另一个表的数据操作,而该操作又会导致该表触发器被触发。
2. 什么是存储过程?用什么来调用?
存储过程是一个预编译的SQL语句,优点是允许模块化的设计,就是说只需创建一次,以后在程序中就可以调用多次。如果某次操作需要执行多次SQL,使用存储过程比单纯SQL语句执行要快。可以用一个“execute 存储过程名 参数”命令来调用存储过程。
3. 索引的作用?和它的优点缺点是什么?。
索引就一种特殊的查询表,数据库的搜索引擎可以利用它加速对数据的检索。它很类似与现实生活中书的目录,不需要查询整本书内容就可以找到想要的数据。索引可以是唯一的,创建索引允许指定单个列或者是多个列。缺点是它减慢了数据录入的速度,同时也增加了数据库的尺寸大小。
4. 主键和索引的区别?
1.主键时为了标识数据库记录唯一性,不允许记录重复,且键值不能为空,主键也是一个特殊索引;
2.数据表中只允许有一个主键,但是可以有多个索引;
3.使用主键数据库会自动创建主索引,也可以在非主键上创建索引,方便查询效率;
4.索引可以提高查询速度,它就相当于字典的目录,可以通过它很快查询到想要的结果,而不需要进行全表扫描;
5.唯一索引则标识该索引值唯一,可以由一个或几个字段组成,一个表可以有多个唯一索引。
5. 什么是内存泄漏?
一般我们所说的内存泄漏指的是堆内存的泄漏。当应用程序用关键字new等创建对象时,就从堆中为它分配一块内存,使用完后由于某种原因程序未释放或无法释放,造成系统内存的浪费。导致程序运行速度减慢甚至系统崩溃等严重后果。
6. 维护数据库的完整性和一致性,你喜欢用触发器还是自写业务逻辑?为什么?
我是这样做的,尽可能使用约束,如check,主键,外键,非空字段等来约束,这样做效率最高,也最方便。其次是使用触发器,这种方法可以保证,无论什么业务系统访问数据库都可以保证数据的完整新和一致性。最后考虑的是自写业务逻辑,但这样做麻烦,编程复杂,效率低下。
7. 什么是事务?
事务就是被绑定在一起作为一个逻辑工作单元的SQL语句组,如果任何一个语句操作失败那么整个操作就被失败,进而回滚到操作前状态,或者是上个节点。为了确保要么执行,要么不执行,就可以使用事务。要将一组语句作为事务考虑,就需要通过ACID测试,即原子性,一致性,隔离性和持久性。
8. 什么是锁?
在所有的DBMS中,锁是实现事务的关键,锁可以保证事务的完整性和并发性。与现实生活中锁一样,它可以使某些数据的拥有者,在某段时间内不能使用某些数据或数据结构。当然锁还分级别的。
9. 什么叫视图?
视图是一种虚拟的表,具有和物理表相同的功能。可以对视图进行增,改,查,操作,视图通常是由一个表或者多个表的行或列的子集。它使得我们获取数据更容易,相比多表查询。
10. 视图创建和使用语法?
1.首先判断是否存在
if exists (select * from sysobjects where name = '视图名')
drop view View_EdsProd
Go
2. 创建视图
create view View_EdsProd as select * from Tab_EdsProd where Mid>1(条件) go
3. 使用视图
select *from View_EdsProd
11. 游标是什么?
游标是SQL 的一种数据访问机制。可以将游标简单的看成是查询的结果集的一个指针,可以根据需要在结果集上面来回滚动,浏览需要的数据。
12. 你能向我简要叙述一下SQL Server 中使用的一些数据库对象吗?
表、索引、视图、存储过程、触发器、用户定义函数、数据库关系图、全文索引。
13. NULL是什么意思?
NULL(空)这个值表示UNKNOWN(未知):它不表示“”(空字符串)。不能把任何值与一个 UNKNOWN值进行比较,都会生产一个NULL值。您必须使用IS NULL操作符。
14. 什么是索引,有哪些索引,具体怎么用?
索引是与表或视图关联的磁盘上结构,可以加快从表或视图中检索行的速度。索引包含由表或视图中的一列或多列生成的键。这些键存储在一个结构(B 树)中,使 SQL Server 可以快速有效地查找与键值关联的行。
索引分为聚集索引和非聚集索引。
在数据库系统中建立索引主要有以下作用:
(1)快速取数据;
(2)保证数据记录的唯一性;
(3)实现表与表之间的参照完整性;
(4)在使用ORDER by、group by子句进行数据检索时,利用索引可以减少排序和分组的时间。
15. SQL Server 里有什么类型的索引?
在SQL Server里,它们有两种形式:聚集索引和非聚集索引。聚集索引在索引的叶级保存数据。每个表格只会有一个聚集索引。非聚集索引在索引的叶级有一个行标识符。每个表格有多个非聚集索引。
16. 什么是主键?
主键是表格里的(一个或多个)字段,只用来定义表格里的行;主键里的值总是唯一的。
17. 什么是外键?
外键是一个用来建立两个表格之间关系的约束。这种关系一般都涉及一个表格里的主键字段与另外一个表格(可能是同一个表格)里的一系列相连的字段。那么这些相连的字段就是外键。
18. 什么是触发器?
触发器是一种专用类型的存储过程,它被捆绑到SQL Server 的表格或者视图上。
19. SQL Server 有什么不同类型的触发器?
有INSTEAD-OF和AFTER两种触发器。例如,如果有一个用于TableA的INSTEAD-OF-UPDATE触发器,同时对这个表格执行更新语句,那么INSTEAD-OF-UPDATE触发器里的代码会执行,而不是执行更新语句则不会执行操作。AFTER触发器要在DML语句在数据库里使用之后才执行。这些类型的触发器对于监视发生在数据库表格里的数据变化十分好用。
20. 您如何确保一个带有名为Fld1字段的TableB表格里只具有Fld1字段里的那些值,而这些值同时在名为TableA的表格的Fld1字段里?
第一个答案是使用外键限制。外键限制用来维护引用的完整性。它被用来确保表格里的字段只允许有已经在另一表格里的某个字段里定义了的值。通常是另外一个表格的主键。
另外一种答案是触发器。触发器可以被用来保证以另外一种方式实现与限制相同的作用,但是它非常难设置与维护,而且性能一般都很糟糕。
21. 对一个投入使用的在线事务处理表格有过多索引需要有什么样的性能考虑?
对一个表格的索引越多,数据库引擎用来更新、插入或者删除数据所需要的时间就越多,因为在数据操控发生的时候索引也必须要维护。
22. 你可以用什么来确保表格里的字段只接受特定范围里的值?
可以使用Check约束,它在数据库表格里定义,用来限制输入该列的值。
触发器也可以被用来限制数据库表格里的字段能够接受的值,但是这种办法要求触发器在表格里被定义,可能会在某些情况下影响到性能。
23. 概述存储过程及其优缺点。
存储过程是一个预编译的sql语句 ,编译后可多次使用
优势:响应时间上来说有优势,可以给我们带来运行效率提高的好处,且使用存储过程的系统更加稳定
缺点:维护性较差,相对于简单sql,存储过程并没有什么优势,并且在进行调试时比较困难
24. 什么是相关子查询?如何使用这些查询?
相关子查询是一种包含子查询的特殊类型的查询。查询里包含的子查询会请求外部查询的值,从而形成一个类似于循环的状况。
25. 什么是SQL注入式攻击?
所谓SQL注入式攻击,就是攻击者把SQL命令插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令。比如:攻击者在用户名字和密码输入框中输入"'或'1'='1"之类的内容。最后得到的SQL命令可能变成:SELECT * from Users WHERE login = '' or '1'='1' AND password = '' or '1'='1'。这时,已经不能真正验证用户身份,所以系统会错误地授权给攻击者。
26. 如何防范SQL注入式攻击?
只要在利用表单输入的内容构造SQL命令之前,把所有输入内容过滤一番就可以了。过滤输入内容可以按多种方式进行。
⑴ 对于动态构造SQL查询的场合,可以使用下面的技术:
第一:替换单引号,即把所有单独出现的单引号改成两个单引号,防止攻击者修改SQL命令的含义。
第二:删除用户输入内容中的所有连字符。
第三:对于用来执行查询的数据库帐户,限制其权限。
⑵ 用存储过程来执行所有的查询。
⑶ 限制表单或查询字符串输入的长度。
⑷ 检查用户输入的合法性,确信输入的内容只包含合法的数据。
⑸ 将用户登录名称、密码等数据加密保存。
⑹ 检查提取数据的查询所返回的记录数量。
27. 默认的系统数据库有哪些?
1)master数据库(主);2)tempdb数据库(临时);3)model 数据库(模板);4)msdb数据库(计划任务);
28. 默认创建一个数据库,会生成哪些文件?
1)主文件(.mdf),2)日志文件(.ldf),无次要文件(.ndf)。
29. 创建数据库时,能不能把数据文件和日志文件分开?
可以分开,起到优化作用。把数据文件放到高速读写区,把日志文件放到低速读写区。
30. 什么是索引覆盖(Index Covering)查询?
索引覆盖(Index Covering)查询是指数据可以只通过索引获取,而不用接触表。
31. 存储过程和触发器的区别?
触发器与存储过程的主要区别在于触发器的运行方式。存储过程必须有用户、应用程序或者触发器来显示的调用并执行,而触发器是当特定时间出现的时候,自动执行或者激活的,与连接用数据库中的用户、或者应用程序无关
32. 存储过程和函数的区别?
存储过程是用户定义的一系列SQL语句的集合,,而函数通常是数据库已定义的方法,具体区别如下:
??1.对于存储过程来说可以返回参数,而函数只能返回值或者表对象.
??2.函数必须有返回值,存储过程可有可无
??3.存储过程一般是作为一个独立的部分来执行,而函数可以作为查询语句的一部分来调用.
33. 聚集索引和非聚集索引区别
聚集索引,数据按索引顺序存储,中子结点存储真实的物理数据
非聚集索引,存储指向真正数据行的指针
34. 索引的优缺点,什么时候使用索引,什么时候不能使用索引?
索引最大的好处是提高查询速度,
缺点是更新数据时效率低,因为要同时更新索引
对数据进行频繁查询进建立索引,如果要频繁更改数据不建议使用索引。
35. 数据库的优化
1.创建适当的索引
2.对sql语句优化
使用exists或not exists代替in或not in
使用存储过程
用union替换or(适用于索引列)
where代替having,having 检索完所有记录,才进行过滤
使用select top或set rowcount来限制操作的行
避免嵌套查询
对多个字段进行等值查询时,联合索引
36. 数据库的主从复制
默认异步复制,容易造成主库数据和从库不一致
一个数据库为Master,一个数据库为slave,通过Binlog日志来实现
slave两个线程,一个线程去读master binlog日志,写到自己的中继日志
一个线程解析日志,执行sql
master启动一个线程,给slave传递binlog日志
半同步复制
只有把master发送的binlog日志写到slave的中继日志,这时主库才返回操作完成的反馈,性能有一定降低
并行复制
slave 多个线程去请求binlog日志
37. long_query怎么解决
设置参数,开启慢日志功能,得到耗时超过一定时间的sql
(1)slow_query_log 这句是开启记录慢查询功能,slow_query_log=0关闭;slow_query_log=1开启(这个1可以不写)
(2)long_query_time = 1 这句是记录超过1秒的SQL执行语句
38. varchar和char的使用场景
用来存储字符
varchar适用字符长度经常变的
char适用字符长度固定的
39. 数据库连接池的作用
维护一定数量的连接,减少创建连接的时间
更快的响应时间
统一的管理
40. 分库分表,主从复制,读写分离
读写分离,读从库,写主库
spring配置两个数据库,通过AOP(面向切面编程),在写或读方法前面进行判断得到动态切换数据源。
41. 数据库三范式
1NF 属性不可分
2NF 非主键属性,完全依赖于主键属性
3NF 非主键属性无传递依赖
42. 数据库中join的inner join, outer join, cross join
以A,B两张表为例 A left join B
选出A的所有记录,B表中没有的以null 代替
right join 同理
inner join
A,B的所有记录都选出,没有的记录以null代替
cross join (笛卡尔积)
A中的每一条记录和B中的每一条记录生成一条记录
例如A中有4条,B中有4条,cross join 就有16条记录
43. 有哪些锁,select时怎么加排它锁
乐观锁,悲观锁,排它锁,共享锁,更新锁,表锁,行级锁。
乐观锁:乐观锁不会锁住任何东西,也就是说,它不依赖数据库的事务机制,乐观锁完全是应用系统层面的东西。
悲观锁:悲观锁是指假设并发更新冲突会发生,所以不管冲突是否真的发生,都会使用锁机制
排它锁: 可以防止并发事务对资源进行访问。
共享锁: 允许并发事务在封闭式并发控制下读取资源。
更新锁:是共享锁和排他锁的结合。
行级锁:单独的一行记录加锁
表锁:锁住整个表,可以同时读,写不行
在Select语句中加for update是给相应的行增加排他锁。Select出来的数据别的事务不能读取,不能修改、不能删除。
44. 死锁怎么解决
找到进程号,kill 进程
产生死锁的原因:
一是系统提供的资源数量有限,不能满足每个进程的使用;二是多道程序运行时,进程推进顺序不合理。
产生死锁的必要条件是:
1、互斥条件;
2、不可剥夺条件(不可抢占);
3、部分分配;
4、循环等待。
根据产生死锁的四个必要条件,只要使其中之一不能成立,死锁就不会出现。为此,可以采取下列三种预防措施:
1、采用资源静态分配策略,破坏"部分分配"条件;
2、允许进程剥夺使用其他进程占有的资源,从而破坏"不可剥夺"条件;
3、采用资源有序分配法,破坏"环路"条件。
解除死锁常常采用下面两种方法:1、资源剥夺法;2、撤消进程法
45. 最左匹配原则
最左匹配原则是针对索引的
举例来说:两个字段(name,age)建立联合索引,如果where age=12这样的话,是没有利用到索引的,这里我们可以简单的理解为先是对name字段的值排序,然后对age的数据排序,如果直接查age的话,这时就没有利用到索引了,查询条件where name=’xxx’ and age=xx 这时的话,就利用到索引了。因为创建复合索引的规则是首先会对复合索引的最左边的,也就是第一个name字段的数据进行排序,在第一个字段的排序基础上,然后再对后面第二个的age字段进行排序。其实就相当于实现了类似 order by name age这样一种排序规则。所以:第一个name字段是绝对有序的,而第二字段就是无序的了。所以通常情况下,直接使用第二个age字段进行条件判断是用不到索引的,当然,可能会出现上面的使用index类型的索引。这就是所谓的为什么要强调最左匹配原则的原因。
46. SqlServer是一种大型数据库,他的存储容量只受存储介质的限制,请问它是通过什么方式实现这种无限容量机制的。
它的所有数据都存储在数据文件中(*.dbf),所以只要文件够大,SQLServer的存储容量是可以扩大的.
SQL Server 数据库有三种类型的文件:
主要数据文件
主要数据文件是数据库的起点,指向数据库中文件的其它部分。每个数据库都有一个主要数据文件。主要数据文件的推荐文件扩展名是 .mdf。
次要数据文件
次要数据文件包含除主要数据文件外的所有数据文件。有些数据库可能没有次要数据文件,而有些数据库则有多个次要数据文件。次要数据文件的推荐文件扩展名是 .ndf。
日志文件
日志文件包含恢复数据库所需的所有日志信息。每个数据库必须至少有一个日志文件,但可以不止一个。日志文件的推荐文件扩展名是 .ldf。
47. sqlserver数据库中常用的聚合函数有哪些?
Max(),Avg(),Count(),Min(),Sum()。
中文:最大值,平均值,数据条数,最小值,总和。
48. 数据库主键、外键、约束、索引的作用是什么?有几种连表查询方式?
主键、外键及约束的作用:保证数据的完整性
索引的作用:索引是一个数据结构,用来快速访问数据库表格或者视图里的数据,加快数据库的搜索引擎对数据的检索效率
方式:左连接、右连接、内连接、自连接
49. 除了sqlserver存储过程实现分页,还有什么实现方法?
利用select top 和select not in进行分页
利用select top 和 select max(列)
利用Row_number()给数据行加上索引
利用临时表及Row_number
7.1Java基础部分
1. Java 的 “一次编写,处处运行”如何实现?
JAVA之所以能实现 一次编译,到处运行,是因为JAVA在每个系统平台上都有 JAVA虚拟机(JVM),JAVA编译的中间文件class是由JAVA虚拟机在运行时动态转换为对应平台的机器代码.
2. 描述JVM运行原理。
Java平台由Java虚拟机和Java应用程序接口搭建,Java语言则是进入这个平台的通道,用Java语言编写并编译的程序可以运行在这个平台上。这个平台的结构如下图所示: 运行期环境代表着Java平台,开发人员编写Java代码(.java文件),然后将之编译成字节码(.class文件),再然后字节码被装入内存,一旦字节码进入虚拟机,它就会被解释器解释执行,或者是被即时代码发生器有选择的转换成机器码执行。
3. 为什么Java没有全局变量?
Global variables(全局变量) 是指可以全局访问的变量, Java不支持全局变量,原因如下:
1. 全局变量破坏了引用的透明性。
2. 全局变量制造了命名空间冲突。
可以使用properties类将想要全局有效的变量值写在properties文件中,那么在何处用时都从此properties文件中读取这个变量的值就可以了,此值在任何时候都可以修改的
说明:我们平时在类中声明的只是相对类而言是全局变量,不是真正意义的全局变量
4. 说明一下public static void main(String args[])这段声明里每个关键字的作用。
Public 是一个访问权限(访问修饰符)公共
static 修饰的成员称为类成员或者静态成员
void 当方法定义时用void修饰时,表示没有返回值
String 类来创建和操作字符串
5. Java 是否存在内存泄漏?
java中内存泄露的发生场景,通俗地说,就是程序员可能创建了一个对象,以后一直不再使用这个对象,这个对象却一直被引用,即这个对象无用但是却无法被垃圾回收器回收的,这就是java中的内存泄露,一定要让程序将各种分支情况都完整执行到程序结束,然后看某个对象是否被使用过,如果没有,则才能判定这个对象属于内存泄露。
6. ==与equals的区别。
"= ="除了比较基本数据之外都是比较的内存地址
"equals"除了没有没有重写equals方法的类之外都是比较的内容
7. Java中有几种类型的流?
Java中的流分为两种,一种是字节流,另一种是字符流,分别由四个抽象类来表示(每种流包括输入和输出两种所以一共四个):InputStream,OutputStream,Reader,Writer。
8. 如何用Java代码列出一个目录下所有的文件。
File file=new File("H:\\");
for(File temp:file.listFiles()){
if(temp.isFile()){
System.out.println(temp.toString());
}
9. &和&&的区别。
1、&与&&都可以用作逻辑与的运算符,当两边的结果都为true时,运算结果才为true,否则只要有一方运算结果是false,运算结果就为false。
2、&&在开发过程中用到的概率比&大,因为&&具有短路的功能,只要第一个表达式是false,就不会再进行判断。例如:if(str!=null && !str.equals("")){}
当str==null时,后面的表达式就不会继续执行,但是
if(str!=null & !str.equals("")){}当str==null时,程序会报空指针异常,因为&不具有短路的功能。
3、&同时也是位运算符,就是我们通常所说的按位与运算,当&的左右两边都是Boolean型表达式时或Boolean值时,就执行按位与运算。
10. 构造器(constructor)是否可被重写(override),其规范是什么?
构造器(构造方法)Constructor不能被继承,因此不能重写Override,但可以被重载Overload(不同参数即可)。
每一个类必须有自己的构造函数,在创建对象时自动调用,如果添加有参构造函数后,默认无参构造函数则被覆盖。子类不会覆盖父类的构造函数,但是在创建子类对象的时候,会自动调用父类构造函数。
11. JAVA 的反射机制的原理。
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。
12. 静态嵌套类(Static Nested Class)和内部类(Inner Class)的不同?
内部类是类中类(内部类不为同一包的其他类可见,具有很好的封装性),分为静态内部类,成员内部类,局部内部类以及匿名内部类;局部内部类写在方法里面;用到最多的就是匿名内部类。
1. 静态的内部类称为嵌套类,嵌套类不能直接引用外部类的non-static属性和方法,创建嵌套类对象时不依赖外部类对象;
2. 静态内部类没有了指向外部的引用,和C++的嵌套类很相像了,Java内部类和C++嵌套类最大的不同在于是否具有指向外部引用这点;
3. 在任何非静态内部类中,都不能有静态数据、静态方法或者又一个静态内部类(也就是不止一层),然后静态内部类可以拥有这一切。
13. 如何将String类型转化成Number类型。
Integer类的valueOf方法可以将String转成Number
14. 什么是值传递和引用传递?
对象被值传递,意味着传递了对象的一个副本。因此,就算是改变了对象副本,也不会影响源对象的值。
对象被引用传递,意味着传递的并不是实际的对象,而是对象的引用。因此,外部对引用对象所做的改变会反映到所有的对象上。
15. Java的访问修饰符是什么?
在Java编程语言中有四种权限访问控制符,这四种访问权限的控制符能够控制类中成员的 public是公共的,被public所修饰的成员可以在任何类中都能被访问到。
protected是受保护的,受到该类所在的包所保护。
friendly是友好的,即在成员的前面不写任何的访问修饰符的时候,默认就是友好的。所谓友好的,是对同一package的类友好。
private是私有的,即只能在当前类中被访问到,它的作用域最小。
16. Java 基础数据类型有哪些?
byte(字节) short(短整型) int(整型) long(长整型) float(浮点型) double(双精度) char(字符型) boolean(布尔型)
17. hashCode()和equals()方法的重要性体现在什么地方?
Java中的HashMap使用hashCode()和equals()方法来确定键值对的索引,当根据键获取值的时候也会用到这两个方法。如果没有正确的实现这两个方法,两个不同的键可能会有相同的hash值,因此,可能会被集合认为是相等的。而且,这两个方法也用来发现重复元素。所以这两个方法的实现对HashMap的精确性和正确性是至关重要的。
18. switch 中用于判断的表达式,可以用哪些数据类型?
1. int
2.char
3.byte
4.short
5.枚举
6. String: PS:对JDK版本有要求,必须为1.7及以上版本
19. char型变量中能不能存贮一个中文汉字?为什么?
Java里采用了Unicode编码格式,Unicode编码中一个char型占用2个字节,而一个汉字也是占用2个字节,所以可以存储中文汉字。
备注:C语言里,char占用1个字节,不用存汉字。
20. 静态变量和实例变量的区别?
在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。
在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。
21. 是否可以从一个static方法内部发出对非static方法的调用?
不可以。因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用时不需要创建对象,可以直接调用。也就是说,当一个static方法被调用时,可能还没有创建任何实例对象,如果从一个static方法中发出对非static方法的调用,那个非static方法是关联到哪个对象上的呢?这个逻辑无法成立,所以,一个static方法内部发出对非static方法的调用。
22. Integer与int的区别?
1、int是基本数据类型,Integer是包装类;
2、int的默认值是0,Interger的默认值是null;
23. Overload和Override的区别。参数列表相同,返回值不同的方法,是否是重载方法?
Overload是重载的意思,Override是覆盖的意思,也就是重写。
重载是指在一个类里,方法名相同,参数不同;
重写是指子类继承父类,子类里重新编写了父类中的同名(同参数)方法,也就是覆盖了父类的方法;
不是!因为重载必须要求参数列表不同!
24. 接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承具体类(concrete class)?
接口可以继承多个接口。抽象类可以实现(implements)接口,抽象类是可继承具体类。
备注:只要明白了接口和抽象类的本质和作用,这些问题都很好回答。
只有记住抽象类与普通类的唯一区别就是不能创建实例对象和允许有abstract方法。
25. 面向对象有哪三大特性?
1、面向对象有三大特性,分别是:封装、继承和多态。
2、封装:面向对象的封装就是把描述一个对象的属性和行为的代码封装在一个类中,有些属性是不希望公开的,或者说被其他对象访问的,所以我们使用private修饰该属性,使其隐藏起来;类中提供了方法(用public修饰),常用的是get、set方法,可以操作这些被隐藏的属性,其他类可以通过调用这些方法,改变隐藏属性的值!
封装是保证软件部件具有优良的模块性的基础,封装的目标就是要实现软件部件的“高内聚、低耦合”,防止程序相互依赖性而带来的变动影响。在面向对象的编程语言中,对象是封装的最基本单位,面向对象的封装比传统语言的封装更为清晰、更为有力。
3、继承:在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,使用extends关键字实现继承;子类中可以加入若干新的内容,或修改原来的方法使之更适合特殊的需要,这就是继承。继承是子类自动共享父类数据和方法的机制,这是类之间的一种关系,提高了软件的可重用性和可扩展性。
4、多态:多态就是在声明时使用父类,在实现或调用时使用具体的子类;即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性,多态增强了软件的灵活性和扩展性。这里可以举个例子,比如声明时使用的是动物类,调用时传递的是一个猫类(动物类的子类)的对象,具体执行父类里动物——吃的方法时,实际执行的是猫——吃的方法。
26. abstract class和interface有什么区别?
1、抽象类里面可以用普通方法,而接口中的方法全部都是抽象的;
2、在应用范围上来说,接口往往在程序设计的时候,用来定义程序模块的功能,方便各模块协同工作;抽象类是对相似类进行抽象,形成一个抽象的父类可供重用!
27. 如何理解Java中的Serialization和Deserialization。
串行化(serialization)是指将一个对象的当前状态转换成字节流(a stream of bytes)的过程,
而反串行化(deserialization)则指串行化过程的逆过程,将字节流转换成一个对象,打回原形。
28. String是最基本的数据类型吗?
1、String是个类,不是基本数据类型;
2、基本数据类型包括byte、int、char、long、float、double、boolean和short。
29. 如何实现字符串的反转及替换。
1.通过jdk自带reverse的方法
public class InvertString {
public static void main(String[] args) {
String a="abcde";
StringBuilder b = new StringBuilder(a);
System.out.print(b.reverse().toString());
}
注:String类本身没有反转类,需要包装成Stringbuiler或者是StringBuffer类。
2.通过自己写循环。
利用String.toCharArray()方法,将String转成一个char型数组,然后用数组遍历的方式从后向前遍历。
public String reverse(String s){
char ch[] = s.toCharArray();
int start = 0, end = ch.length-1;
char temp;
while(start temp = ch[start]; ch[start] = ch[end]; ch[end] = temp; start++; end--; } String s1 = String.copyValueOf(ch); return s1; } 、 或者是这样 public static String reverse2(String s) { int length = s.length(); String reverse = ""; for (int i = 0; i < length; i++) reverse = s.charAt(i) + reverse; return reverse; } 两个对象,要理解这个,就要知道string类的工作原理。 public class StringTest { public static void main(String[] args){ String s1="Hello"; String s2="Hello"; String s3=new String("Hello"); System.out.println("s1和s2 引用地址是否相同:"+(s1 == s2)); System.out.println("s1和s2 值是否相同:"+s1.equals(s2)); System.out.println("s1和s3 引用地址是否相同:"+(s1 == s3)); System.out.println("s1和s3 值是否相同:"+s1.equals(s3)); } } 输出结果: s1和s2 引用地址是否相同:true s1和s2 值是否相同:true s1和s3 引用地址是否相同:false s1和s3 值是否相同:true 1、String是个不可变长度的字符串,而StringBuffer是个可变长度的字符串; 2、在对String类进行操作的时候(例如增加字符),实际上是在内存中产生了一个新的String对象; 而StringBuffer是给原对象增加字符,不是新创建一个对象; 数组没有length()这个方法,有length的属性。String有length()这个方法。 final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。 finally是异常处理语句结构的一部分,表示总是执行。 finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。JVM不保证此方法总被调用 Error(错误)表示系统级的错误和程序不必处理的异常,是java运行环境中的内部错误或者硬件问题。比如:内存资源不足等。对于这种错误,程序基本无能为力,除了退出运行外别无选择,它是由Java虚拟机抛出的。 Exception(违例)表示需要捕捉或者需要程序进行处理的异常,它处理的是因为程序设计的瑕疵而引起的问题或者在外的输入等引起的一般性问题,是程序必须处理的。 Exception又分为运行时异常,受检查异常。 运行时异常,表示无法让程序恢复的异常,导致的原因通常是因为执行了错误的操作,建议终止程序,因此,编译器不检查这些异常。 受检查异常,是表示程序可以处理的异常,也即表示程序可以修复(由程序自己接受异常并且做出处理), 所以称之为受检查异常。 Exception体系包括RuntimeException体系和其他非RuntimeException的体系: ① RuntimeException:RuntimeException体系包括错误的类型转换、数组越界访问和试图访问空指针等等。处理RuntimeException的原则是:如果出现RuntimeException,那么一定是程序员的错误。例如,可以通过检查数组下标和数组边界来避免数组越界访问异常。 ②其他非RuntimeException(IOException等等):这类异常一般是外部错误,例如试图从文件尾后读取数据等,这并不是程序本身的错误,而是在应用环境中出现的外部错误。 throws是获取异常 throw是抛出异常 try是将会发生异常的语句括起来,从而进行异常的处理, catch是如果有异常就会执行他里面的语句, 而finally不论是否有异常都会进行执行的语句。 throws是用来声明一个方法可能抛出的所有异常信息,而throw则是指抛出的一个具体的异常类型。 空指针异常; NullPointerException 数组下标越界; ArrayIndexOutOfBoundsException 类型转换异常; ClassCastException 算数异常,例如除数为零;ArithMeticException IO异常,比如说找不到文件; FileNotFoundException 找不到类异常; ClassNotFoundException sql异常,例如sql语句不能正常运行; 1、是程序执行流的最小单元。在单个程序中同时运行多个线程完成不同的工作,称为多线程。 2、开始时:就绪状态,等待cpu调用后进入运行状态,运行过程中遇到阻塞事件,进入阻塞状态,等待阻塞事件结束后,重新进入就绪状态;如果没有阻塞事件,运行结束后,则进入结束状态。 sleep就是暂停当前线程一段时间,把cpu让给其他线程使用,到时后会自动恢复。调用sleep不会释放对象锁。 wait方法导致本线程放弃对象锁,进入等待,只有等到本对象的notify方法(或notifyAll)后本线程才进入就绪状态,等待执行。 多线程有两种实现方法,分别是继承Thread类与实现Runnable接口 启动一个线程是调用start()方法,使线程就绪状态,以后可以被调度为运行状态,一个线程必须关联一些具体的执行代码,run()方法是该线程所关联的执行代码。 1、新建状态(New):新创建了一个线程对象。 2、就绪状态(Runnable):也叫可运行状态。线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。 3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。 4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种: ①等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。 ②同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。 ③其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。 5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。 1、Set是无序的,元素不可重复;List是有序的,元素可以重复; 2、List存储的是单个对象的集合(有序的),Map存储的是键值对为对象的集合(无序的); 1.同步方法 即有synchronized关键字修饰的方法。 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。 2.同步代码块 即有synchronized关键字修饰的语句块。 被该关键字修饰的语句块会自动被加上内置锁,从而实现同步 java中所说的锁就是指的内置锁,每个java对象都可以作为一个实现同步的锁,虽然说在java中一切皆对象, 但是锁必须是引用类型的,基本数据类型则不可以 。每一个引用类型的对象都可以隐式的扮演一个用于同步的锁的角色,执行线程进入synchronized块之前会自动获得锁,无论是通过正常语句退出还是执行过程中抛出了异常,线程都会在放弃对synchronized块的控制时自动释放锁。 获得锁的唯一途径就是进入这个内部锁保护的同步块或方法 。 它们都是用于对类的对象进行比较和排序使用的接口。 Comparable是排序接口,位于java.lang包下,若一个类实现了Comparable接口,且重写了compareTo方法,就意味着该类支持排序,常结合Collections.sort或Arrays.sort对集合或数组内的元素进行排序。 Comparator是比较接口,位于java.util包下,我们如果需要控制某个类对象的次序,而该类本身不支持排序(即没有实现Comparable接口),那么我们就可以建立一个“该类的比较器”来进行排序,这个“比较器”只需要实现Comparator接口即可。 Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。 首先Java中的集合框架体系非常强大和完善,主要用于程序中的数据存储,从最顶层主要分为了Collection和Map接口,我们平时使用的集合类都是从这两个类别中扩展开来,正确选择要使用的集合的类型对性能非常重要。 比如: 1)元素的大小是固定的,而且能事先知道,我们就应该用Array而不是ArrayList。 2)如果我们大概知道存储的数量,可以在使用集合时先给予一个初始容量大小,从而有效避免集合自动增长的算法而造成的空间浪费,如new ArrayList(30)。 3)为了类型安全,提高存取效率和可读性,我们优先使用泛型,并且还能有效避免ClassCastException类型转换异常。 4)有时为了提高数据的快速定位查找,可优先使用Map键值对集合,因为Map集合在数据的查找上效率非常高,但是如果要保证数据的顺序,最好使用List 5)使用JDK提供的不变类作为Map的键可以避免为我们自己的类实现hashCode()和equals()方法。 6)底层的集合实际上是空的情况下,返回长度是0的集合或者是数组,不要返回null。 1、HashMap和HashTable都是键值对数据结构,且都实现了Map接口,存储的元素无序; 2、HashMap非线程安全的,而HashTable是线程安全的(HashTable里面的方法使用Synchronize关键字修饰),所以HashMap的效率高于HashTable。 3、HashMap允许空键空值,HashTable则不允许 相同点:1、单列存储 2、元素不可重复 不同点:1、底层数据结构不同(HashSet===哈希表结构 TreeSet===二叉树结构) 2、数据唯一性依据不同(HashSet通过重写hashcode和equals TreeSet通过compareable接口) 3、有序性不同,HashSet无序,TreeSet有序 1、ArrayList和LinkedList、Vector都实现了List接口; 2、ArrayList和Vector底层是用数组实现的,而LinkedList使用双向链表实现的,在集合插入、删除元素时,ArrayList需要移动数组元素性能较差;但是在查询时,因为是连续的数组,所以查询速度快;LinkedList正好相反。 3、在容量增长上,ArrayList增长原来50%,Vector集合增加容量原来的一倍。 4、安全性方面Vector能够保证线程安全,但是效率比ArrayList要低。 goto这个词是C语言中的,goto语句通常与条件语句配合使用,可用来实现条件转移,构成循环,跳出循环体等功能。而在结构化程序语言中一般不主张使用goto语句, 以免造成程序流程的混乱,使理解和调试程序都产生困难。但是在java语言中,goto这个词只是作为了保留字,不推荐使用,因为java语言讲究简单,方便。 1、泛型 2、For-Each循环 3、自动装包/拆包 4、枚举 5、静态导入 6、Annotation(框架配置,代码生成 的里程 7、可变参数 8、字符串格式化器(java.util.Formatter) 9、新的线程模型和并发库 Thread Frameword 1、引入了一个支持脚本引擎的新框架 2、UI的增强 3、对WebService支持的增强(JAX-WS2.0和JAXB2.0) 4、一系列新的安全相关的增强 5、JDBC4.0 6、Compiler API 7、通用的Annotations支持 1.switch中可以使用字串了 2.运用List 3.语法上支持集合,而不一定是数组 4.新增一些读取环境信息的工具方法 5.Boolean类型反转,空指针安全,参与位运算 6.两个char间的equals 7.安全的加减乘除 8.map集合支持并发请求,且可以写成 Map map = {name:"xxx",age:18}; 1.Lambda 表达式 ? Lambda允许把函数作为一个方法的参数,用更简洁的语法实现以前复杂的功能代码 2.方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。 3.接口中可以使用default关键字声明一个默认实现方法。 4.新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。 5.新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。 6.加强对日期与时间的处理。 7.Optional 类用来解决空指针异常。 8.Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。 代理模式是常用的java设计模式之一,java中的代理实现主要有基于接口的jdk动态代理和基于类的cglib动态代理,代理的特点就是会为目标对象产生代理对象,从而在调用实际目标对象方法时实现无侵入式的代码扩展,比如一些框架中的拦截器机制、springAOP面向切面机制都是基于动态代理模式实现的,其次也可以更安全的保护目标对象。动态代理的目的主要就是为了解决一些安全性问题(不让客户直接调用目标对象的功能,而是相当于通过中介),其次就是可以在调用目标功能方法之前、之后额外添加一些功能,比如日志、事务等,并且还能阻止调用功目标功能,从而实现权限控制等。 1、避免在开发程序的时候,创建出一个类的多个实例(占用空间,性能问题),所以使用单例模式,保证该类只创建一个对象; 2、一般单例模式通常有两种形式:它的构造函数为private的,必须有一个静态方法,静态方法返回自己的实例;实行形式有两种,懒汉式和饿汉式;所谓的饿汉式就是在声明实例的时候直接初始化对象,而懒汉式是先声明一个空对象,在静态方法中实例化该对象并返回。 //构造方法私有化,让外界无法创建对象 private Test() { //在当前类中声明静态对象,并提供公共静态方法让外界调用获取对象 private static Test t; public static Test getInstance(){ if(t==null){ t=new Test(); return t; 排序主要用于将一组无需数据进行升序/降序排列,Java中有很多种排序方法,如:冒泡排序,选择排序,插入排序,快速排序等,其中在大量数据无需数据中效率最高的属于快速排序,比如实际工作中如果需要对数据排序,我们可以借助JDK中自带的Arrays.sort方法,它内部采用了快速排序,效率非常高,当然也可以自己实现。 冒泡排序代码如下: import java.util.Arrays; public class BubbleSort { public static void BubbleSort(int[] arr) { int temp;//定义一个临时变量 for(int i=0;i for(int j=0;j if(arr[j+1] temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } } public static void main(String[] args) { int arr[] = new int[]{1,6,2,2,5}; BubbleSort.BubbleSort(arr); System.out.println(Arrays.toString(arr)); } Java语言中一个显著的特点就是引入了垃圾回收机制(简称GC),使c语言程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制,Java中的对象不再有“作用域”的概念,只有对象的引用才有“作用域”。垃圾回收可以有效的防止内存泄露,有效的使用空闲的内存。简单的理解,就是当对象失去引用后,系统会在调度的时间对它所占用的内存进行回收。 实现对象克隆有两种方式: 1). 实现Cloneable接口并重写Object类中的clone()方法;?? 2). 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。?? Java中有23种设计模式,我觉得理解设计模式对我们程序中的类和类的设计、依赖关系,扩展性,灵活性起着非常重要的作用,比如spring框架中都大量使用了设计模式,我比较熟悉的设计模式有: 1.单例设计模式 2.工厂设计模式(简单工厂、抽象工厂、工厂方法) 3.代理设计模式 4.观察者设计模式 5.适配器模式 6.原型模式 GC是垃圾回收的意思(gabage collection),内存处理器是编程人员容易出现问题的地方,忘记或者错误的内存回收导致程序或者系统的不稳定甚至崩溃,java的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,java语言没有提供释放已分配内存的显式操作方法。 Java中的String类提供了支持正则表达式操作的方法,包括:matches()、replaceAll()、replaceFirst()、split()。此外,Java中可以用Pattern类表示正则表达式对象,它提供了丰富的API进行各种正则表达式操作。 JavaScript 与 Java 是两个公司开发的不同的两个产品。Java 是 SUN 公司推出的新一代面向对象的程序设计语言,特别适合于 Internet 应用程序开发;而JavaScript 是 Netscape 公司的产品,其目的是为了扩展 Netscape Navigator功能,而开发的一种可以嵌入 Web 页面中的基于对象和事件驱动的解释性语言,它的前身是 Live Script;而 Java 的前身是 Oak 语言。 11.5+0.5后是12再向下取整是12;-11.5+0.5后是-11再向下取整-11 JDBC是java连接及操作数据库的一种技术,使用步骤如下: 1、加载JDBC驱动程序; Class.forName(“com.mysql.jdbc.Driver”) 2、创建数据库的连接对象; Connection conn = DriverManager.getConnection(“jdbc:mysql://localhost:3306/数据库名”,”root”,”123456”); 3、创建一个执行sql命令的Statement或PreparedStatement或者CallableStatement对象 4、执行SQL语句; 增删改操作executeUpdate()à返回int 查询操作executeQuery()à返回结果集ResultSet 5、返回并处理结果; 如果是查询需要对结果集逐行处理:while(rst.next()) 6、关闭连接; conn.close() 通过一个字符串加载一个类到java虚拟机中,返回与给定的字符串名称相关联类或接口的Class对象,该方法使用时会抛出ClassNotFoundException,即类无法找到异常。 事务是为了保证一个业务下的多条更新语句处于同一个不可分割的单元,要么都成功执行要么都取消回滚,目的是保证数据的准确合理性。 JDBC同样对事务进行了很好的支持,因为JDBC默认是开启事务的,所以需要通过数据库连接对象的setAutoCommit(false)来禁止自动提交,然后在执行完相关操作之后,调用连接对象的commit()方法提交事务,如果出现异常则调用rollback()方法进行回滚。 一般在实际应用中,建议使用存储过程来进行事务的控制,因为存储过程更安全,高效。 Blob是指二进制大对象(Binary Large Object),而Clob是指大字符对象(Character Large Objec),因此其中Blob是为存储大的二进制数据而设计的,而Clob是为存储大的文本数据而设计的。JDBC的PreparedStatement和ResultSet都提供了相应的方法来支持Blob和Clob操作。 1、PreparedStatement是Statement的子接口; 2、PreparedStatement支持SQL语句中使用占位符,能够避免SQL注入,安全性更好; 3、PreparedStatement对SQL语句有预编译的功能,所以性能更好; 通常我们定义一个基本数据类型的变量,还有就是函数调用的现场保存都使用内存中的栈空间;而通过new关键字和构造器创建的对象放在堆空间;程序中的字面量(literal)如直接书写的100、”hello”和常量都是放在静态区中。 栈空间操作起来最快但是栈很小,通常大量的对象都是放在堆空间,理论上整个内存没有被其他进程使用的空间甚至硬盘上的虚拟内存都可以被当成堆空间来使用。 String str = new String("hello"); 上面的语句中变量str放在栈上,用new创建出来的字符串对象放在堆上,而”hello”这个字面量放在静态区。 代码如下所示: String s1 = "你好"; String s2 = new String(s1.getBytes("GB2312"), "ISO-8859-1"); 异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误,只要程序设计得没有问题通常就不会发生。受检异常跟程序运行的上下文环境有关,即使程序设计无误,仍然可能因使用的问题而引发。Java编译器要求方法必须声明抛出可能发生的受检异常,但是并不要求必须声明抛出未被捕获的运行时异常。异常和继承一样,是面向对象程序设计中经常被滥用的东西,在Effective Java中对异常的使用给出了以下指导原则: - 不要将异常处理用于正常的控制流(设计良好的API不应该强迫它的调用者为了正常的控制流而使用异常) - 对可以恢复的情况使用受检异常,对编程错误使用运行时异常 - 避免不必要的使用受检异常(可以通过一些状态检测手段来避免异常的发生) - 优先使用标准的异常 - 每个方法抛出的异常都要有文档 - 保持异常的原子性 - 不要在catch中忽略掉捕获到的异常 ArithmeticException(算术异常) 5/0 ClassCastException (类转换异常) IllegalArgumentException (非法参数异常) IndexOutOfBoundsException (下标越界异常) NullPointerException (空指针异常) SecurityException (安全异常) NumberFormatException (数字格式异常 Integer.parseInt(“a1b2”)) FileNotFoundException (文件找不到异常) ClassNotFoundException (类找不到异常) List、Set 是,Map 不是。Map是键值对映射容器,与List和Set有明显的区别,而Set存储的零散的元素且不允许有重复元素(数学中的集合也是如此),List是线性结构的容器,适用于按数值索引访问元素的情形。 sleep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程暂停执行指定的时间,将执行机会(CPU)让给其他线程,但是对象的锁依然保持,因此休眠时间结束后会自动恢复。 wait()是Object类的方法,调用对象的wait()方法导致当前线程放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool),只有调用对象的notify()方法(或notifyAll()方法)时才能唤醒等待池中的线程进入等锁池(lock pool),如果线程重新获得对象的锁就可以进入就绪状态。 ① sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会; ② 线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态; ③ sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常; ④ sleep()方法比yield()方法(跟操作系统CPU调度相关)具有更好的可移植性。 - wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁; - sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要处理InterruptedException异常; - notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且与优先级无关; - notityAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而是让它们竞争,只有获得锁的线程才能进入就绪状态; 同步:指发送一个请求,需要等待返回,然后才能够发送下一个请求,有个等待过程,如果某个操作非常耗时,则会使后续的功能处于等待状态,产生假死/阻塞效果。 异步:指发送一个请求,不需要等待返回,随时可以再发送下一个请求,即不需要等待。 区别:一个需要等待,一个不需要等待,在部分情况下,我们的项目开发中都会优先选择不需要等待的异步交互方式。银行的转账系统,对数据库的保存操作等等,都会使用同步交互操作,其余情况都优先使用异步交互。 Java中的某个方法可以通过Synchronized关键字使其变为同步,从而解决线程中的异步资源安全问题。 Java中将一个类实现Serializable接口(实际是空接口,起标识作用),则该类的对象就可以被序列化。 序列化就是将类的对象进行流化,被流化后的对象可以在网络中传输或者以文件的形式进行保存,然后在需要的时候可以进行反序列化,将流化的对象还原为原始对象,并且数据都保持原来的状态。具体操作是使用writeObject()方法进行写,然后使用时再通过readObject()方法进行对象读取还原。 - 方法1:类型.class,例如:String.class - 方法2:对象.getClass(),例如:”hello”.getClass() - 方法3:Class.forName(),例如:Class.forName(“java.lang.String”) - 方法1:通过类对象调用newInstance()方法,例如:String.class.newInstance() - 方法2:通过类对象的getConstructor()或getDeclaredConstructor()方法获得构造器(Constructor)对象并调用其newInstance()方法创建对象,例如:String.class.getConstructor(String.class).newInstance(“Hello”); Enumeration速度是Iterator的2倍,同时占用更少的内存。但是,Iterator远远比Enumeration安全,因为其他线程不能够修改正在被iterator遍历的集合里面的对象。同时,Iterator允许调用者删除底层集合里面的元素,这对Enumeration来说是不可能的。 吞吐量收集器使用并行版本的新生代垃圾收集器,它用于中等规模和大规模数据的应用程序。 而串行收集器对大多数的小应用(在现代处理器上需要大概100M左右的内存)就足够了。 7.2Java web部分 B/S是Brower/Server(浏览器/服务器模式)的缩写,客户机上只要安装一个浏览器,实现与服务器交互; C/S是Client/Server(客户端/服务器模式)的缩写,客户机需安装专用客户端,实现与服务器交互,如数据库产品; B/S代表,淘宝网、京东网站。 C/S代表,腾讯QQ .主要区别如下: 1、 B/S使用浏览器访问,安装维护的成本代价很小。 2、 C/S需要安装客户端软件,安装维护成本较大。 1、在web.xml里为每一个Servlet配置初始化参数; 2、通过ServletConfig对象实现对Servlet初始化对象的获取; 1、Ajax是采用了异步请求的方式,解决了页面无刷新式提交的问题,改善了页面的用户体验效果;常用自动完成提示,注册时用户名重复性校验。 2、常用的Ajax框架: Jquery中的ajax 答题技巧:解释概念,说明用途,举例 Get和Post都是提交表单的方式之一; 1、[安全性]get方式提交后,数据会在地址栏中显示出来,而post方式不会,所以post更安全; 2、[数据长度]get方式在提交数据的时候,数据长度是有限制的;而post方式在理论上对提交数据的大小是无限制的; 3、[效率]get方式效率更高 1、Servlet生命周期包括加载和实例化、初始化、处理请求以及销毁。 2、Servlet被服务器调用构造方法实例化,第一次访问Servlet时,容器运行其init方法进行初始化,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等,当服务器决定将实例销毁的时候调用其destroy方法。 1、forward是请求转发,而redirect是重定向; 2、请求转发是服务器将客户端的请求转发到另一个地址去处理,然后将响应返回给客户端;实际上是1次请求,1次响应,对客户端而言是透明的;而重定向是服务器根据客户端发来的请求,返回给客户端一个新的地址,客户端根据这个返回的地址再发送请求,得到响应;实际上是2次请求,2次响应,而且客户端的地址是第二次访问的地址; 3、转发只能转发到服务器自己的资源,重定向无限制。 4、转发的效率高于重定向 5、转发地址栏不会改变,重定向地址栏会变成第二次访问的地址。 转发核心代码:request.getRequestDispatcher(“资源地址”).forward(request,response); 重定向核心代码:response.sendRedirect(“资源地址”); JSP是Java Server Page的简称,是由Sun公司倡导简历的一种动态网页技术标准,用于开发动态网页。JSP页面由HTML代码和嵌入其中的Java代码组成,服务器在页面被客户端请求后执行Java代码,将生成的HTML页面返回给客户端。 1、JSP技术的优点 (1)一次编写,到处运行。 (2)跨平台。 (3)强大的可伸缩性。 2、JSP技术的弱势 (1)正是由于为了跨平台的功能,所以极大的增加了产品的复杂性。 (2)占用内存较大。 (3)代码调试不便。 JSP共有以下9个内置的对象: page、config、application、request、response、session、out、exception、pageContext request:封装客户端的请求,其中包含来自GET或POST请求的参数; response:封装服务器对客户端的响应; session:封装用户会话的对象; application:封装服务器运行环境的对象; page:JSP页面本身(相当于Java程序中的this); pageContext:通过该对象可以获取其他对象; out:输出服务器响应的输出流对象; config:Web应用的配置对象; exception:封装页面抛出异常的对象。 JSP的四大作用域:page、request、session、application page:变量只能在当前页面上生效 request:变量能在一次请求中生效,一次请求可能包含一个页面,也可能包含多个页面,比如页面A请求转发到页面B session:代表变量能在一次会话中生效,基本上就是能在web项目下都有效。一般来说,只要浏览器不关闭,session的使用就不会受到影响。 application:代表整个应用程序范围。 存入数据:作用域对象.setAttribute(“名字”,数据); 取出数据:作用域对象.getAttribute(“名字”); 1、Session和Cookie都是会话跟踪技术; 2、Session是保存在服务器端的技术(保持用户登录状态的检查常用Session),而Cookie是保存在客户端的技术; 3、Cookie只能存字符串,Session可以存对象; 1.Tomcat 目前非常流行的Tomcat服务器是Apache-Jarkarta开源项目中的一个子项目,是一个小型、轻量级的支持JSP和Servlet 技术的Web服务器,也是初学者学习开发JSP应用的首选。 2.JBoss JBoss是一个种遵从JavaEE规范的、开放源代码的、纯Java的EJB服务器,对于J2EE有很好的支持。JBoss采用JML API实现软件模块的集成与管理,其核心服务又是提供EJB服务器,不包含Servlet和JSP的Web容器,不过它可以和Tomcat完美结合 3.WebLogic WebLogic 是BEA公司的产品(现在已经被Oracle收购)。WebLogic 支持企业级的、多层次的和完全分布式的Web应用,并且服务器的配置简单、界面友好。 在Java Web程序中,Servlet主要负责接收用户请求 HttpServletRequest,在doGet(),doPost()中做相应的处理,并将回应HttpServletResponse反馈给用户。Servlet 可以设置初始化参数,供Servlet内部使用。一个Servlet类只会有一个实例,在它初始化时调用init()方法,销毁时调用destroy()方法。Servlet需要在web.xml中配置,一个Servlet可以设置多个URL访问。 1.jsp经编译后就变成了Servlet. (JSP的本质就是Servlet,Web容器将JSP的代码编译成java类) 2.jsp更擅长表现于页面显示,Servlet更擅长于逻辑控制. 3.Servlet中没有内置对象,Jsp中的内置对象都是必须通过HttpServletRequest对象,HttpServletResponse对象以及HttpServlet对象得到。 web.xml文件是用来配置:欢迎页、servlet、filter、listener、初始化信息、错误页面等的。当你的web工程没用到这些时,你可以不用web.xml文件来配置你的web工程。 答题技巧:可根据个人实际情况,增加各类框架在web.xml内的配置代码,如struts2 过滤器配置,spring 监听器配置,springmvc Servlet配置等. EL的隐式对象包括: pageContext、 initParam(访问上下文参数)、 param(访问请求参数)、 paramValues、 header(访问请求头)、 headerValues、 cookie(访问cookie)、 applicationScope(访问application作用域)、 sessionScope(访问session作用域)、 requestScope(访问request作用域)、 pageScope(访问page作用域)。 使用标签库的好处包括以下几个方面: - 分离JSP页面的内容和逻辑,简化了Web开发; - 开发者可以创建自定义标签来封装业务逻辑和显示逻辑; - 标签具有很好的可移植性、可维护性和可重用性; - 避免了对Scriptlet(小脚本)的使用(很多公司的项目开发都不允许在JSP中书写小脚本) <% Java代码 %> EL表达式的操作符主要有: 算术运算符、关系运算符、逻辑运算符、验证运算符empty、条件运算符 算术运算符主要有平时常用的“+”、“-”、“*”、“/”、“%” 。 关系运算符主要有“==”、“!=”、“<”、“>”、“<=”、“>=” 逻辑运算符主要有“&&”、“||”、“!” 。 验证运算符“empty” 条件运算符“?:” 答题技巧: 先说明支持分类,然后对每一类运行符说明具体运算符, 表达式控制标签:out、set、remove、catch 流程控制标签:if、choose、when、otherwise 循环标签:forEach、forTokens URL操作标签:import、url、redirect 答题技巧:不要求写出全部标签,写自己真实用过,理解最深的标签,适当附上示例代码 1、静态包含属于编译期包含(包含页面和被包含的页面在编译期形成一个jsp文件),动态包含属于运行期包含(包含页面和被包含的页面分别编译成两个文件,然后运行时把两个文件组装起来); 2、动态包含可以带参数; 通过请求对象(ServletRequest)的setCharacterEncoding(String)方法可以设置请求的编码,其实要彻底解决乱码问题就应该让页面、服务器、请求和响应、Java程序都使用统一的编码,最好的选择当然是UTF-8;通过响应对象(ServletResponse)的setContentType(“text/html;charset=utf-8”)方法可以设置响应内容的类型,当然也可以通过HttpServletResponse对象的setHeader(String, String)方法来设置。 7.3数据持久化部分 ORM是对象-关系映射(Object-Relational Mapping,简称ORM) 它是java中持久层框架技术的一种实现思想,基于这种思想常见的框架有MyBatis、Hibernate等。其原理是建立java中类(实体类)和数据表之间的映射关系,然后通过反射的思想,动态获取类中的属性,此时属性对应了表中的列,所以能够动态产生JDBC代码从而达到操作数据库的目的。 dao全称是data access object,数据库访问对象,主要的功能就是用于进行数据操作的,在程序的标准开发架构中属于数据层的操作 DAO组成 在整个DAO中实际上都是以接口为操作标准的,即:客户端依靠DAO实现的接口进行操作,而服务端要将接口进行具体的实现。DAO由以下几个部分组成。 1.DatabaseConnection:专门负责数据库的打开与关闭操作的类 2.VO:主要由属性、setter、getter方法组成,VO类中的属性与表中的字段相对应,每一个VO类的对象都表示表中的每一条记录; 3.DAO:主要定义操作的接口,定义一系列数据库的原子性操作,例如:增加、修改、删除、按ID查询等; 4.Impl : DAO接口的真实实现类,完成具体的数据库操作,但是不负责数据库的打开和关闭; 5 Proxy :代理实现类,主要完成数据库的打开和关闭,并且调用真实实现类对象的操作 6 Factory :工厂类,通过工厂类取得一个DAO的实例化对象 例如:商品和订单、学生和课程都是典型的多对多关系。首先在数据库表中需要通过第三张关系表来进行数据的维护,该关系表中主要包含了两个外键。具体代码中实现根据框架的不同也有不同的实现方式,比如JPA中可以在实体类上通过@ManyToMany注解配置多对多关联或者通过映射文件中的和标签配置多对多关联,但是实际项目开发中,很多时候都是将多对多关联映射转换成两个多对一关联映射来实现的。 继承关系的映射策略有三种: ① 每个继承结构一张表(table per class hierarchy),不管多少个子类都用一张表。 ② 每个子类一张表(table per subclass),公共信息放一张表,特有信息放单独的表。 ③ 每个具体类一张表(table per concrete class),有多少个子类就有多少张表。 第一种方式属于单表策略,其优点在于查询子类对象的时候无需表连接,查询速度快,适合多态查询;缺点是可能导致表很大。后两种方式属于多表策略,其优点在于数据存储紧凑,其缺点是需要进行连接查询,不适合多态查询。 1、Hibernate是一个基于ORM思想的操作数据库的框架技术,实现了对JDBC的封装; 2、Hibernate用的是面向对象的方法,但是在关系型数据库里,存的是一条条的记录;为了用纯面向对象的思想解决问题,所以需要将程序中的对象和数据库中的记录建立起映射关系,ORM就是将对象和数据库中的记录建立起映射的技术; 3、Hibernate通过方言来自动切换不同的数据库,无需在代码中编写; 4、使用Hibernate的基本流程是:配置Configuration对象、产生SessionFactory、创建session对象,启动事务,完成CRUD操作,提交事务,关闭session; 5、使用Hibernate时,先要配置hibernate.cfg.xml文件,其中配置数据库连接信息和方言等,还要为每个实体配置相应的hbm.xml文件,hibernate.cfg.xml文件中需要登记每个hbm.xml文件。 Hibernate是一个采用ORM(Object/Relation Mapping对象关系映射)机制持久层的开源框架 其主要核心思想是面向对象,而非面向过程,而这个面向对象则主要通过ORM实现。 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。 1.#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。 2.$将传入的数据直接显示生成在sql中。 3.#方式能够很大程度防止sql注入。 4.$方式无法防止Sql注入。 5.$方式一般用于传入数据库对象 6.一般能用#的就别用$ 注意: 一般如果将表名、列名作为参数的动态功能操作时,必须使用$,而不能使用#。如MyBatis排序时使用order by 动态参数时需要使用$。 相同点:都是基于ORM思想的java持久层框架技术,都封装了JDBC实现数据库操作,提高了开发数据库编码的效率。 不同点: 1) Hibernate是一个全自动的orm映射工具,它可以自动生成sql语句;MyBatis需要我们自己在xml配置文件中写sql语句。因为hibernate自动生成sql语句,我们无法控制该语句,我们就无法去写特定的高效率的sql。对于一些不太复杂的sql查询,hibernate可以很好帮我们完成,但是,对于特别复杂的查询,hibernate就很难适应了,这时候用MyBatis就是不错的选择,因为MyBatis还是由我们自己写sql语句; 2) Mybatis比hibernate对存储过程的支持更好一些。 所谓"持久"就是将数据保存到存储设备中以便今后使用,简单的说,就是将内存中的数据保存到关系型数据库、文件系统、消息队列等提供持久化支持的设备中。持久层就是系统中专注于实现数据持久化的相对独立的层面。 持久层设计的目标包括: - 数据存储逻辑的分离,提供抽象化的数据访问接口。 - 数据访问底层实现的分离,可以在不修改代码的情况下切换底层实现。 - 资源管理和调度的分离,在数据访问层实现统一的资源调度(如缓存机制)。 - 数据抽象,提供更面向对象的数据操作。 持久层主要是负责将数据进行持久化,早期的JDBC代码太麻烦繁琐,所以出现了一系列基于ORM思想的持久层框架,我主要使用的是MyBatis框架,其他的比如Hibernate以及JPA有一些了解。 技巧:选自己最熟的持久化框架,说明其关键特点 技巧:mappedBy 属性的主要作用是告诉hibernate关联关系是通过对方外键引用完成关联映射,这一点必须说清楚。 One的一方会成为主控方,加入mappedBy以后,就不会生成这两张关联表的中间表了,而是在Many的一方的表中生成一列作为外键。 MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑,一般在我们的Mapper.xml映射文件中使用,MyBatis中用于实现动态SQL的标签元素主要有: if choose(when,otherwise) trim where set foreach N+1问题主要是数据库表中的级联问题,就是在查询的时候使用了association或collection标签进行关联数据时,如果使用了嵌套的select方式,则会造成N+1的问题,解决方案是: 第一种方法是使用一条多表关联的SQL语句,一次性查询出需要的数据。 第二种方法是使用MyBatis的延迟加载机制,在具体使用到的时候再去加载数据。 1.MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑。 2.MyBatis中用于实现动态SQL的元素主要有 if choose(when,otherwise) trim where set foreach 可以看出MyBatis的动态SQL的标签元素和接近JSP中的JSTL语法,下面我就分别详细的介绍一下 3.动态SQL中if的用法 4.动态SQL中choose用法 5.动态SQL中where语句的作用主要是简化SQL语句中where中的条件判断的 注意: where元素的作用是给SQL语句添加一个条件判断. 如果输出后是and 开头的,MyBatis会把第一个and忽略,当然如果是or开头的,MyBatis也会把它忽略;此外,在where元素中你不需要考虑空格的问题,MyBatis会智能的帮你加上 6.动态SQL中set元素主要是用在更新操作的时候,它的主要功能和where元素其实是差不多的 7.动态SQL中foreach 主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。 foreach元素的属性主要有item,index,collection,open,separator,close 8.动态SQL中trim语句 JDBC是java进行数据库操作时的技术统称,提供了很多操作接口,但是编写的代码非常繁琐麻烦,创建一个以JDBC连接数据库的程序,包含7个步骤: 1、加载JDBC驱动程序: Class.forName(“com.mysql.jdbc.Driver”) 2、提供JDBC连接的URL: “jdbc:mysql://localhost:3306/数据库名” 3、创建数据库的连接 Connection conn = DriverManager.getConnection(“URL”,”root”,”123456”) 4、创建一个执行sql命令的Statement对象 PreparedStatement pstmt = conn.prepareStatement(sql); 5、执行SQL语句 1)增删改 pstmt.executeUpdate() à返回int为影响的行数 2)查询 pstmt.executeQuery()à返回ResultSet为查询的结果集 6、循环读取结果: while(rst.next()) 7、关闭JDBC相关资源对象 1)数据库连接池技术主要是提高应用程序和数据库交互时的性能问题,因为连接数据库是非常耗费资源的,如果每个操作都去频繁连接和断开,则会造成巨大的开销,连接池技术即在系统初始化时,就创建一系列的连接对象放入集合中管理,需要连接数据库时从连接池中取出使用,使用完毕归还给连接池,这样的目的是提高同一个连接的可重用性。 2)java中有很多连接池框架,比如dbcp、c3p0,我个人比较喜欢使用阿里的druid连接池,因为性能稳定,功能强大。 注:一般项目使用时直接添加maven引用 1、MySQL:3306 2、Oracle:1521 3、SQL Server:1433 分页的目的是减少一次性查询出数据的额外开销,提高应用的性能。 Mybatis中可以使用如下几种方案: 1、 sql语句分页,利用传递的页码和每页显示数,使用limit分页 2、 采用mybatis拦截器插件实现分页 Mybatis要求我们自己完成查询sql语句,然后对查询的类进行映射,默认情况下如果类和实体属性一致,则可以直接使用reusltType进行关联映射,如果不一致,则需要自定义resultMap进行映射说明。当然如果数据库列是下划线,而java中是驼峰命名,则可以在mybatis主配置中添加驼峰命名的全局setting配置即可。 1) 缓存是为了提高程序的性能,把从数据库中查询出来和使用过的对象保存在内存中,当以后要使用某个对象时,先查询缓存中是否有这个对象,如果有则使用缓存中的对象,如果没有则去查询数据库,并将查询出来的对象保存在缓存中,以便下次使用。 2) Mybatis中有一级缓存和二级缓存,其中一级缓存是SqlSession级别的缓存,在同一个SqlSession操作时都会默认使用,当会话关闭则会自动清空无法使用。二级缓存是Mapper级别的缓存,需要在主配置中声明开启,然后在Mapper.xml中使用<cache>标签声明后才能使用。 3) 缓存使用时需要注意,经常修改和准确度要求很高的数据不适合放入缓存中,因为很容易产生脏数据,从而造成程序中的数据不准确。 1) 首先项目中加入mybatis的依赖,如maven的pom.xml中添加 2) 创建并修改mybatis-config.xml核心配置文件(配置全局属性、别名、数据库连接、注册的Mapepr等) 3) 创建实体类和数据表映射 4) 创建功能操作接口,完成抽象方法 5) 针对抽象方法完成对应的Mapper.xml中的映射或者使用注解实现 6) 运行时加载配置,产生SqlSessionFactory对象,然后调用openSession方法获取SqlSession,然后拿到Mappper接口代理对象,调用方法完成操作。 7) 关闭会话 1) 一般使用< association>标签进行一对一的对象关联映射 2) 使用< collection>标签进行一对多的集合关联映射 具体映射时候可以采用一次性查询出结果(推荐)然后映射,也可以采用嵌套的select查询方式。 插件也可以理解为拦截器,即在mybatis执行某个sql语句或者结果处理前后,均可以自己编写代码进行额外的操作,Mybatis 仅可以编写针对 ParameterHandler、ResultSetHandler、StatementHandler、Executor 这 4 种接口的插件。Mybatis 使用 JDK 的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这 4 种接口对象的方法时,就会进入拦截方法,具体就是 InvocationHandler 的 invoke() 方法,只会拦截那些你指定需要拦截的方法,具体使用时还需要在拦截器类上进行签名以及在主配置文件中声明才能使用。 1) MyBatis的优点:屏蔽jdbc api的底层访问细节;自己定制sql能自定义映射,和将sql语句与java代码进行分离;提供了将结果集自动封装称为实体对象和对象的集合的功能,queryForList返回对象集合,用queryForObject返回单个对象;提供了自动将实体对象的属性传递给sql语句的参数。其次mybatis很好的跟spring集成。 2) Mybatis的缺点:SQL 语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL 语句的功底有一定要求,SQL 语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。 mybatis中提供了<foreach>标签,可以对集合、数组进行循环,从而实现动态的批量操作。 Mybatis中可以在<insert>标签中添加usegeneratedkeys=”true” keyproperty=” id”属性获取自增后的主键值,比如增加操作时传入的实体对象没有id,调用带有该属性的增加操作后,则会将自增主键放入实体对象中。 也可以在<insert>标签中使用<selectKey>标签查询获取自增主键列数据。 Mybatis如果参数是一个,或者实体对象,则直接可以使用#{名称或属性}取出对应的数据,那么如果不是实体对象,但是有多个参数,实现如下: 1) 使用Map集合封装传递的多个参数,因为map有键作为名称。 2) 使用@Param注解实现参数名的标注。 7.4流行框架与技术 Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。当你使用Maven的时候,你用一个明确定义的项目对象模型来描述你的项目,然后Maven可以应用横切的逻辑,这些逻辑来自一组共享的(或者自定义的)插件。 Maven 有一个生命周期,当你运行 mvn install 的时候被调用。这条命令告诉 Maven 执行一系列的有序的步骤,直到到达你指定的生命周期。遍历生命周期旅途中的一个影响就是,Maven 运行了许多默认的插件目标,这些目标完成了像编译和创建一个 JAR 文件这样的工作。 此外,Maven能够很方便的帮你管理项目报告,生成站点,管理JAR文件,等等。 SVN是Subversion的简称,是一个开放源代码的版本控制系统,相较于RCS、CVS,它采用了分支管理系统,它的设计目标就是取代CVS。互联网上很多版本控制服务已从CVS迁移到Subversion。说得简单一点SVN就是用于多个人共同开发同一个项目,共用资源的目的。 Git(读音为/g?t/。)是一个开源的分布式版本控制系统,可以有效、高速的处理从很小到非常大的项目版本管理。[1] Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。 Java世界中主要有三大构建工具:Ant、Maven和Gradle 目前:Ant已经销声匿迹、Maven也没落了,而Gradle的发展则如日中天。 Maven的主要功能主要有,分别是依赖管理系统、多模块构建、一致的项目结构、一致的构建模型和插件机制。 第一Maven为Java世界引入了一个新的依赖管理系统。在Java世界中,可以用groupId、artifactId、version组成的Coordination(坐标)唯一标识一个依赖。任何基于Maven构建的项目自身也必须定义这三项属性,生成的包可以是Jar包,也可以是war包或者ear包。一个典型的依赖引用如下所示: Gradle在设计的时候基本沿用了Maven的这套依赖管理体系。不过它在引用依赖时还是进行了一些改进。首先引用依赖方面变得非常简洁。 第二,Maven和Gradle对依赖项的scope有所不同。在Maven世界中,一个依赖项有6种scope,分别是complie(默认)、provided、runtime、test、system、import。而grade将其简化为了4种,compile、runtime、testCompile、testRuntime。那么如果想在gradle使用类似于provided的scope怎么办?别着急,由于gradle语言的强大表现力,我们可以轻松编写代码来实现类似于provided scope的概念(例如How to use provided scope for jar file in Gradle build?)。 第三点是Gradle支持动态的版本依赖。在版本号后面使用+号的方式可以实现动态的版本管理。 第四点是在解决依赖冲突方面Gradle的实现机制更加明确。 其实Git和SVN还是挺像的,都有提交,合并等操作,看来这是源码管理工具的基本操作。 1. Git是分布式的,SVN是集中式的,好处是跟其他同事不会有太多的冲突,自己写的代码放在自己电脑上,一段时间后再提交、合并,也可以不用联网在本地提交; 2. Git下载下来后,在本地不必联网就可以看到所有的log,很方便学习,SVN却需要联网; 3. Git鼓励分Branch,而SVN,说实话,我用Branch的次数还挺少的,SVN自带的Branch merge我还真没用过,有merge时用的是Beyond Compare工具合并后再Commit的; 4. Tortoise也有出Git版本,真是好东西; 5. SVN在Commit前,我们都建议是先Update一下,跟本地的代码编译没问题,并确保开发的功能正常后再提交,这样其实挺麻烦的,有好几次同事没有先Updata,就 Commit了,发生了一些错误,耽误了大家时间,Git可能这种情况会少些。 1、M:Model 模型层 主要用来处理业务逻辑,承载数据; 2、V:View 视图层 主要用来做页面显示的 3、C:Control 控制层 主要用来进行业务流程控制; 4、常用的MVC框架包括:Struts、Struts2、SpringMVC;谈谈Struts2的工作流程(或运行原理)。 1、客户端发送一个指向Servlet容器(例如Tomcat)的请求 2、这个请求经过一系列的过滤器(Filter) 3、接着核心控制器FilterDispatcher被调用(2.3以后是StrutsPrepareAndExecuteFilter过滤器),将request中所携带的数据放入值栈(ValueStack); 4、 核心控制器询问ActionMapper来决定这个请求是否需要调用某个Action,把请求的处理交给ActionProxy; 5、 ActionProxy通过Configuration Manager询问框架的配置文件(struts.xml),找到调用的Action类; 6、 ActionProxy创建一个ActionInvocation的实例; 7、 ActionInvocation在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用; 8、 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果(JSP显示结果)。 优点: 1、实现MVC模式,结构清晰,使开发者只关注业务逻辑的实现; 2、有丰富的tag可以用 ,Struts的标记库(Taglib),如能灵活动用,则能大大提高开发效率; 3、通过配置文件,使系统的脉络更加清晰。一个配置文件,即可把握整个系统各部分之间的联系,这对于后期的维护有着很大的好处。 4、Struts提供了两种异常处理方式,声明式异常处理和编程式异常处理 5、对国际化进行支持,支持I18N; 缺点: 1、实现MVC模式,代码复杂度提升; 2、需要维护配置文件,比较麻烦; 1. 拦截机制的不同 Struts2是类级别的拦截,每次请求就会创建一个Action,和Spring整合时Struts2的ActionBean注入作用域是原型模式prototype,然后通过setter,getter吧request数据注入到属性。Struts2中,一个Action对应一个request,response上下文,在接收参数时,可以通过属性接收,这说明属性参数是让多个方法共享的。Struts2中Action的一个方法可以对应一个url,而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了,只能设计为多例。 SpringMVC是方法级别的拦截,一个方法对应一个Request上下文,所以方法直接基本上是独立的,独享request,response数据。而每个方法同时又何一个url对应,参数的传递是直接注入到方法中的,是方法所独有的。处理结果通过ModeMap返回给框架。在Spring整合时,SpringMVC的Controller Bean默认单例模式Singleton,所以默认对所有的请求,只会创建一个Controller,有应为没有共享的属性,所以是线程安全的,如果要改变默认的作用域,需要添加@Scope注解修改。 Struts2有自己的拦截Interceptor机制,SpringMVC这是用的是独立的Aop方式,这样导致Struts2的配置文件量还是比SpringMVC大。 2、底层框架的不同 Struts2采用Filter(StrutsPrepareAndExecuteFilter)实现,SpringMVC(DispatcherServlet)则采用Servlet实现。Filter在容器启动之后即初始化;服务停止以后坠毁,晚于Servlet。Servlet在是在调用时初始化,先于Filter调用,服务停止后销毁。 3、性能方面 Struts2是类级别的拦截,每次请求对应实例一个新的Action,需要加载所有的属性值注入,SpringMVC实现了零配置,由于SpringMVC基于方法的拦截,有加载一次单例模式bean注入。所以,SpringMVC开发效率和性能高于Struts2。 4、配置方面 spring MVC和Spring是无缝的。从这个项目的管理和安全上也比Struts2高。 1.AOP为Aspect Oriented Programming的缩写,意为:面向切面编程(也叫面向方面),可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种思想。 2.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。 当项目中需要编写大量相同功能重复代码时,可以考虑使用AOP的形式来实现。如声明式事务管理、权限校验等。 备注:如果面试官问你是否用过AOP,一定要说用过(Spring的事务处理机制就是AOP的思想来实现的)——非常重要!!! 1.IOC是控制反转,DI是依赖注入,其基本含义差不多。 2.IOC:原来创建对象的控制权是由我们自己来创建的,现在不再是由程序员创建了,由IOC容器为我们提供,这样带来的好处是,降低代码的耦合度,更加符合开闭原则; 备注:学生需要知道怎么在配置文件里配置相关信息,面试官可能会问。 1.Set注入 2.构造器注入 在WebApp中获得XMLWebApplicationContext的步骤 1.在Web.xml中配置上下文载入器. 2.指定上下文载入器的配置文件. 3.获得应用上下文. springAOP主要通过Java 动态代理的方式进行实现。 GCLIB代理 cglib(Code Generation Library)是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。 cglib封装了asm,可以在运行期动态生成新的class。 cglib用于AOP,jdk中的proxy必须基于接口,cglib却没有这个限制。 原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。 1.如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP 2.如果目标对象实现了接口,可以强制使用CGLIB实现AOP 3.如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换 1. IoC容器:IoC容器帮助应用程序管理对象以及对象之间的依赖关系,对象之间的依赖关系如果发生了改变只需要修改配置文件而不是修改代码,因为代码的修改可能意味着项目的重新构建和完整的回归测试。有了IoC容器,程序员再也不需要自己编写工厂、单例,这一点特别符合Spring的精神“不要重复的发明轮子”。 2. AOP:面向切面编程,将所有的横切关注功能封装到切面(aspect)中,通过配置的方式将横切关注功能动态添加到目标代码上,进一步实现了业务逻辑和系统服务之间的分离。另一方面,有了AOP程序员可以省去很多自己写代理类的工作。 3. MVC:Spring的MVC框架是非常优秀的,从各个方面都可以甩Struts 2几条街,为Web表示层提供了更好的解决方案。 4. 事务管理:Spring以宽广的胸怀接纳多种持久层技术,并且为其提供了声明式的事务管理,在不需要任何一行代码的情况下就能够完成事务管理。 1.用户请求首先发送到前端控制器DispatcherServlet,DispatcherServlet根据请求的信息来决定使用哪个页面控制器Controller(也就是我们通常编写的Controller)来处理该请求。找到控制器之后,DispatcherServlet将请求委托给控制器去处理。 2.接下来页面控制器开始处理用户请求,页面控制器会根据请求信息进行处理,调用业务层等等,处理完成之后,会把结果封装成一个ModelAndView返回给DispatcherServlet。 3.前端控制器DispatcherServlet接到页面控制器的返回结果后,根据返回的视图名选择相应的试图模板,并根据返回的数据进行渲染。 4.最后前端控制器DispatcherServlet将结果(如jsp)返回给用户。 1. 事务简介: 事务管理是企业级应用程序开发中必不可少的技术,用来确保数据的完整性和一致性 事务就是一系列的动作,它们被当作一个单独的工作单元。这些动作要么全部完成,要么全部不起作用 2. 事务的四个关键属性(ACID) ① 原子性(atomicity):事务是一个原子操作,有一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用 ② 一致性(consistency):一旦所有事务动作完成,事务就被提交。数据和资源就处于一种满足业务规则的一致性状态中 ③ 隔离性(isolation):可能有许多事务会同时处理相同的数据,因此每个事物都应该与其他事务隔离开来,防止数据损坏 ④ 持久性(durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响。通常情况下,事务的结果被写到持久化存储器中 作为企业级应用程序框架,Spring在不同的事务管理API之上定义了一个抽象层。而应用程序开发人员不必了解底层的事务管理API,就可以使用Spring的事务管理机制。 Spring既支持编程式事务管理(也称编码式事务),也支持声明式的事务管理 编程式事务管理:将事务管理代码嵌入到业务方法中来控制事务的提交和回滚,在编程式事务中,必须在每个业务操作中包含额外的事务管理代码 声明式事务管理:大多数情况下比编程式事务管理更好用。它将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。事务管理作为一种横切关注点,可以通过AOP方法模块化。Spring通过Spring AOP框架支持声明式事务管理。 如何在Spring配置文件中定义事务管理器: 声明对本地事务的支持: a)JDBC及iBATIS、MyBatis框架事务管理器 在Spring中,声明式事务是通过事务属性来定义的,事务属性描述了事务策略如何应用到方法上。尽管Spring提供了多种声明式事务的机制,但是所有的方式都依赖这五个参数来控制如何管理事务策略。声明式事务通过传播行为,隔离级别,只读提示,事务超时及回滚规则来进行定义。 Spring事务的传播行为: 当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。 事务的传播行为可以由传播属性指定。Spring定义了7种传播行为: 1.Propagation.REQUIRED 方法被调用时自动开启事务,在事务范围内使用则使用同一个事务,否则开启新事务。 2.Propagation.REQUIRES_NEW 无论何时自身都会开启事务 3.Propagation.SUPPORTS 自身不会开启事务,在事务范围内则使用相同事务,否则不使用事务 4.Propagation.NOT_SUPPORTED 自身不会开启事务,在事务范围内使用挂起事务,运行完毕恢复事务 5.Propagation.MANDATORY 自身不开启事务,必须在事务环境使用否则报错 6.Propagation.NEVER 自身不会开启事务,在事务范围使用抛出异常 7.Propagation.NESTED 如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行。需要JDBC3.0以上支持。 1. ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与JDBC的隔离级别相对应 2. ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。 3. ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据 4. ISOLATION_REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。 它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。 5. ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。 除了防止脏读,不可重复读外,还避免了幻像读。 “只读事务”并不是一个强制选项,它只是一个“暗示”,提示数据库驱动程序和数据库系统,这个事务并不包含更改数据的操作,那么JDBC驱动程序和数据库就有可能根据这种情况对该事务进行一些特定的优化,比方说不安排相应的数据库锁,以减轻事务对数据库的压力,毕竟事务也是要消耗数据库的资源的。“只读事务”仅仅是一个性能优化的推荐配置而已,并非强制你要这样做不可。 为了使应用程序更好的运行,事务不能运行太长的时间。因此,声明式事务的第四个特性就是超时。 默认情况下,事务只有在遇到运行期异常时才会回滚,而在遇到检查型异常时不会回滚,但是也可以声明事务在遇到特定的检查型异常时像遇到运行期异常那样回滚。同样,你还可以声明事务遇到特定的异常不回滚,即使这些异常是运行期异常。 1.创建独立的Spring应用程序 2.嵌入式的Tomcat,不需要部署war包 3.简化Maven配置 4.自动配置Spring 5.提供生产就绪型功能,如指标,健康检查,和外部配置 6.开箱即用,没有代码生成,也无需XML配置 - no:不进行自动装配,手动设置Bean的依赖关系。 - byName:根据Bean的名字进行自动装配。 - byType:根据Bean的类型进行自动装配。 - constructor:类似于byType,不过是应用于构造器的参数,如果正好有一个Bean与构造器的参数类型相同则可以自动装配,否则会导致错误。 - autodetect:如果有默认的构造器,则通过constructor的方式进行自动装配,否则使用byType的方式进行自动装配。 - 如果使用了构造器注入或者setter注入,那么将覆盖自动装配的依赖关系。 - 基本数据类型的值、字符串字面量、类字面量无法使用自动装配来注入。 - 优先考虑使用显式的装配来进行更精确的依赖注入而不是使用自动装配。 xml配置 优势:集中配置,代码配置分离更加方便管理 劣势:繁杂,编译期不容易发现错误 javaConfig配置 优势:代码简洁, 劣势:国内xml配置方式比较多,不容易被人接受 singleton prototype 多例即原型 Request 和http请求关联 Session 会话 application 应用程序 ① Spring IoC容器找到关于Bean的定义并实例化该Bean。 ② Spring IoC容器对Bean进行依赖注入。 方法被调用。 ⑧ 当销毁Bean实例时,如果Bean实现了DisposableBean接口,则调用其destroy方法。30. String s = new String("xyz");创建了几个字符串对象。
31. String 和StringBuffer的区别。
32. 数组有没有length()这个方法? String有没有length()这个方法?
33. final, finally, finalize的区别。
34. Errror , Exception,RuntimeException区别
35. Java语言如何进行异常处理,关键字:throws、throw、try、catch、finally分别如何使用。
36. throw和throws有什么区别?
37. 请说一下你常用的几种异常?
38. 线程的基本概念?线程的基本状态以及状态之间的关系
39. sleep() 和 wait() 有什么区别?
40. 多线程有几种实现方法?
41. 启动一个线程是用run()还是start()? .
42. 线程的基本状态以及状态之间的关系。
43. Set和List的区别,List和Map的区别?
44. 同步方法、同步代码块区别?
45. 描述Java 锁机制。
46. Comparable和Comparator接口是干什么的?列出它们的区别
47. Java集合类框架的最佳实践有哪些?
48. HashMap和Hashtable的区别。
49. HashSet和TreeSet有什么区别?
50. 说出ArrayList,Vector, LinkedList的存储性能和特性。
51. 在Java语言,怎么理解goto。
52. 请描述一下Java 5有哪些新特性?
53. Java 6新特性有哪些。
54. Java 7 新特性有哪些。
55. Java 8 新特性有哪些。
56. 描述Java 动态代理。
57. 为什么要使用单例模式?
58. Java中有哪些常用排序方式,使用Java实现冒泡排序。
59. Java中垃圾回收有什么目的?什么时候进行垃圾回收?
60. 如何实现对象克隆。
61. Java设计模式有哪些?
62. GC是什么?为什么要有GC?
63. Java中是如何支持正则表达式。
64. 比较一下Java和JavaSciprt。
65. Math.round(11.5) 等于多少?Math.round(-11.5)等于多少?
66. JDBC连接数据库的步骤?
67. Class.forName()方法有什么作用?
68. JDBC中如何进行事务处理
69. JDBC能否处理Blob和Clob
70. JDBC中的PreparedStatement相比Statement的好处
71. 解释内存中的栈(stack)、堆(heap)和静态区(static area)的用法。
72. 怎样将GB2312编码的字符串转换为ISO-8859-1编码的字符串?
73. 运行时异常与受检异常有何异同?
74. 列出一些你常见的运行时异常?
75. List、Set、Map是否继承自Collection接口?
76. Thread类的sleep()方法和对象的wait()方法都可以让线程暂停执行,它们有什么区别?
77. 线程的sleep()方法和yield()方法有什么区别?
78. 请说出与线程同步以及线程调度相关的方法。
79. 举例说明同步和异步。
80. Java中如何实现序列化,有什么意义?
81. 获得一个类的类对象有哪些方式?
82. 如何通过反射创建对象?
83. Enumeration接口和Iterator接口的区别有哪些?
84. 串行(serial)收集器和吞吐量(throughput)收集器的区别是什么?
85. 什么是B/S和C/S?
86. 如何设置servlet初始化参数?如何获取servlet初始化的参数?
87. Ajax是什么?
88. HTTP请求的GET与POST方式的区别?
89. 说一说Servlet的生命周期? Servlet里常用的方法有哪些?
90. Servlet API中forward() 与redirect()的区别?
91. 什么是JSP
92. Jsp优缺点。
93. jsp有哪些内置对象?
94. 讲解JSP中的四种作用域。
95. Session和Cookie的区别?
96. 常用的Web服务器有哪些
97. 什么是Servlet。
98. JSP和Servlet是什么区别和联系。
99. web.xml文件中可以配置哪些内容。
100. 说一下表达式语言(EL)的隐式对象及其作用。
101. 使用标签库有什么好处
102. 表达式语言(EL)支持哪些运算符。
103. 你的项目中使用过哪些JSTL标签。
104. 静态include和动态include的区别?
105. 如何设置请求的编码以及响应内容的类型。
106. ORM框架的原理是什么?
107. 什么是DAO模式?
108. 举一个多对多关联的例子,并说明如何实现多对多关联映射。
109. 谈一下你对继承映射的理解。
110. 什么是Hibernate,好处是什么?
111. Hibernate的核心思想?
112. 什么是Mybatis?
113. MyBatis中使用#和$书写占位符有什么区别?
114. Hibernate 与 Mybatis区别(MyBatis与Hibernate有什么不同)。
115. 持久层设计要考虑的问题有哪些?
116. 你用过的持久层框架有哪些
117. @OneToMany注解的mappedBy属性有什么作用?
118. MyBatis中的动态SQL是什么意思?
119. 如何解决 Mybatis “n+1”问题。
120. Mybatis 动态SQL相关标签作用及含义?
121. 什么是JDBC,简述实现方法?
122. 请介绍一下数据库连接池技术?
123. MySQL、Oracle、SQL Server各数据库服务的默认端口号?
124. MyBatis中如何实现分页?
125. MyBatis中如何实现数据映射?
126. MyBatis中的缓存如何使用?
127. MyBatis中的使用流程?
128. MyBatis中的关联如何实现?
129. MyBatis中的插件如何实现?
130. 请描述MyBatis中的优缺点?
131. 请描述MyBatis如何进行批量操作?
132. 请描述MyBatis如何获取自增的主键值?
133. 请描述MyBatis的Mapper功能方法如何传递多个参数?
134. 什么是Maven。
135. 什么是SVN。
136. 什么是GIT。
137. Java常用构建工具区别(ant,maven,gradle区别)。
138. 常用源码版本管理工具有几种,并说明其优缺点(svn,git)。
139. 什么是MVC?常用的MVC框架有哪些?
140. Struts框架的优缺点。
141. 说说struts2和springmvc的区别?
142. 什么是AOP?谈谈你对他的理解。
143. 什么是IOC和DI?
144. 依赖注入的两种方式?
145. Web应用开发中,如何启用Spring框架支持,写出关键配置。
146. 简述Spring Aop 实现方法(cglib,java proxy差别)。
147. Spring框架为企业级开发带来的好处有哪些?
148. SpringMVC 执行流程。
149. 描述Spring 事务的概念。
150. 描述Spring 事务管理机制。
151. 描述Spring 事务的方式。
152. 描述Spring 事务的属性。
153. 描述Spring 事务的隔离级别。
154. 描述Spring 事务的只读、超时、回滚的原则。
155. Spring Boot 的优点。
156. Spring中自动装配的方式有哪些?
157. Spring中的自动装配有哪些限制?
158. Spring JavaConfig 与Xml配置优缺点。
159. Spring IOC容器中Bean范围(scope)有几个?
160. 阐述Spring框架中Bean的生命周期?