java工程师面试题_第1页
java工程师面试题_第2页
java工程师面试题_第3页
java工程师面试题_第4页
java工程师面试题_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、1 . struts1 和 struts2区别:Struts2 从本质上讲已不是从 Struts1 扩展而来的, 说它是一个换了品牌标签的 WebWork 更合适。从 Struts1 升级到 Struts2:Struts1 里使用 ActionServlet 作为控制器; Struts2 使用了一个过滤器作为控制器Struts1 中每个 HTML 表单都对应一个 ActionForm 实例. Struts2 中, HTML 表单将被直接映射到一个 POJO.Struts1 的验证逻辑编写在 ActionForm 中; Struts2 中的验证逻辑编写在 Action 中.Struts1 中,

2、Action 类必须继承类; Struts2 中任何一个 POJO 都可以是一个 Action 类. Struts2 在页面里使用 OGNL 来显示各种对象模型, 可以不再使用 EL 和 JSTLPS:POJO(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBeans2. struts1的缺陷: 1).单元测试困难: HttpServletRequest和HttpServletResponse是由Servlet容器负责实例化的,因此Acton类的测试就要依赖于Web容器,单元测试很难实现。当然,也可以使用第三方的测试工具-JUnit的扩展工具St

3、rutsTestCase来对Action进行单元测试,但是测试相对来说比较困难这是不争的事实! 2) Action是单例模式并且必须是线程安全的 因为仅有Action的一个实例来处理求。单例策略限制了Struts1Action能作的事,并且要在开发时特别小心。Action资源必须是线程安全的或同步的。 3).对Servlet的依赖性太大 4). Struts1使用ActionForm对象捕获输入 所有的ActionForm必须继承一个基类。因为其他JavaBean不能用作ActionForm,开发者经常创建多余的类捕获输入。动态Bean(DynaBeans)可以作为创建传统ActionForm

4、的选择,但是,开发者可能是在重新描述(创建)已经存在的JavaBean(仍然会导致有冗余的javabean) 5)每配置一下 struts-config,须重新启动tomcat,而且配置烦所,页面转向过多,导致forword配置过多使得 struts-config文件内容过多,寻找东西比较困难 6)到了struts3.0的时候,发现建一个action就必须要有相应的actionform与之对应。导致没必要有actionform的action都要建立actionform。要不然web页面是提交不到action的。3. 分布式存储集群文件系统是指运行在多台计算机之上,之间通过某种方式相互通信从而将

5、集群内所有存储空间资源整合、虚拟化并对外提供文件访问服务的文件系统。其与NTFS、EXT等本地文件系统的目的不同,前者是为了扩展性,后者运行在单机环境,纯粹管理块和文件之间的映射以及文件属性。集群文件系统分为多类,按照对存储空间的访问方式,可分为共享存储型集群文件系统和分布式集群文件系统,前者是多台计算机识别到同样的存储空间,并相互协调共同管理其上的文件,又被称为共享文件系统;后者则是每台计算机各自提供自己的存储空间,并各自协调管理所有计算机节点中的文件。Veritas的VxFS/VCS,昆腾Stornext,中科蓝鲸BWFS,EMC的MPFS,属于共享存储型集群文件系统。而HDFS、Glus

6、ter、Ceph、Swift等互联网常用的大规模集群文件系统无一例外都属于分布式集群文件系统。分布式集群文件系统可扩展性更强,目前已知最大可扩展至10K节点。按照元数据的管理方式,可分为对称式集群文件系统和非对称式集群文件系统。前者每个节点的角色均等,共同管理文件元数据,节点间通过高速网络进行信息同步和互斥锁等操作,典型代表是Veritas的VCS。而非对称式集群文件系统中,有专门的一个或者多个节点负责管理元数据,其他节点需要频繁与元数据节点通信以获取最新的元数据比如目录列表文件属性等等,后者典型代表比如HDFS、GFS、BWFS、Stornext等。对于集群文件系统,其可以是分布式+对称式、

7、分布式+非对称式、共享式+对称式、共享式+非对称式,两两任意组合。按照文件访问方式来分类,集群文件系统可分为串行访问式和并行访问式,后者又被俗称为并行文件系统。串行访问是指客户端只能从集群中的某个节点来访问集群内的文件资源,而并行访问则是指客户端可以直接从集群中任意一个或者多个节点同时收发数据,做到并行数据存取,加快速度。HDFS、GFS、pNFS等集群文件系统,都支持并行访问,需要安装专用客户端,传统的NFS/CIFS客户端不支持并行访问。对于分布式集群,其对文件元数据的管理方式又可以分为single path image和single filesystem image两种方式,具体可以参考

8、大话存储终极版中对集群文件系统的描述。以上总结于大话存储终极版4. JVM底层结构Java虚拟机(Java Virtual Machine) 简称JVM Java虚拟机是一个想象中的机器,在实际的计算机上通过软件模拟来实现。Java虚拟机有自己想象中的硬件,如处理器、堆栈、寄存器等,还具有相应的指令系统。下面我们就来看一下这几部分比较重要的java虚拟机的结构JVM寄存器所有的CPU均包含用于保存系统状态和处理器所需信息的寄存器组。如果虚拟机定义义较多的寄存器,便可以从中得到更多的信息而不必对栈或内存进行访问,这有利于提高运行速度。然而,如果虚拟机中的寄存器比实际CPU的寄存器多,在实现虚拟机

9、时就会占用处理器大量的时间来用常规存储器模拟寄存器,这反而会降低虚拟机的效率。针对这种情况,JVM只设置了4个最为常用的寄存器。它们是:pc程序计数器,optop操作数栈顶指针 ,frame当前执行环境指针, vars指向当前执行环境中第一个局部变量的指针, 所有寄存器均为32位。pc用于记录程序的执行。optop,frame和vars用于记录指向Java栈区的指针。JVM栈结构作为基于栈结构的计算机,Java栈是JVM存储信息的主要方法。当JVM得到一个java字节码应用程序后,便为该代码中一个类的每一个方法创建一个栈框架,以保存该方法的状态信息。每个栈框架包括以下三类信息:局部变量执行环境

10、操作数栈 局部变量用于存储一个类的方法中所用到的局部变量。vars寄存器指向该变量表中的第一个局部变量。执行环境用于保存解释器对Java字节码进行解释过程中所需的信息。它们是:上次调用的方法、局部变量指针和操作数栈的栈顶和栈底指针。执行环境是一个执行一个方法的控制中心。例如:如果解释器要执行iadd(整数加法),首先要从frame寄存器中找到当前执行环境,而后便从执行环境中找到操作数栈,从栈顶弹出两个整数进行加法运算,最后将结果压入栈顶。操作数栈用于存储运算所需操作数及运算的结果。JVM碎片回收堆Java类的实例所需的存储空间是在堆上分配的。解释器具体承担为类实例分配空间的工作。解释器在为一个

11、实例分配完存储空间后,便开始记录对该实例所占用的内存区域的使用。一旦对象使用完毕,便将其回收到堆中。在Java语言中,除了new语句外没有其他方法为一对象申请和释放内存。对内存进行释放和回收的工作是由Java运行系统承担的。这允许Java运行系统的设计者自己决定碎片回收的方法。在SUN公司开发的Java解释器和Hot Java环境中,碎片回收用后台线程的方式来执行。这不但为运行系统提供了良好的性能,而且使程序设计人员摆脱了自己控制内存使用的风险。JVM存储区JVM有两类存储区:常量缓冲池和方法区。常量缓冲池用于存储类名称、方法和字段名称以及串常量。方法区则用于存储Java方法的字节码。对于这两

12、种存储区域具体实现方式在JVM规格中没有明确规定。这使得Java应用程序的存储布局必须在运行过程中确定,依赖于具体平台的实现方式。JVM是为Java字节码定义的一种独立于具体平台的规格描述,是Java平台独立性的基础。目前的JVM还存在一些限制和不足,有待于进一步的完善,但无论如何,JVM的思想是成功的。对比分析:如果把Java原程序想象成我们的C+原程序,Java原程序编译后生成的字节码就相当于C+原程序编译后的80x86的机器码(二进制程序文件),JVM虚拟机相当于80x86计算机系统,Java解释器相当于80x86CPU。在80x86CPU上运行的是机器码,在Java解释器上运行的是Ja

