`
jefferent
  • 浏览: 80256 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

java笔试题套题(1)

 
阅读更多

数据库:
(1)举例说明Dynamic SQL的原理及应用?

      答:嵌入式SQL语句为编程提供了一定的灵活性,使用户可以在程序运行过程中根据实际需要输入WHERE子句或HAVING子句中某些变量的值。这些SQL语句的共同特点是,语句中主变量的个数与数据类型在预编译时都是确定的,只有主变量的值是程序运行过程中动态输入的,我们称这类嵌入式SQL语句为静态SQL语句。
静态SQL语句提供的编程灵活性在许多情况下仍显得不足,有时候我们需要编写更为通用的程序。例如,查询学生选课关系SC,任课教师想查选修某门课程的所有学生的学号及其成绩,班主任想查某个学生选修的所有课程的课程号及相应成绩,学生想查某个学生选修某门课程的成绩,也就是说查询条件是不确定的,要查询的属性列也是不确定的,这时就无法用一条静态SQL语句实现了。
    实际上,如果在预编译时下列信息不能确定,我们就必须使用动态SQL技术:

  • SQL语句正文
  • 主变量个数
  • 主变量的数据类型
  • SQL语句中引用的数据库对象(例如列、索引、基本表、视图等)

    动态SQL方法允许在程序运行过程中临时“组装”SQL语句,主要有三种形式:
     <1> 语句可变。可接收完整的SQL语句。即允许用户在程序运行时临时输入完整的SQL语句。
     <2> 条件可变。
    对于非查询语句,条件子句有一定的可变性。例如删除学生选课记录,既可以是因某门课临时取消,需要删除有关该课程的所有选课记录,也可以是因为某个学生退学,需要删除该学生的所有选课记录。
对于查询语句,SELECT子句是确定的,即语句的输出是确定的,其他子句(如WHERE子句、HAVING短语)有一定的可变性。例如查询学生人数,可以是查某个系的学生总数,查某个性别的学生人数,查某个年龄段的学生人数,查某个系某个年龄段的学生人数等等,这时SELECT子句的目标列表达式是确定的(COUNT(*)),但WHERE子句的条件是不确定的。
     <3> 数据库对象、查询条件均可变。对于查询语句,SELECT子句中的列名、FROM子句中的表名或视图名、WHERE子句和HAVING短语中的条件等等均可由用户临时构造,即语句的输入和输出可能都是不确定的。例如我们前面查询学生选课关系SC的例子。对于非查询语句,涉及的数据库对象及条件也是可变的。
这几种动态形式几乎可覆盖所有的可变要求。为了实现上述三种可变形式,SQL提供了相应的语句,例如EXECUTE IMMEDIATE、PREPARE、EXECUTE、DESCRIBE等。使用动态SQL技术更多的是涉及程序设计方面的知识,而不是SQL语言本身。

 

在mysql中使用动态SQL:

mysql> set @sql_text:='select count(*) from test';
Query OK, 0 rows affected (0.00 sec)

mysql> prepare stmt from @sql_text;
Query OK, 0 rows affected (0.04 sec)
Statement prepared

mysql> execute stmt;
+----------+
| count(*) |
+----------+
| 0 |
+----------+
1 row in set (0.19 sec)

mysql> deallocate prepare stmt;
Query OK, 0 rows affected (0.00 sec)

在存储过程中改变@sql_text的值,则可以实现动态SQL的效果了。

但要注意,能够使用prepare的SQL是有限制的:

The following SQL statements can be used in prepared statements: CREATE TABLE, DELETE, DO, INSERT, REPLACE, SELECT, SET, UPDATE, and most SHOW statements. supported. ANALYZE TABLE, OPTIMIZE TABLE, and REPAIR TABLE are supported as of MySQL 5.0.23. Other statements are not yet supported.

 
(2)举例说明数据库索引的优缺点?

    答:

<1> 为什么要创建索引呢?这是因为,创建索引可以大大提高系统的性能。
第一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
第二,可以大大加快 数据的检索速度,这也是创建索引的最主要的原因。
第三,可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
第四,在使用分组和排序 子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
第五,通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

<2> 也许会有人要问:增加索引有如此多的优点,为什么不对表中的每一个列创建一个索引呢?这种想法固然有其合理性,然而也有其片面性。虽然,索引有许多优点, 但是,为表中的每一个列都增加索引,是非常不明智的。这是因为,增加索引也有许多不利的一个方面。

第一,创建索引和维护索引要耗费时间,这种时间随着数据 量的增加而增加。
第二,索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。
第三,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。

<3> 索引是建立在数据库表中的某些列的上面。因此,在创建索引的时候,应该仔细考虑在哪些列上可以创建索引,在哪些列上不能创建索引。一般来说,应该在这些列 上创建索引,例如:

在经常需要搜索的列上,可以加快搜索的速度;
在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;
在经常用在连接的列上,这 些列主要是一些外键,可以加快连接的速度;
在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;
在经常需要排序的列上创 建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;
在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。


<4> 同样,对于有些列不应该创建索引。一般来说,不应该创建索引的的这些列具有下列特点:

第一,对于那些在查询中很少使用或者参考的列不应该创建索引。这是因 为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。
第二,对于那 些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比 例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。
第三,对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。
第四,当修改性能远远大于检索性能时,不应该创建索 引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因 此,当修改性能远远大于检索性能时,不应该创建索引。


(3)如果由你来设计数据的rollback,你的思路和方案?

    答:要设计rollback,首先需要了解事务的概念:

    数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。

    在事务处理过程中出现任何异常,数据库将放弃未进行的操作,并将之前以进行的数据操作进行恢复,即常说的回滚(rollback)。

    需要完成rollback,就需要知道哪些内容应该被回滚。回滚时应该优先回滚最后进行的操作。这样我们可以使用一个堆栈来记录本次事务处理过程中,已进行的操作,如果成功完成事务过程,则在commit之后释放堆栈,如果出现任何异常,则在rollback的时候按事务的操作记录依次出栈。

(4)假设有一个table,名为pages,有四个字段,id ,url,title,body。里面储了很多网页,网页的url地址,title和网页内容,用一个sql查询将url匹配的排在最前面,title匹配的在其次,body匹配的排最后,没有任何字段匹配的,不返回。

    答:
select a.[id],a.mark from
(
select [page].[id],100 as mark from [page] where [page].[url] like '%baidu%'
union
select [page].[id],50 as mark from [page] where [page].[title] like '%baidu%'
union
select [page].[id],10 as mark from [page] where [page].[body] like '%baidu%'
) as a order by mark desc
 
    用union 实现联合查询,在每个查询语句中定义一个临时变量mark 并给mark赋值,在最后的输出时采用mark来排序。

(5)自定义函数与存储过程的区别是什么?什么情况下只能用自定义函数,什么情况下只能用存储过程?
    答:存储过程可以使得对数据库的管理、以及显示关于数据库及其用户信息的工作容易得多。存储过程是 SQL 语句和可选控制流语句的预编译集合,以一个名称存储并作为一个单元处理。存储过程存储在数据库内,可由应用程序通过一个调用执行,而且允许用户声明变量、有条件执行以及其它强大的编程功能。
  存储过程可包含程序流、逻辑以及对数据库的查询。它们可以接受参数、输出参数、返回单个或多个结果集以及返回值。
  可以出于任何使用 SQL 语句的目的来使用存储过程,它具有以下优点:
  (1)可以在单个存储过程中执行一系列 SQL 语句。
  (2)可以从自己的存储过程内引用其它存储过程,这可以简化一系列复杂语句。
  (3)存储过程在创建时即在服务器上进行编译,所以执行起来比单个 SQL 语句快。
    自定义函数:一般用于在其他SQL中调用。自定义函数中有诸多限制,有许多语句不能使用,许多功能不能实现。
两者的比较:
存储过程
  • 功能强大,限制少

  • 不能直接引用返回值

  • 用select语句返回记录集

自定义函数

  • 诸多限制,有许多语句不能使用,许多功能不能实现

  • 可以直接引用返回值

  • 用表变量返回记录集

 

(6)管理50台数据库,日常工作是检查数据库作业是否完成,你应该如何完成这项检查工作?

    答: 在每台机器上建立linkserver,然后在DBA管理服务器上做个分布式视图,每次查询该视图,各个机器上的作业情况一目了然。分布式视图写法:

create view vw_joBas
select '机器一' as MName,* from linkserver1..sysjobactivity
union all
select '机器二' as MName,* from linkserver2..sysjobactivity
union all
select '机器三' as MName,* from linkserver3..sysjobactivity

    其中,sysjobactivity 表记录当前 SQL Server 代理作业活动和状态。

 

网络:
(1)使用UML圈中的时序图,描述TCP/ip三次握手过程。

 答:

图 TCP三次握手及数据传输过程


(2)简友交换机,路由器,Hub的共性和不同。

    答:首先说HUB,也就是 集线器 。它的作用可以简单的理解为将一些机器连接起来组成一个局域网。而 交换机 (又名交换式集线器)作用与集线器大体相同。但是两者在性能上有区别:集线器采用的是共享带宽的工作方式,而交换机是独享带宽。这样在机器很多或数据量很大时,两者将会有比较明显的。而 路由器 与以上两者有明显区别,它的作用在于连接不同的网段并且找到网络中数据传输最合适的路径 ,可以说一般情况下个人用户需求不大。路由器是产生于交换机之后,就像交换机产生于集线器之后,所以路由器与交换机也有一定联系,并不是完全独立的两种设备。路由器主要克服了交换机不能路由转发数据包的不足。


(3)简述UDP的原理和应用场景。

    答:UDP(User DataGram Protocol)的缩写,是一种无连接的协议,使用UDP传输数据时,每个数据段都是一个独立的信息,包括完整的源地址和目的地,在网络上以任何可能的路径传到目的地,因此,能否到达目的地,以及到达目的地的时间和内容的完整性都不能保证。

    UDP的特点:

  • UDP传送数据前并不与对方建立连接,即UDP是无连接的,在传输数据前,发送方和接收方相互交换信息使双方同步。
  • UDP不对收到的数据进行排序,在UDP报文的首部中并没有关于数据顺序的信息(如TCP采用的序号),而且报文不一定按顺序到达的,所以接收端无从排起。
  • UDP对接收到的数据报不发送确认信号,发送端不知道数据是否被正确接收,也不会重发数据。
  • UDP传送数据较TCP快速,系统开销也小。

    UDP的应用:

  • 在只需要简单的数据交换应用中,如DNS服务
  • 在不需要关心数据的差错机制和流量控制的应用中,这种情况下一般是由于高层已经提供了这些机制,如TFTP(Trivial File Transfer Protocol)
  • 在实时性要求高而可承受一定的数据错误的应用中,如实时的语音视频传输
  • 在广播和组播服务中也使用UDP

语言:
(1)public class TestString{
public static void link(String a){
  a +="World";
}
public static void main(String[] args){
  String a = "Hello";
  link(a);
  System.out.PRintln(a);
        }
}

    答:输出为:Hello,这里的String虽然是引用传递,但是a +="World"会创建一个新的String,而之前传入的String没有发生改变,所以仍然是Hello


(2)System.out.println("ja"+"va"=="java");

    答:输出为:true,当两个字符串字面值连接时(相加),得到的新字符串依然是字符串字面值,保存在常量池中。

 

(3)简述GC的工作原理。

    答:对于GC来说,当程序员创建对象时,GC就开始监控这个对象的 地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的", 哪些对象是"不可达的".当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空间。但是,为了保证GC能够在不同平台实现的问题,Java规范 对GC的很多行为都没有进行严格的规定。例如,对于采用什么类型的回收算法、什么时候进行回收等重要问题都没有明确的规定。因此,不同的JVM的实现者往 往有不同的实现算法。这也给Java程序员的开发带来行多不确定性。

(4)sleep() 与wait()有什么区别。

    答:

      <1> 这两个方法来自不同的类分别是Thread和Object
      <2> 最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
      <3> wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用(使用范围)
        synchronized(x){
           x.notify()
          //或者wait()
        }
      <4> sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常。

 

 

 

 

 

 

(5)HashMap()与Hashtable的区别。

     答:Hastmap是一个接口 是map接口的子接口,是将键映射到值的对象,其中键和值都是对象,并且不能包含重复键,但可以包含重复值。HashMap允许null key和null value,而hashtable不允许。HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。HashMap允许将null作为一个entry的key或者value,而Hashtable不允许。
HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因为contains方法容易让人引起误解。 Hashtable继承自Dictionary类,而HashMap是Java1.2引进的Map interface的一个实现。
最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。 Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异。

 

 

 

 

 

 

(6)Interface与Abstract class的区别。

答:主要区别如下所示:

    (1) interface被继承时用的关键字是implements,而且可以同时implements多个interface,而abstract class被继承时用的关键字是extends,而且只能同时extends一个abstract class。
    (2) interface内定义的方法都是public的,而abstract class内的则不一定。
    (3) interface内定义的成员对象都是static & final的,而abstract class不是(一定不能是final)
    (4) interface的方法不能有默认实现,只有一个申明,而abstract class内申明abstract的方法不能有实现,非申明abstract的方法可以有默认实现。
    (5) interface被implements时,所有方法都必须被实现,必须申明是public的,而abstract class被extends时只有abstract的方法才必须被实现,别的有默认实现的直接被继承过来。
  注:不能创建接口或抽象类的实例。


(7)请设计一个递归程序,使用最简练的代码。


(8)请列举你熟悉的两种设计模式,举例说明其原理。

    答:参见本博设计模式系列。

 

(9)Apache与Tomcat有什么关系和区别。

    答:分别描述如下所示:

Tomcat

    如今,基于Web的应用越来越多,传统的Html已经满足不了如今的需求。我们需要一个交互式的Web,于是便诞生了各种Web语言。如Asp,Jsp, Php等。当然,这些语言与传统的语言有着密切的联系,如Php基于C和C++语言,Jsp基于Java语言。本文所要介绍的Tomcat即是一个Jsp 和Servlet的运行平台。

Tomcat不仅仅是一个Servlet容器,它也具有传统的Web服务器的功能:处理Html页 面。但是与Apache相比,它的处理静态Html的能力就不如Apache。我们可以将Tomcat和Apache集成到一块,让Apache处理静态 Html,而Tomcat处理Jsp和Servlet。这种集成只需要修改一下Apache和Tomcat的配置文件即可。

基于 Tomcat的开发其实主要是Jsp和Servlet的开发,开发Jsp和Servlet非常简单,你可以用普通的文本编辑器或者IDE,然后将其打包成 WAR即可。我们这里要提到另外一个工具Ant,Ant也是Jakarta中的一个子项目,它所实现的功能类似于Unix中的make。你需要写一个 build.xml文件,然后运行Ant就可以完成xml文件中定义的工作,这个工具对于一个大的应用来说非常好,我们只需在xml中写很少的东西就可以 将其编译并打包成WAR。事实上,在很多应用服务器的发布中都包含了Ant。另外,在Jsp1.2中,可以利用标签库实现Java代码与Html文件的分 离,使Jsp的维护更方便。

Apache:

    Apache是一种免费的网站服务器,所以也不用钱...
    Apache是一种占有率最高网站服务器,是微软的三倍...
    Apache是一种最稳定的网站服务器,效率好!
    Apache是世界排名第一的Web服务器, 根据Netcraft所作的调查,世界上百分之五十以上的Web服务器在使用Apache.
     1995 年4月, 最早的Apache(0.6.2版)由Apache Group公布发行. Apache Group 是一个完全通过Internet进行运 作的非盈利机构, 由它来决定Apache Web服务器的标准发行版中应该包含哪些内容. 准许任何人修改隐错, 提供新的特征和将它移植到新的平台 上, 以及其它的工作. 当新的代码被提交给Apache Group时, 该团体审核它的具体内容, 进行测试, 如果认为满意, 该代码就会被集成到 Apache的主要发行版中.
    Apache 的特性:
1) 几乎可以运行在所有的计算机平台上.
2) 支持最新的HTTP/1.1协议
3) 简单而且强有力的基于文件的配置(HTTPD.CONF).
4) 支持通用网关接口(CGI)
5) 支持虚拟主机.
6) 支持HTTP认证.
7) 集成PERL.
8) 集成的代理服务器
9) 可以通过WEB浏览器监视服务器的状态, 可以自定义日志.
10) 支持服务器端包含命令(SSI).
11) 支持安全SOCKET层(SSL).
12) 具有用户会话过程的跟踪能力.
13) 支持FASTCGI
14) 支持JAVA SERVLETS.

 

 

 

(10)什么是重构?重构最终目的是什么?列举几种常用的重构工具和方法。

     答:重构(Refactoring)就是在不改变软件现有功能的基础上,通过调整程序代码改善软件的质量、性能,使其程序的设计模式和架构更趋合理,提高软件的扩展性和维护性。

    由定义可知,重构的目的是为了提高软件的扩展性和维护性。设计模式是经过提炼和验证的设计思想,重构的目标是模式,不能为了模式而模式。

    什么时候不重构?

  • 程序原型
  • 系统还不能工作
  • 逼近交期(已经要交付,效率提升没有多大意义)

    何时进行重构?

  • 存在重复的时候。(三次法则)
  • 当我们觉得代码或代码所表达的意图不清晰的时候。
  • 当我们察觉到代码有bad smells 的时候。

    如何进行重构?

(1)准备好自动测试环境,这些测试能在我们执行重构时及时的向我们反馈重构是否伤到原有行为。
(2)小步前进,在每一步重构完成时运行测试。以便于最快的检查重构的有效性。如果失败,必须恢复到正确代码,再尝试进一步的重构。
(3)擅于使用优良的重构工具可以大大减少我们重构所需的时间。

 

  • 重构方法如下:
  • 提取方法:当一个方法太长或逻辑过于复杂而不易理解时,我们可以将其中的某些部分提取出来而形成各自独立的方法。
  • 用委托来代替继承(Replace Inheritance witch Delegation):我们应当只在子类对超类进行扩展而不仅仅是覆写超类的部分功能时,才使用继承。如果只是为了重用超类的某些功能的话,应该用委托来代替继承。
  • 用子类来代替型别码(Replace Type with Subclasses):当我们的类使用型别码来表示子类的时候(例如,雇员分工程师,销售人员和管理人员),就可以使用这种重构方法。针对每种类型分别设计子类可以消除那些根据型别码进行判别的复杂的条件判断和switch语句。
  • 用多态来代替条件判断(Replace conditional with Polymorphism):当我们发现代码中有switch语句时,可以考虑创建子类处理不同的情况,从而去掉switch语句。
  • 模板函数(Form Template Method):当我们在多个类中都有某种具有相同结构但不同细节的相似方法时就可以使用这种重构方法。相同结构的方法放在父类中,提取出来的细节具体方法在子类中实现。
    提取类:当一个类变得太大或其行为逻辑组织分散时,我们需要将其分成多块内聚的行为并在需要的时候创建新类。
  • 提取接口:当两个classes的接口有部分相同,可以考虑提取接口。
  • 引入解释变量(Introduce Explaining Variable):当表达式复杂且难以理解时,我们就可以提取其中的某些部分,把中间结果保留在命名清楚的临时变量中。把表达式切分成容易理解的片段,提高整个表达式的清晰度。
  • 使用工厂方法来代替构造方法(Replace Constructor with Factory Method):因为构造方法具有相同的名字,所以当存在多个构造方法时,就容易让人搞不清楚调用哪个。对此我们使用静态工厂方法,这样就能给每个构造方法起一个有意义的名字。
  • 使用符号常量来代替魔化数字(Replace Magic Number with Symbolic Constant):在代码中硬性编码的数值是一种非常不好的习惯。这样的数值很难分辨,改变它们会引起霰弹式手术,其实这也是一种重复。可以用命名良好的符号常量来代替它们。
  • 使用卫述句代替嵌套的条件判断(Replace Nested Conditional with Guard Clauses):单一出口规则要求每个方法只能有一个出口(即return语句)。对应当在多种条件下退出的方法来说,就会导致复杂、嵌套的条件判断语句。这种情况下一种更好更清楚的解决办法就是采用卫述句来返回。

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics