zoukankan      html  css  js  c++  java
  • java基础知识(二)

    5、字符串与数组

    5.1、字符串创建于存储的机制是什么

    字符串的声明和初始化主要有以下两种情况:

          1:对于String s1 = new String("abc")语句与String s2 = new String("abc")语句,存在两个引用对象s1,s2,两个内容相同的字符串对象“abc”,它们在内存中的地址是不一样的。只要用到new总会生成新的对象。

          2:对于String s1 = "abc"与String s2 = "abc"语句,在JVM中存在着一个字符串池,其中保存着很多String对象,并且可以被共享使用,s1,s2引用的是同一个常量池的对象。由于String的实现采用了Flyweight的设计模式,当创建一个字符串常量时,例如String s = "abc",会首先在字符串常量池中差最后啊是否已有相同的字符串被定义,其判断依据是String类equals(Object obj)方法的返回值。若已经定义,则直接获取对其的引用,此时不需要创建新的对象;若没有定义,则首先创建这个对象,然后把它加入到字符串池中,再将它的引用返回。由于String是不可变类,一旦创建好了就不能被修改,因此String对象可以被共享而且不会导致程序的混乱。

    5.2、“==”、equals和HashCode有什么区别

          1:“==”运算符用来比较两个变量的值是否相等。该运算符用于比较变量对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能使用“==”运算符。

          2:equals是Object类提供的方法之一。每一个java类都继承自Object类,所以每一个对象都具有equals这个方法。Object类中定义的equals(Object)方法是直接使用“==”运算符比较的两个对象,所以在没有覆盖equals(Object)方法的情况下,equals(Object)与“==”运算符一样,比较的是引用。

          相比“==”运算符,equals(Object)方法的特殊之处就在于它可以被覆盖,所以可以通过覆盖的方法让他不是比较引用而是比较数据内容,例如String类的equals方法是用于比较两个独立对象的内容是否相同,即堆中的内容是否相同。

          3:HashCode()方法是从Object类中继承过来的。它返回对象在内存中地址转换成的一个int值,所以如果没有重写hashcode()方法,任何对象的hashCode()方法都是不相等的。

          hashCode方法与equals方法的关系如下:如果x.equals(y)返回true,那么调用这两个对象中任一个对象的hashCode方法都必须产生同样的整数结果。如果返回false,那么x和y的hashCode方法的返回值可能相等也可能不相等。反之,hashCode方法的返回值不相等一定可以退出equals方法的返回值也不相等,而hashCode方法返回值相等,equals方法返回值有可能相等也可能不同。

    5.3、String、StringBuffer、StringBuilder和StringTokenizer有什么区别

          java语言有四个类可以对字符或字符串进行操作,它们分别是Character、String、StringBuffer和StringTokenizer,其中character用于对单个字符的操作,string用于字符串操作,属于不可变类,StringBuffer也是用于字符串操作,不同之处是stringbuffer属于可变类。

          string是不可变类,也就是说string对象一旦被创建,其值将不能被改变,而StringBuffer是可变类,当对象被创建后仍然可以对其值进行修改。StringBuffer只能使用构造函数(StringBuffer s = new StringBuffer(“Hello”))的方式来初始化。

          StringBuilder也是可以被修改的字符串,它与StringBuffer类似,都是字符串缓冲区,但StringBuilder不是线程安全的。如果只是在单线程中使用字符串缓冲区,那么StringBuilder的效率会高些。因此在只有单线程访问时可以使用StringBuilder,当有多个线程访问时,最好使用StringBuffer。因为StringBuffer必要时可以对这些方法进行同步,所以任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。StringTokenizer是用来分割字符串的工具类。

    6、异常处理

    6.1、finally块中的代码是什么时候被执行

          在java语言的异常处理中,finally块的作用是为了保证无论出现什么情况,finally块里的代码一定会被执行。由于程序执行return就意味着结束对当前函数的调用并跳出这个函数体,因此任何语句要执行都只能在return之前执行(除非碰到exit函数),因此finally块里的代码也是在return前执行的。此外,try-finally或者catch-finally中都有return,那么finally块中的return语句将会覆盖别处的return语句,最终返回到调用者那里的是finally中return的值。

    6.2、异常处理的原理是什么

          异常是指程序运行时(非编译时)所发生的非正常情况或错误,当程序违反了语义规则时,JVM就会将出现的错误表示为一个异常并抛出。这个异常可以在catch程序块中进行补货,然后进行处理。而异常处理的目的则是为了提高程序的安全性和鲁棒性。

          java语言把异常作为对象来处理,并定义了一个基类作为所有异常的父类。在java API中,已经定义了许多异常类,这些异常类分为Error(错误)和Exception(异常)两大类。

          违反语义规则包括两种情况:一种是Java类库内置的语义检查例如当数组下标越界时会引发IndexOutOfBoundsException,当访问null对象时,会引发NullPointerException;另一种情况是Java允许开发人员扩展这种语义检查,开发人员可以创建自己的异常类(所有异常都是Java.lang.Throwable的子类),并自由选择在何时用throw关键字抛出异常。

    6.3、运行时异常和普通异常有什么区别

          java提供了两种错误的异常类,分别是错误和异常,且他们有共同的父类——Throwable。Error表示程序在运行期间出现了非常严重的错误,并且该错误是不可恢复的,由于这属于JVM层次的严重错误,因此这种错误是会导致程序终止执行的。Exception表示可恢复的异常,是编译器可以捕捉到的。它包含两种类型:检查异常和运行时异常。

          检查异常是在程序中最常碰到的异常。所有继承自Exception并且不是运行时异常的异常都是检查异常,比如最常见的IO异常和SQL异常。这种异常都发生在编译阶段,java编译器强调程序去捕获此类异常,即把可能会出现这些异常的代码放到try块中,把对异常处理的代码放到catch块中。这种异常通常在以下情况中使用:异常的发生并不会导致程序出错,进行处理后可以继续执行后续的操作,例如当连接数据库失败后可以重新连接后进行后续操作。程序依赖于不可靠的外部条件,例如系统IO。

          运行时异常不同于检查异常,编译器没有强制对其进行补货并处理。如果不对这些异常进行处理,当出现这种异常时,会由JVM来处理,例如NullPointerException异常,他就是运行时异常。最常见的还有类型转换异常,数组越界异常,数组存储异常,缓冲区溢出异常,算术异常等。出现运行时异常后,系统会把异常一致往上层抛出,知道遇到处理代码为止,若没有处理块,则抛到最上层;如果是多线程则用Thread.run()方法抛出,如果是单线程就用main()方法抛出。抛出之后,如果是单线程那么这个线程也就退出了,如果是主程序抛出的异常,那么整个程序也就退出啦。所以如果不对运行时异常进行处理,后果是非常严重的,一旦发生,要么是线程终止,要么是主程序终止。

    7、输入输出流

    7.1、javaIO流实现机制是什么

          在JAVA语言中,输入和输出都被称为抽象的流,流可以被看做一组有序的字节集合,即数据在两设备之间的传输。流的本质是数据传输,根据处理数据类型的不同,流可以分为两大类:字节流和字符流。字节流以8bit为单位,字符流以16bit为单位。字节流和字符流之间最主要的区别是:字节流在处理输入输出时不会用到缓存,而字符流用到了缓存。

    7.2、java socket是什么

          网络上的两个程序通过一个双向的通信连接来实现数据的交换,这个双向链路的一端称为一个socket。socket也称为套接字,可以用来实现不同虚拟机或不同计算机之间的通信,在java语言中,socket可以分为两种类型:面向连接的socket通信协议(TCP)和面向无连接的socket协议(UDP)。任何一个socket都是由IP地址和端口号唯一确定的。

    7.3、java NIO 是什么

          在非阻塞(Nonblocking)出现之前,java是通过传统的socket来实现基本的网络通信功能的。

          NIO通过selector、channel和buffer来实现非阻塞的IO操作。NIO非阻塞的实现主要采用了Reactor(反应器)设计模式,这个设计模式与Observer(观察者)设计模式类似,只不过Observer设计模式只能处理一个事件源,而Reactor可以用来处理多个事件源。

       NIO在网络编程中有着非常重要的作用,与传统的socket方式相比,由于NIO采用了非阻塞的方式,在处理大量并发请求时,使用NIO要比使用传统socket效率高出很多。

    7.4、什么是java序列化

          java提供了两种对象持久化的方式,分别是序列化和外部序列化。

          1、序列化:在分布式环境下,当进行远程通信时,无论是何种类型的数据,都会以二进制序列的方式在网络上传送。序列化是一种将对象以一连串的字节描述的过程,用于解决在对对象流进行读写操作时所引发的问题。序列化可以将对象的状态写在流里进行网络传输,或者保存到文件、数据库等系统里,并在需要时把该流读取出来重新构造一个相同的对象。所有要实现序列化的类都必须实现Serializable接口,Serializable接口位于java.lang包中,它里面没有包含任何方法。使用一个输出流来构造一个ObjectOutputStream对象,紧接着,使用该对象的writeObject方法就可以将obj对象写出,要恢复时可以使用其对应的输入流。

          由于序列化的使用会影响系统的性能,因此如果不是必须要使用序列化,应尽可能不要使用序列化,在以下情况下使用:需要通过网络来发送对象,或对象的状态需要被持久化到数据库或文件中。序列化能实现深复制,即可以复制引用的对象。

          与序列化相对的是反序列化,它将流转换为对象。

          2、外部序列化

          外部序列化与序列化的主要区别在于序列化是内置的API,只需要实现Serializable接口,开发人员不需要编写任何代码就可以实现对象的序列化,而是用外部序列化时,Externalizable接口中的读写方法必须有开发人员来实现。因此与实现Serializable接口的方法相比,使用Externalizable编写程序的难读更大,但是由于把控制权交给了开发人员,在编程时有更多的灵活性,对需要持久化的那些属性可以进行控制,可能会提高性能。

    8、java平台与内存管理

    8.1、JVM加载class文件的原理机制是什么

          java语言是一种具有动态性的解释型语言,类只有被加载到JVM中后才能运行。当运行指定程序时,JVM会将编译生成的.class文件按照需求和一定的规则加载到内存中,并组织成一个完整的java应用程序。这个过程是由类加载器完成的,具体来说就是由ClassLoader和它的子类来实现的。类加载器本身也是一个类,其实质是把类文件从硬盘读到内存中。

          类的加载方式分为隐式加载和显式加载两种。隐式加载指的是程序在使用new等方式创建对象时会隐式的调用类的加载器把对应的类加载到JVM中。显式加载指的是通过直接调用class.forName()方法来吧所需的类加载到JVM中。

    8.2、垃圾回收

          垃圾回收在java语言中是一个非常重要的概念,它的主要作用是回收程序不在使用的内存。具体而言,垃圾回收期主要负责完成三项任务:分配内存、确保被引用对象的内存不被错误的回收以及回收不在被引用的对象的内存空间。

    9、容器

    9.1、java Collection框架是什么

          java Collection框架中包含了大量集合接口以及这些接口的实现类和操作它们的算法,具体而言,主要提供了List、queue、set、stack和map等数据结构。其中,List、queue、set、stack都继承自collection接口。

    9.2、ArrayList、Vector、LinkedList有什么区别 

          ArrayList与Vector之间最大的区别是同步的使用,没有一个ArrayList的方法是同步的,而vector的绝大多数方法是直接或间接同步的,所以Vector方法是线程安全的,ArrayList不是线程安全的。正是由于Vector提供了线程安全的机制,其性能上也要略逊于ArrayList。

          LinkedList是采用双向列表实现的,对数据的索引需要从列表头开始遍历,因此用于随机访问则效率较低,但是插入元素时不需要对数据进行移动,因此插入效率较高。同时,LinkedList是非线程安全的容器。

    9.3、HashMap、Hashtable、TreeMap和WeakHashMap有哪些区别

          HashMap是一个最常用的Map,他根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。由于HashMap和Hashtable都采用了hash方法进行索引,因此二者具有很多相似之处,它们的主要区别有:

          1:HashMap是Hashtable的轻量级实现(非线程安全的实现),它们都完成了map接口,主要区别在于HashMap允许空键值(最多只允许一条记录的键为空,不允许多条记录的键为空),而Hashtable不允许。

          2:HashMap把Hashtable的contains方法去掉了,改成了containsvalue和containsKey,因为contains方法容易让人产生误解。Hashtable继承自directory类,而HashMap是java1.2引进的Map interface的一个实现。

          3:Hashtable的方法是线程安全的,而HashMap不支持线程的同步,所以它不是线程安全的。在多个线程访问Hashtable时,不需要开发人员对它进行同步,而对于HashMap,开发人员必须提供额外的同步机制。所以就效率而言,HashMap可能高于Hashtable。

          4:Hashtable使用Enumeration,HashMap使用Iterator。

          5:Hashtable和HashMap采用的hash/rehash算法都几乎一样,所以性能不会有很大差异。

          6:在Hashtable中,hash数组默认大小是11,增加的方式是old*1+1,在HashMap中,hash数组的默认大小是16,而且一定是2的指数。

          7:hash值的使用不同,Hashtable直接使用对象的hashcode。

          由于TreeMap实现了sortmap接口,能够把它保存的记录根据键排序,因此,取出来的是排序后的键值对,如果需要按自然排序或自定义顺序遍历键,那么treemap会更好LinkedHashMap是HashMap的一个子类,如果需要输出的顺序与输入的顺序相同,可以使用它,他还可以根据读取顺序来排列。

          weakhashmap与HashMap类似,二者的不同之处在于weakhashmap中key采用的是“弱引用”的方式,只要weakhashmap中的key不再被外部引用,他就可以被垃圾回收器回收。而HashMap中的key采用的是强引用的方式,当HashMap中的key没有被外部引用时,只有在这个key从HashMap中删除后才可以被垃圾回收器回收。

    9.4、Collection和Collections有什么区别

          Collection是一个集合接口。他提供了对集合对象进行基本操作的通用接口方法。实现该接口的类主要有List和set,该接口的设计目标是为各种具体的集合提供最大化的统一的操作方式。

          Collections是针对集合类的一个包装类,它提供了一系列静态方法以实现对各种集合的搜索、排序、线程安全化等操作,其中大多数方法都是用来处理线性表。Collections类不能实例化,如同一个工具类,服务于Collection框架。若在使用Collections的方法时,对应的Collection的对象为null,则这些方法都会抛出NullPointerException。

    10、多线程

    10.1、多线程的便利之处

          1、使用多线程可以减少程序运行的时间;2、与进程相比,线程的创建和切换开销更小;3、多CPU或多核计算机本身就具有执行多线程的能力,如果使用单个线程,将无法重复利用计算机资源,造成资源的巨大浪费;4、使用多线程能简化程序的结构,使程序便于理解和维护。

    10.2如何实现java多线程

          1、继承Thread类,重写run()方法

          2、实现Runnable()接口,并实现该接口的run()方法

          3、实现Callable接口,重写call()方法

    10.3、多线程同步的实现方法有哪些

          1、synchronized关键字:在java语言中,每个对象都有一个对象锁与之相关联,该锁表明对象在任何时候只允许被一个线程所拥有,当一个线程调用对象的一段synchronized代码时,需要先获得这个锁,然后去执行相应的代码,执行结束后释放锁。synchronized关键字主要有两种用法,synchronized方法和synchronized块,此处该关键字还可以作用于静态方法、类或某个实例,但这都对程序的效率有很大的影响。

          2、wait()方法和notify()方法:在synchronized代码被执行期间线程可以调用对象的wait()方法,释放对象锁,进入等待状态,并且可以调用notify()方法或notifyAll()方法通知正在等待的其他进程。notify()方法用来唤醒一个线程并允许它获得锁,notifyAll()方法唤醒所有等待这个对象的线程并允许它们去获得锁。

          3、Lock:

          lock():以阻塞的方式获取锁,也就是说如果获取到了锁,立即返回;如果别的线程持有锁,当前线程等待,直到获取锁后返回。

          trylock():以非阻塞的方式获取锁。只是尝试性的去获取一下锁,如果获取到了锁,立即返回true,否则立即返回false。

          tryLock(long timeout,TimeUnit unit):如果获取了锁立即返回true,否则会等待参数给定的时间单元,在等待的过程中,如果获取了锁,就返回true,如果等待超时返回false。

          lockInterruptibly():如果获取了锁,立即返回;如果没有获取锁,当前线程处于休眠状态直到获得锁,或者当前线程被别的线程中断。

    10.4、sleep与wait方法有什么区别

    1、原理不同:sleep方法是Thread类的静态方法,是线程用来控制自身流程的。而wait方法是Object类的方法,用于线程间的通信,这个方法会使当前拥有该对象锁的进程等待,直到其他线程调用notify方法是才醒来,不过开发人员也可以给他指定一个时间自动醒来。

    2、对锁的处理机制不同:由于sleep方法的主要作用是让线程暂停执行一段时间,时间一到自动恢复,不涉及线程间的通信,因此调用sleep方法不会释放锁。而wait方法不同,调用它后,线程会释放掉它所占用的锁,从而使线程所在对象中的其他synchronized数据可被别的线程使用。

    3、使用区域不同:由于wait方法的特殊意义,它必须放在同步控制方法或者同步语句块中使用,而sleep方法可以在任何地方使用。

    10.5、终止线程的方法有哪些

          在java语言中,可以使用stop和suspend方法来终止线程的执行。当用Thead.stop()来终止线程时,他会释放已经锁定的所有监视资源。如果当前任何一个受这些监视资源保护的对象处于一个不一致的状态,其他线程将会看到这个不一致的状态,这可能会导致程序执行的不确定性,并且这种问题很难被定位。调用suspend()方法很容易导致死锁。由于调用suspend()方法不会释放锁,这就会导致一个问题:如果用一个suspend挂起一个有锁的线程,那么在锁恢复之前将不会被释放。如果调用suspend方法,线程将试图取得相同的锁,程序就会发生死锁。

    10.6、synchronized与lock有什么异同

          java提供了两种锁机制来实现对某个共享资源的同步:synchronized和lock方法。其中,synchronized使用object对象本身的wait、notify和notifyAll调度机制,而lock可以用condition进行线程之间的调度,完成synchronized实现的所有功能。

    区别如下:

          1、用法不一样:在需要同步的对象中加入synchronized控制,synchronized既可以加在方法上,也可以加在特定代码块中,括号中表示需要锁的对象。而lock需要显式的指定起始位置和终止位置。synchronized是托管给jvm执行的,而lock的锁定是通过代码实现的,它有比synchronized更精确的线程语义。

          2、性能不一样:在JDK5中增加了一个Lock接口的实现类ReentrantLock。他不仅拥有和synchronized相同的并发性和内存语义,还多了锁投票、定时锁、等候和中断锁等。它们的性能在不同的情况下会有锁不同:在资源竞争不是很激烈的情况下,synchronized的性能要优于ReentrantLock,但是在资源竞争很激烈的情况下,synchronized的性能下降的非常快,而ReentrantLock的性能基本保持不变。

          3、锁机制不一样:synchronized获得锁和释放的方式都是在块结构中,当获取多个锁时,必须以相反的顺序释放,并且是自动解锁,不会因为出了异常而导致锁没有被释放从而引发死锁。而lock则需要开发人员手动去释放,并且必须在finally块中释放,否则会引起死锁问题的发生。此外,lock还提供了更强大的功能,它的tryLock方法可以采用非阻塞的方式去获取锁。

    10.7、什么是守护线程

          java提供了两种线程:守护线程和用户线程。守护线程又被称为服务进程、精灵线程或后台线程,是指在程序运行时在后台提供一种通用服务的线程,这种线程并不属于程序中不可或缺的一部分。通俗的讲,任何一个守护线程都是整个JVM中所有非守护线程的保姆。

          用户线程和守护线程几乎一样,唯一的不同之处就在于如果用户线程已经全部退出运行,只剩下守护线程存在了,JVM也就退出了。因为当所有非守护线程结束时,没有了被守护者,守护线程也就没工作可做了,也就没有继续运行程序的必要了,程序也就终止了,同时会杀死所有守护线程。

    10.8、join方法的作用是什么

          在java语言中,join方法的作用是让调用该方法的线程在执行完run方法后再执行join方法后面的代码。简单来说就是将两个线程合并,用于实现同步功能。

    11、java数据库操作

    11.1、如何通过JDBC访问数据库

          java数据库连接(JDBC)用于在java程序中实现数据库操作功能,他提供了执行SQL语句、访问各种数据库的方法,并为各种不同数据库提供统一的操作接口,java.sql包中包含了JDBC操作数据库的所有类。通过JDBC访问数据库一般有如下几个步骤:1、加载JDBC驱动器。将数据库的JDBC驱动加载到classpath中,在基于JavaEE的web应用开发过程中,通常要把目标数据库产品的JDBC驱动复制到WEB_INF/lib下。2、加载JDBC驱动,并将其注册到DriverManager中。一般使用反射Class.forName(String driveName)。3、建立数据库连接,取得connection对象。一般通过DriverManager.getConnection(url,username,passwd)方法实现。4、建立Statement对象或是PreparedStatement对象。5、执行SQL语句。6、访问结果集ResultSet对象。7、依次将ResultSet、Statement、PreparedStatement、Connection对象关闭,释放掉所占用资源。

    11.2、JDBC处理事务采用什么方法

          一个事务是由一条或多条对数据库操作的SQL语句所组成的一个不可分割的工作单元,只有当事务中的所有操作都正常执行完了,整个事务才会被提交给数据库。在JDBC中,一般是通过commit方法或rollback方法来结束事务的操作。其中commit方法表示完成对事务的提交,rollback表示完成事务回滚,多用于在处理事务的过程中出现了异常的情况,这两种方法都位于java.sql.connection类中。一般而言,事务默认操作是自动提交,即操作成功后,系统将自动调用commit方法,否则将调用rollback方法。

           当然在JDBC中也可以通过调用setAutoCommit(false)方法来禁止自动提交,然后就可以把多个数据库操作的表达式作为一个事务,在操作完成后调用commit方法实现整体提交,如果其中一个表达式操作失败,就会抛出异常而不会调用commit方法。在这种情况下就可以在异常捕获的代码块中调用rollback实现回滚。通过此种方法可以保证对数据的多次操作后,数据仍然保持一致性。

    11.3、Class.forName作用是什么

          在java语言中,任何类只有在装载到JVM上才能运行。Class.forName方法的作用就是把类加载到JVM上,他会返回一个与大有给定字符串名的类或接口相关联的class对象,并且JVM会加载这个类,同时JVM会执行该类的静态代码段。

    11.4、Statement、PreparedStatement和CallableStatement有什么区别

          statement用来执行不带参数的简单SQL语句,并返回它所生成结果的对象,每次执行SQL语句时,数据库都会编译该SQL语句。

          PreparedStatement表示预编译的SQL语句的对象,用于执行带参数的预编译SQL语句。

          CallableStatement则提供了用来调用数据库中存储过程的接口,如果有输出参数要注册,说明是输出参数。

    11.5、getString与getObject方法有什么区别

          JDBC提供了getString、getInt和getData等方法从ResultSet中获取数据,当查询结果集中数据量较小时,不用考虑性能,使用这种方法完全能够满足需求,但是当查询结果集中的数据量非常大时则会抛出异常:OracleException未处理:...。而通常情况下,使用getObject方法就可以解决这个问题。

          getString或getInt方法在被调用时,程序会一次性的把数据都放到内存中,然后通过调用ResultSet的next和getString等方法来获取数据。当数据量大到内存中放不下的时候会抛出异常,而使用getObject方法就不会出现这种问题,因为数据不会一次性被读取到内存中,每次调用时会直接从数据库中去获取数据,因此使用这种方法不会因为数据量过大而出错。

    11.6、使用JDBC需要主要哪些问题

          在使用JDBC编程时,首先需要建立数据库的连接才能完成对数据库的访问,由于与数据库的连接是非常重要的资源。JDBC连接池提供了JDBC连接定义和数目有限的连接,如果连接数量不够,就需要长时间的等待。不正常关闭JDBC连接会导致等待回收无效的JDBC连接。只有正常的关闭和释放JDBC连接,JDBC资源才可以被快速的重用,从而使系统性能得到改善。因此在编程时,一定要保证释放不在使用的连接。

          一般来讲,在使用JDBC访问数据库时,createStatement和PreparedStatement最好放在循环外面,而且使用了这些statement后,需要及时关闭。最好是执行了一次executeQuery、executeUpdate等之后,如果不需要使用结果集(ResultSet)的数据,就马上将statement关闭。因为每次执行conn.createStatement()和conn.prepareStatement,实际上都相当于在数据库中打开一个cursor(游标),如果把对这两个方法的调用放在循环内,会一致不停的打开cursor。如果不能及时的关闭,会导致程序抛出异常。

    11.7、什么是JDO

          java数据对象(java data object)是一个用于存取某种数据仓库中的对象的标准化API,它使开发人员能够间接的访问数据库。

          JDO是JDBC的一个补充,他提供了透明的对象存储,因此对于开发人员来说,存储数据对象完全不需要额外的代码(例如JDBC API的使用)。这些繁琐的工作已经转移到JDO产品提供商身上,使开发人员解脱出来,从而集中时间和精力在业务逻辑上。另外,相较于JDBC,JDO更加灵活,更通用,它提供了到任何数据底层的存储功能。

    11.8、JDBC与Hibernate有什么区别

          Hibernate是JDBC的封装,采用配置文件的形式将数据库的连接参数写到XML文件中,至于对数据库的访问还是通过JDBC来完成的。

          Hibernate是一个持久层框架,它将表的信息映射到XML文件中,再从XML文件映射到相应的持久化类中,这样可以使用Hibernate独特的查询语言了。

  • 相关阅读:
    Docker Swarm(十)Portainer 集群可视化管理
    Docker Swarm(九)资源限制
    Docker Swarm(八)滚动更新、回滚服务
    Docker Swarm(七)Scale 扩(缩)容服务
    Docker Swarm(六)Label 节点标签与服务约束
    Docker Swarm(五)Config 配置管理
    select样式调整
    在VS2008和VS2010中禁用Visual Assist X
    解决IE与FF 中 input focus 光标移动在最后的方案
    Office Web APP预览如何去掉顶部版权标志“Microsoft Office Web Apps”
  • 原文地址:https://www.cnblogs.com/strawqqhat/p/10602284.html
Copyright © 2011-2022 走看看