13、va字节码。Java解释器相当于运行Java字节码的“CPU”,但该“CPU”不是通过硬件实现的,而是用软件实现的。Java解释器实际上就是特定的平台下的一个应用程序。只要实现了特定平台下的解释器程序,Java字节码就能通过解释器程序在该平台下运行,这是Java跨平台的根本。当前,并不是在所有的平台下都有相应Java解释器程序,这也是Java并不能在所有的平台下都能运行的原因,它只能在已实现了Java解释器程序的平台下运行。Java虚拟机从启动到结束的生命周期,当java虚拟机启动后,在如下几种情况下,Java虚拟机将结束生命周期:1.执行了System.exit()方法 2.程序正常执行结束

14、 3.程序在执行过程中遇到了异常或错误而异常终止4.由于操作系统出现错误而导致Java虚拟机进程终止 Java虚拟机的栈有三个区域:局部变量区、运行环境区、操作数区。局部变量区每个Java方法使用一个固定大小的局部变量集。它们按照与vars寄存器的字偏移量来寻址。局部变量都是32位的。长整数和双精度浮点数占据了两个局部变量的空间,却按照第一个局部变量的索引来寻址。(例如,一个具有索引n的局部变量,如果是一个双精度浮点数,那么它实际占据了索引n和n+1所代表的存储空间)虚拟机规范并不要求在局部变量中的64位的值是64位对齐的。虚拟机提供了把局部变量中的值装载到操作数栈的指令,也提供了把操作数栈中

15、的值写入局部变量的指令。运行环境区在运行环境中包含的信息用于动态链接,正常的方法返回以及异常捕捉。操作数栈区机器指令只从操作数栈中取操作数,对它们进行操作,并把结果返回到栈中。选择栈结构的原因是:在只有少量寄存器或非通用寄存器的机器(如Intel486)上,也能够高效地模拟虚拟机的行为。操作数栈是32位的。它用于给方法传递参数,并从方法接收结果,也用于支持操作的参数,并保存操作的结果。例如,iadd指令将两个整数相加。相加的两个整数应该是操作数栈顶的两个字。这两个字是由先前的指令压进堆栈的。这两个整数将从堆栈弹出、相加,并把结果压回到操作数栈中。每个原始数据类型都有专门的指令对它们进行必须的操

16、作。每个操作数在栈中需要一个存储位置,除了long和double型,它们需要两个位置。操作数只能被适用于其类型的操作符所操作。例如,压入两个int类型的数,如果把它们当作是一个long类型的数则是非法的。在Sun的虚拟机实现中,这个限制由字节码验证器强制实行。但是,有少数操作(操作符dupe和swap),用于对运行时数据区进行操作时是不考虑类型的。本地方法栈,当一个线程调用本地方法时,它就不再受到虚拟机关于结构和安全限制方面的约束,它既可以访问虚拟机的运行期数据区,也可以使用本地处理器以及任何类型的栈。例如,本地栈是一个C语言的栈,那么当C程序调用C函数时,函数的参数以某种顺序被压入栈,结果则

17、返回给调用函数。在实现Java虚拟机时,本地方法接口使用的是C语言的模型栈,那么它的本地方法栈的调度与使用则完全与C语言的栈相同。 Java虚拟机的运行过程:上面对虚拟机的各个部分进行了比较详细的说明,下面通过一个具体的例子来分析它的运行过程。虚拟机通过调用某个指定类的方法main启动,传递给main一个字符串数组参数,使指定的类被装载,同时链接该类所使用的其它的类型,并且初始化它们。例如对于程序:class HelloApp public static void main(String args) "Hello World!"); for (int i = 0; i &l

18、t; args.length; i+ ) argsi); 编译后在命令行模式下键入: java HelloApp run virtual machine将通过调用HelloApp的方法main来启动java虚拟机,传递给main一个包含三个字符串"run"、"virtual"、"machine"的数组。现在我们略述虚拟机在执行HelloApp时可能采取的步骤。 开始试图执行类HelloApp的main方法,发现该类并没有被装载,也就是说虚拟机当前不包含该类的二进制代表,于是虚拟机使用ClassLoader试图寻找这样的二进制代表。如果

19、这个进程失败,则抛出一个异常。类被装载后同时在main方法被调用之前,必须对类HelloApp与其它类型进行链接然后初始化。链接包含三个阶段:检验,准备和解析。检验检查被装载的主类的符号和语义,准备则创建类或接口的静态域以及把这些域初始化为标准的默认值,解析负责检查主类对其它类或接口的符号引用,在这一步它是可选的。类的初始化是对类中声明的静态初始化函数和静态域的初始化构造方法的执行。一个类在初始化之前它的父类必须被初始化。整个过程如下:5. 面向对象的三大特征、五大基本原则:三大特性是:封装,继承,多态 所谓封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象

20、操作,对不可信的进行信息隐藏。封装是面向对象的特征之一,是对象和类概念的主要特性。 简单的说,一个类就是一个封装了数据以及操作这些数据的代码的逻辑实体。在一个对象内部,某些代码或某些数据可以是私有的,不能被外界访问。通过这种方式,对象对内部数据提供了不同级别的保护,以防止程序中无关的部分意外的改变或错误的使用了对象的私有部分。所谓继承是指可以让某个类型的对象获得另一个类型的对象的属性的方法。它支持按级分类的概念。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。 通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“

21、超类”。继承的过程,就是从一般到特殊的过程。要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。继承概念的实现方式有二类:实现继承与接口继承。实现继承是指直接使用基类的属性和方法而无需额外编码的能力;接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力;所谓多态就是指一个类实例的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。五大基本原则 单一职责原则SRP(Single Responsibi

22、lity Principle):指一个类的功能要单一,不能包罗万象。如同一个人一样,分配的工作不能太多,否则一天到晚虽然忙忙碌碌的,但效率却高不起来。开放封闭原则OCP(OpenClose Principle) :一个模块在扩展性方面应该是开放的而在更改性方面应该是封闭的。比如:一个网络模块,原来只服务端功能,而现在要加入客户端功能,那么应当在不用修改服务端功能代码的前提下,就能够增加客户端功能的实现代码,这要求在设计之初,就应当将服务端和客户端分开,公共部分抽象出来。替换原则(the Liskov Substitution Principle LSP) :子类应当可以替换父类并出现在父类能够

23、出现的任何地方。比如:公司搞年度晚会,所有员工可以参加抽奖,那么不管是老员工还是新员工,也不管是总部员工还是外派员工,都应当可以参加抽奖,否则这公司就不和谐了。依赖原则(the Dependency Inversion Principle DIP): 具体依赖抽象,上层依赖下层。假设B是较A低的模块,但B需要使用到A的功能,这个时候,B不应当直接使用A中的具体类: 而应当由B定义一抽象接口,并由A来实现这个抽象接口,B只使用这个抽象接口:这样就达到了依赖倒置的目的,B也解除了对A的依赖,反过来是A依赖于B定义的抽象接口。通过上层模块难以避免依赖下层模块,假如B也直接依赖A的实现,那么就可能造成

24、循环依赖。一个常见的问题就是编译A模块时需要直接包含到B模块的cpp文件,而编译B时同样要直接包含到A的cpp文件。接口分离原则(the Interface Segregation Principle ISP) :模块间要通过抽象接口隔离开,而不是通过具体的类强耦合起来6、String、StringBuilder与StringBuffer的区别(1)可变与不可变:String类中使用字符数组保存字符串,如下就是,因为有“final”修饰符,所以可以知道string对象是不可变的。private final char value;StringBuilder与StringBuffer都继承自Abs

25、tractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,如下就是,可知这两种对象都是可变的。char value;(2).是否多线程安全String中的对象是不可变的,也就可以理解为常量,显然线程安全。AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。看如下源码:复制代码 publi

26、c synchronized StringBuffer reverse() super.reverse(); return this; public int indexOf(String str) return indexOf(str, 0); /存在 public synchronized int indexOf(String str, int fromIndex) 方法 StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。 (3)StringBuilder与StringBuffer共同点StringBuilder与StringBuffer有公共父类AbstractStr

27、ingBuilder(抽象类)。抽象类与接口的其中一个区别是:抽象类中可以定义一些子类的公共方法,子类只需要增加新的功能,不需要重复写已经存在的方法;而接口中只是对方法的申明和常量的定义。StringBuilder、StringBuffer的方法都会调用AbstractStringBuilder中的公共方法,如super.append(.)。只是StringBuffer会在方法上加synchronized关键字,进行同步。最后,如果程序不是多线程的,那么使用StringBuilder效率高于StringBuffer。7. Map 集合(1)什么是Java集合API:Java集合框架API是用来

28、表示和操作集合的统一框架,它包含接口、实现类、以及帮助程序员完成一些编程的算法。简言之,API在上层完成以下几件事: 编程更加省力,提高城程序速度和代码质量非关联的API提高互操作性 节省学习使用新API成本 节省设计新API的时间 鼓励、促进软件重用具体来说,有6个集合接口,最基本的是Collection接口,由三个接口Set、List、SortedSet继承,另外两个接口是Map、SortedMap,这两个接口不继承Collection,表示映射而不是真正的集合。(2) 什么是Iterator一些集合类提供了内容遍历的功能,通过接口。这些接口允许遍历对象的集合。依次操作每个元素对象。当使用

29、 Iterators时,在获得Iterator的时候包含一个集合快照。通常在遍历一个Iterator的时候不建议修改集合本省。(3)、Iterator与ListIterator有什么区别?Iterator:只能正向遍历集合,适用于获取移除元素。ListIerator:继承Iterator,可以双向列表的遍历,同样支持元素的修改。(4) 什么是HaspMap和Map?Map是接口,Java 集合框架中一部分,用于存储键值对,HashMap是用哈希算法实现Map的类。(5)、HashMap与HashTable有什么区别?对比Hashtable VS HashMap两者都是用key-value方式获

30、取数据。Hashtable是原始集合类之一(也称作遗留类)。HashMap作为新集合框架的一部分在Java2的1.2版本中加入。它们之间有一下区别:HashMap和Hashtable大致是等同的,除了非同步和空值(HashMap允许null值作为key和value,而Hashtable不可以)。 HashMap没法保证映射的顺序一直不变,但是作为HashMap的子类LinkedHashMap,如果想要预知的顺序迭代(默认按照插入顺序),你可以很轻易的置换为HashMap,如果使用Hashtable就没那么容易了。 HashMap不是同步的,而Hashtable是同步的。 迭代HashMap采用

31、快速失败机制,而Hashtable不是,所以这是设计的考虑点。(6)、在Hashtable上下文中同步是什么意思?同步意味着在一个时间点只能有一个线程可以修改哈希表,任何线程在执行hashtable的更新操作前需要获取对象锁,其他线程等待锁的释放。(7)、什么叫做快速失败特性从高级别层次来说快速失败是一个系统或软件对于其故障做出的响应。一个快速失败系统设计用来即时报告可能会导致失败的任何故障情况,它通常用来停止正常的操作而不是尝试继续做可能有缺陷的工作。当有问题发生时,快速失败系统即时可见地发错错误告警。在Java中,快速失败与iterators有关。如果一个iterator在集合对象上创建了

32、,其它线程欲“结构化”的修改该集合对象,并发修改异常 (ConcurrentModificationException) 抛出。(8)、怎样使Hashmap同步?HashMap可以通过Map m = Collections.synchronizedMap(hashMap)来达到同步的效果。(9)、什么时候使用Hashtable,什么时候使用HashMap基本的不同点是Hashtable同步HashMap不是的,所以无论什么时候有多个线程访问相同实例的可能时,就应该使用Hashtable,反之使用HashMap。非线程安全的数据结构能带来更好的性能。如果在将来有一种可能你需要按顺序获得键值对的方

33、案时,HashMap是一个很好的选择,因为有HashMap的一个子类 LinkedHashMap。所以如果你想可预测的按顺序迭代(默认按插入的顺序),你可以很方便用LinkedHashMap替换HashMap。反观要是使用的Hashtable就没那么简单了。同时如果有多个线程访问HashMap,Collections.synchronizedMap()可以代替,总的来说HashMap更灵活。(10)、为什么Vector类认为是废弃的或者是非官方地不推荐使用?或者说为什么我们应该一直使用ArrayList而不是Vector你应该使用ArrayList而不是Vector是因为默认情况下你是非同步访

34、问的,Vector同步了每个方法,你几乎从不要那样做,通常有想要同步的是整个操作序列。同步单个的操作也不安全(如果你迭代一个Vector,你还是要加锁,以避免其它线程在同一时刻改变集合).而且效率更慢。当然同样有锁的开销即使你不需要,这是个很糟糕的方法在默认情况下同步访问。你可以一直使用Collections.sychronizedList来装饰一个集合。事实上Vector结合了“可变数组”的集合和同步每个操作的实现。这是另外一个设计上的缺陷。Vector还有些遗留的方法在枚举和元素获取的方法,这些方法不同于List接口,如果这些方法在代码中程序员更趋向于想用它。尽管枚举速度更快,但是他们不能

35、检查如果集合在迭代的时候修改了,这样将导致问题。尽管以上诸多原因,oracle也从没宣称过要废弃Vector。8、Socket通信过程:10、查询、插入、删除等几种情况,分别选用ArrayList、LinkList、Vector哪一个合适?ArrayList底层使用的是数组数据结构,因为数组有索引(角标)所以ArrayList的查询速度快,而添加删除元素速度稍慢。因为,你每删除或者添加一个元素,你都要移动所添加或删除元素后面的所有数据,该集合是线程不同步的LinkedList底层使用的是链表数据结构,链表数据结构是没有索引的,当前元素只和他的前一个和后一个元素有关联就像一串珠子一样,该数据结构

36、的特点是,增加删除快,而查询比较慢,因为增加删除只需要找到当前元素,然后断掉当前元素与它前一个和后一个元素的关联即可,和数组比,链表不用重复大部分的数据移动工作,但是因为没有索引所以链表数据结构要一个一个的查询数据,所以LinkedList的查询速度稍慢Vector:底层使用的是数组数据结构,和ArrayList的功能相当,但是Vector是线程同步的,JDK已经对Vector的底层源码中可能出现同步的操作加上了同步锁,但是线程同步之后有弊端,那就是每当操作Vector集合,都会去判断同步锁,较为浪费系统资源。而我们完全可以使用ArrayList来代替Vector,如果需要同步代码,我们也可以

37、自己手动加上同步锁11. Java访问数据库的过程?JDBC连接数据库 创建一个以JDBC连接数据库的程序,包含7个步骤: (1)、加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机), 这通过类的静态方法forName(String className)实现。 例如: try /加载MySql的驱动类 Class.forName( catch(ClassNotFoundException e) 找不到驱动程序类 ,加载驱动失败!"); e.printStackTrace() ; 成功加载后,会将Driver类的实例注册到DriverM

38、anager类中。 (2)、提供JDBC连接的URL 连接URL定义了连接数据库时的协议、子协议、数据源标识。 书写形式:协议:子协议:数据源标识 协议:在JDBC中总是以jdbc开始 子协议:是桥连接的驱动程序或是数据库管理系统名称。 数据源标识:标记找到数据库来源的地址与连接端口。 例如:(MySql的连接URL) jdbc:mysql: /localhost:3306/test?useUnicode=true&characterEncoding=gbk ; useUnicode=true:表示使用Unicode字符集。如果characterEncoding设置为 gb2312或G

39、BK,本参数必须设置为true 。characterEncoding=gbk:字符编码方式。 (3)、创建数据库的连接 要连接数据库,需要向请求并获得Connection对象, 该对象就代表一个数据库的连接。 使用DriverManager的getConnectin(String url , String username , String password )方法传入指定的欲连接的数据库的路径、数据库的用户名和 密码来获得。 例如: /连接MySql数据库,用户名和密码都是root String url = "jdbc:mysql:/localhost:3306/test"

40、; ; String username = "root" ; String password = "root" ; try Connection con = DriverManager.getConnection(url , username , password ) ; catch(SQLException se) 数据库连接失败!"); se.printStackTrace() ; (4)、创建一个Statement 要执行SQL语句,必须获得实例,Statement实例分为以下3 种类型: 执行静态SQL语句。通常通过Statement实

41、例实现。 执行动态SQL语句。通常通过PreparedStatement实例实现。 执行数据库存储过程。通常通过CallableStatement实例实现。 具体的实现方式: Statement stmt = con.createStatement() ; PreparedStatement pstmt = con.prepareStatement(sql) ; CallableStatement cstmt = con.prepareCall("CALL demoSp(? , ?)") ; (5)、执行SQL语句 Statement接口提供了三种执行SQL语句的方法:ex

42、ecuteQuery 、executeUpdate 和execute ResultSet executeQuery(String sqlString):执行查询数据库的SQL语句 ,返回一个结果集(ResultSet)对象。 int executeUpdate(String sqlString):用于执行INSERT、UPDATE或 DELETE语句以及SQL DDL语句,如:CREATE TABLE和DROP TABLE等 execute(sqlString):用于执行返回多个结果集、多个更新计数或二者组合的 语句。 具体实现的代码: ResultSet rs = stmt.executeQ

43、uery("SELECT * FROM .") ; int rows = stmt.executeUpdate("INSERT INTO .") ; boolean flag = stmt.execute(String sql) ; (6)、处理结果 两种情况: 执行更新返回的是本次操作影响到的记录数。 执行查询返回的结果是一个ResultSet对象。 ResultSet包含符合SQL语句中条件的所有行,并且它通过一套get方法提供了对这些 行中数据的访问。 使用结果集(ResultSet)对象的访问方法获取数据: while(rs.next() Str

44、ing name = rs.getString("name") ; String pass = rs.getString(1) ; / 此方法比较高效 (列是从左到右编号的,并且从列1开始) (7)、关闭JDBC对象 操作完成以后要把所有使用的JDBC对象全都关闭,以释放JDBC资源,关闭顺序和声 明顺序相反: 关闭记录集 关闭声明 关闭连接对象 if(rs != null) / 关闭记录集 try rs.close() ; catch(SQLException e) e.printStackTrace() ; if(stmt != null) / 关闭声明 try stm

45、t.close() ; catch(SQLException e) e.printStackTrace() ; if(conn != null) / 关闭连接对象 try conn.close() ; catch(SQLException e) e.printStackTrace() ; 11、数据库索引什么是索引?数据库索引好比是一本书前面的目录,能加快数据库的查询速度。例如这样一个查询:select * from table1 where id=44。如果没有索引,必须遍历整个表,直到ID等于44的这一行被找到为止;有了索引之后(必须是在ID这一列上建立的索引),直接在索引里面找 44(也

46、就是在ID这一列找),就可以得知这一行的位置,也就是找到了这一行。可见,索引是用来定位的。索引分为聚簇索引和非聚簇索引两种,聚簇索引 是按照数据存放的物理位置为顺序的,而非聚簇索引就不一样了;聚簇索引能提高多行检索的速度,而非聚簇索引对于单行的检索很快。建立索引的目的是加快对表中记录的查找或排序。为表设置索引要付出代价的:一是增加了数据库的存储空间,二是在插入和修改数据时要花费较多的时间(因为索引也要随之变动)。为什么要创建索引?创建索引可以大大提高系统的性能。第一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。第二,可以大大加快数据的检索速度,这也是创建索引的最主要的原因。第三,

47、可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。第四,在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。第五,通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。也许会有人要问:增加索引有如此多的优点,为什么不对表中的每一个列创建一个索引呢?因为,增加索引也有许多不利的方面。第一,创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。第二,索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。第三,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护

48、,这样就降低了数据的维护速度。在哪建索引?索引是建立在数据库表中的某些列的上面。在创建索引的时候,应该考虑在哪些列上可以创建索引,在哪些列上不能创建索引。一般来说,应该在这些列上创建索引:(1)在经常需要搜索的列上,可以加快搜索的速度;(2).在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;(3)在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;(4).在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;(5).在经常使用在WHERE子句中的列上

49、面创建索引,加快条件的判断速度。对于有些列不应该创建索引。一般来说,不应该创建索引的的这些列具有下列特点:第一,对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。第二,对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。第三,对于那些定义为text, image和bit数据类型的列不应该增

50、加索引。这是因为,这些列的数据量要么相当大,要么取值很少,不利于使用索引。第四,当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改操作远远多于检索操作时,不应该创建索引。索引的数据结构:B-tree,B是balance,一般用于数据库的索引。使用B-tree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度。而B+tree是B-tree的一个变种,大名鼎鼎的MySQL就普遍使用B+tree实现其索引结构。插入(insert)操作:插入一个元素

51、时,首先在B-tree中是否存在,如果不存在,即在叶子结点处结束,然后在叶子结点中插入该新的元素,注意:如果叶子结点空间足够,这里需要向右移动该叶子结点中大于新插入关键字的元素,如果空间满了以致没有足够的空间去添加新的元素,则将该结点进行“分裂”,将一半数量的关键字元素分裂到新的其相邻右结点中,中间关键字元素上移到父结点中(当然,如果父结点空间满了,也同样需要“分裂”操作),而且当结点中关键元素向右移动了,相关的指针也需要向右移。如果在根结点插入新元素,空间满了,则进行分裂操作,这样原来的根结点中的中间关键字元素向上移动到新的根结点中,因此导致树的高度增加一层。删除(delete)操作:首先查

52、找B-tree中需删除的元素,如果该元素在B-tree中存在,则将该元素在其结点中进行删除,如果删除该元素后,首先判断该元素是否有左右孩子结点,如果有,则上移孩子结点中的某相近元素到父节点中,然后是移动之后的情况;如果没有,直接删除后,移动之后的情况.。删除元素,移动相应元素之后,如果某结点中元素数目小于ceil(m/2)-1,则需要看其某相邻兄弟结点是否丰满(结点中元素个数大于ceil(m/2)-1),如果丰满,则向父节点借一个元素来满足条件;如果其相邻兄弟都刚脱贫,即借了之后其结点数目小于ceil(m/2)-1,则该结点与其相邻的某一兄弟结点进行“合并”成一个结点,以此来满足条件。下面结合

53、例子详细讲解mysql中索引的使用索引是快速搜索的关键。MySQL索引的建立对于MySQL的高效运行是很重要的。下面介绍几种常见的MySQL索引类型。在数据库表中,对字段建立索引可以大大提高查询速度。假如我们创建了一个 mytable表:CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL ); 我们随机向里面插入了10000条记录,其中有一条:5555, admin。在查找username="admin"的记录 SELECT * FROM mytable WHERE username=&#

54、39;admin'时,如果在username上已经建立了索引,MySQL无须任何扫描,即准确可找到该记录。相反,MySQL会扫描所有记录,即要查询10000条记录。索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索包含多个列。MySQL索引类型包括:(1)普通索引这是最基本的索引,它没有任何限制。它有以下几种创建方式:创建索引CREATE INDEX indexName ON mytable(username(length); 如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和T

55、EXT类型,必须指定 length,下同。修改表结构ALTER mytable ADD INDEX indexName ON (username(length)创建表的时候直接指定CREATE TABLE mytable( ID INT NOT NULL, username VARCHAR(16) NOT NULL, INDEX indexName (username(length) ); 删除索引的语法:DROP INDEX indexName ON mytable;(2)唯一索引它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:创建索引CREATE UNIQUE INDEX indexName

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论