Java面试题全集(上)面试必看日程百行

2、访问修饰符public,private,protected,以及不写(默认)时的区别?答:

修饰符|当前类|同包|子类|其他包public√√√√protected√√√×default√√××private√×××类的成员不写访问修饰时默认为default。默认对于同一个包中的其他类相当于公开(public),对于不是同一个包中的其他类相当于私有(private)。受保护(protected)对子类相当于公开,对不是同一包中的没有父子关系的类相当于私有。Java中,外部类的修饰符只能是public或默认,类的成员(包括内部类)的修饰符可以是以上四种。

3、String是最基本的数据类型吗?答:不是。Java中的基本数据类型只有8个:byte、short、int、long、float、double、char、boolean;除了基本类型(primitivetype),剩下的都是引用类型(referencetype),Java5以后引入的枚举类型也算是一种比较特殊的引用类型。

4、floatf=3.4;是否正确?答:不正确。3.4是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失,因此需要强制类型转换floatf=(float)3.4;或者写成floatf=3.4F;。

5、shorts1=1;s1=s1+1;有错吗shorts1=1;s1+=1;有错吗?答:对于shorts1=1;s1=s1+1;由于1是int类型,因此s1+1运算结果也是int型,需要强制转换类型才能赋值给short型。而shorts1=1;s1+=1;可以正确编译,因为s1+=1;相当于s1=(short)(s1+1);其中有隐含的强制类型转换。

6、Java有没有goto?答:goto是Java中的保留字,在目前版本的Java中没有使用。(根据JamesGosling(Java之父)编写的《TheJavaProgrammingLanguage》一书的附录中给出了一个Java关键字列表,其中有goto和const,但是这两个是目前无法使用的关键字,因此有些地方将其称之为保留字,其实保留字这个词应该有更广泛的意义,因为熟悉C语言的程序员都知道,在系统类库中使用过的有特殊意义的单词或单词的组合都被视为保留字)

7、int和Integer有什么区别?答:Java是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入了基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java为每一个基本数据类型都引入了对应的包装类型(wrapperclass),int的包装类就是Integer,从Java5开始引入了自动装箱/拆箱机制,使得二者可以相互转换。Java为每个原始类型提供了包装类型:-原始类型:boolean,char,byte,short,int,long,float,double-包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double

1classAutoUnboxingTest{23publicstaticvoidmain(String[]args){4Integera=newInteger(3);5Integerb=3;//将3自动装箱成Integer类型6intc=3;7System.out.println(a==b);//false两个引用没有引用同一对象8System.out.println(a==c);//truea自动拆箱成int类型再和c比较9}10}最近还遇到一个面试题,也是和自动装箱和拆箱有点关系的,代码如下所示:

1publicclassTest03{23publicstaticvoidmain(String[]args){4Integerf1=100,f2=100,f3=150,f4=150;56System.out.println(f1==f2);7System.out.println(f3==f4);8}9}如果不明就里很容易认为两个输出要么都是true要么都是false。首先需要注意的是f1、f2、f3、f4四个变量都是Integer对象引用,所以下面的==运算比较的不是值而是引用。装箱的本质是什么呢?当我们给一个Integer对象赋一个int值的时候,会调用Integer类的静态方法valueOf,如果看看valueOf的源代码就知道发生了什么。

1publicstaticIntegervalueOf(inti){2if(i>=IntegerCache.low&&i<=IntegerCache.high)3returnIntegerCache.cache[i+(-IntegerCache.low)];4returnnewInteger(i);5}IntegerCache是Integer的内部类,其代码如下所示:

提醒:越是貌似简单的面试题其中的玄机就越多,需要面试者有相当深厚的功力。

补充:如果你熟悉JavaScript,那你可能更能感受到短路运算的强大,想成为JavaScript的高手就先从玩转短路运算开始吧。

9、解释内存中的栈(stack)、堆(heap)和方法区(methodarea)的用法。答:通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用JVM中的栈空间;而通过new关键字和构造器创建的对象则放在堆空间,堆是垃圾收集器管理的主要区域,由于现在的垃圾收集器都采用分代收集算法,所以堆空间还可以细分为新生代和老生代,再具体一点可以分为Eden、Survivor(又可分为FromSurvivor和ToSurvivor)、Tenured;方法区和堆都是各个线程共享的内存区域,用于存储已经被JVM加载的类信息、常量、静态变量、JIT编译器编译后的代码等数据;程序中的字面量(literal)如直接书写的100、"hello"和常量都是放在常量池中,常量池是方法区的一部分,。栈空间操作起来最快但是栈很小,通常大量的对象都是放在堆空间,栈和堆的大小都可以通过JVM的启动参数来进行调整,栈空间用光了会引发StackOverflowError,而堆和常量池空间不足则会引发OutOfMemoryError。

1Stringstr=newString("hello");上面的语句中变量str放在栈上,用new创建出来的字符串对象放在堆上,而"hello"这个字面量是放在方法区的。

补充1:较新版本的Java(从Java6的某个更新开始)中,由于JIT编译器的发展和"逃逸分析"技术的逐渐成熟,栈上分配、标量替换等优化技术使得对象一定分配在堆上这件事情已经变得不那么绝对了。

补充2:运行时常量池相当于Class文件常量池具有动态性,Java语言并不要求常量一定只有编译期间才能产生,运行期间也可以将新的常量放入池中,String类的intern()方法就是这样的。

看看下面代码的执行结果是什么并且比较一下Java7以前和以后的运行结果是否一致。

1Strings1=newStringBuilder("go")2.append("od").toString();3System.out.println(s1.intern()==s1);4Strings2=newStringBuilder("ja")5.append("va").toString();6System.out.println(s2.intern()==s2);10、Math.round(11.5)等于多少?Math.round(-11.5)等于多少?答:Math.round(11.5)的返回值是12,Math.round(-11.5)的返回值是-11。四舍五入的原理是在参数上加0.5然后进行下取整。

11、switch是否能作用在byte上,是否能作用在long上,是否能作用在String上?答:在Java5以前,switch(expr)中,expr只能是byte、short、char、int。从Java5开始,Java中引入了枚举类型,expr也可以是enum类型,从Java7开始,expr还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的。

12、用最有效率的方法计算2乘以8?答:2<<3(左移3位相当于乘以2的3次方,右移3位相当于除以2的3次方)。

补充:我们为编写的类重写hashCode方法时,可能会看到如下所示的代码,其实我们不太理解为什么要使用这样的乘法运算来产生哈希码(散列码),而且为什么这个数是个素数,为什么通常选择31这个数?前两个问题的答案你可以自己百度一下,选择31是因为可以用移位和减法运算来代替乘法,从而得到更好的性能。说到这里你可能已经想到了:31*num等价于(num<<5)-num,左移5位相当于乘以2的5次方再减去自身就相当于乘以31,现在的VM都能自动完成这个优化。

14、在Java中,如何跳出当前的多重嵌套循环?答:在最外层循环前加一个标记如A,然后用breakA;可以跳出多重循环。(Java中支持带标签的break和continue语句,作用有点类似于C和C++中的goto语句,但是就像要避免使用goto一样,应该避免使用带标签的break和continue,因为它不会让你的程序变得更优雅,很多时候甚至有相反的作用,所以这种语法其实不知道更好)

15、构造器(constructor)是否可被重写(override)?答:构造器不能被继承,因此不能被重写,但可以被重载。

16、两个对象值相同(x.equals(y)==true),但却可有不同的hashcode,这句话对不对?答:不对,如果两个对象x和y满足x.equals(y)==true,它们的哈希码(hashcode)应当相同。Java对于eqauls方法和hashCode方法是这样规定的:(1)如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同;(2)如果两个对象的hashCode相同,它们并不一定相同。当然,你未必要按照要求去做,但是如果你违背了上述原则就会发现在使用容器时,相同的对象可以出现在Set集合中,同时增加新元素的效率会大大下降(对于使用哈希存储的系统,如果哈希码频繁的冲突将会造成存取性能急剧下降)。

补充:关于equals和hashCode方法,很多Java程序都知道,但很多人也就是仅仅知道而已,在JoshuaBloch的大作《EffectiveJava》(很多软件公司,《EffectiveJava》、《Java编程思想》以及《重构:改善既有代码质量》是Java程序员必看书籍,如果你还没看过,那就赶紧去亚马逊买一本吧)中是这样介绍equals方法的:首先equals方法必须满足自反性(x.equals(x)必须返回true)、对称性(x.equals(y)返回true时,y.equals(x)也必须返回true)、传递性(x.equals(y)和y.equals(z)都返回true时,x.equals(z)也必须返回true)和一致性(当x和y引用的对象信息没有被修改时,多次调用x.equals(y)应该得到同样的返回值),而且对于任何非null值的引用x,x.equals(null)必须返回false。实现高质量的equals方法的诀窍包括:1.使用==操作符检查"参数是否为这个对象的引用";2.使用instanceof操作符检查"参数是否为正确的类型";3.对于类中的关键属性,检查参数传入对象的属性是否与之相匹配;4.编写完equals方法后,问自己它是否满足对称性、传递性、一致性;5.重写equals时总是要重写hashCode;6.不要将equals方法参数中的Object对象替换为其他的类型,在重写时不要忘掉@Override注解。

17、是否可以继承String类?答:String类是final类,不可以被继承。

补充:继承String本身就是一个错误的行为,对String类型最好的重用方式是关联关系(Has-A)和依赖关系(Use-A)而不是继承关系(Is-A)。

18、当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?答:是值传递。Java语言的方法调用只支持参数的值传递。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象的属性可以在被调用过程中被改变,但对对象引用的改变是不会影响到调用者的。C++和C#中可以通过传引用或传输出参数来改变传入的参数的值。在C#中可以编写如下所示的代码,但是在Java中却做不到。

1usingSystem;23namespaceCS01{45classProgram{6publicstaticvoidswap(refintx,refinty){7inttemp=x;8x=y;9y=temp;10}1112publicstaticvoidMain(string[]args){13inta=5,b=10;14swap(refa,refb);15//a=10,b=5;16Console.WriteLine("a={0},b={1}",a,b);17}18}19}说明:Java中没有传引用实在是非常的不方便,这一点在Java8中仍然没有得到改进,正是如此在Java编写的代码中才会出现大量的Wrapper类(将需要通过方法调用修改的引用置于一个Wrapper类中,再将Wrapper对象传入方法),这样的做法只会让代码变得臃肿,尤其是让从C和C++转型为Java程序员的开发者无法容忍。

19、String和StringBuilder、StringBuffer的区别?答:Java平台提供了两种类型的字符串:String和StringBuffer/StringBuilder,它们可以储存和操作字符串。其中String是只读字符串,也就意味着String引用的字符串内容是不能被改变的。而StringBuffer/StringBuilder类表示的字符串对象可以直接进行修改。StringBuilder是Java5中引入的,它和StringBuffer的方法完全相同,区别在于它是在单线程环境下使用的,因为它的所有方面都没有被synchronized修饰,因此它的效率也比StringBuffer要高。

面试题1-什么情况下用+运算符进行字符串连接比调用StringBuffer/StringBuilder对象的append方法连接字符串性能更好?

面试题2-请说出下面程序的输出。

1classStringEqualTest{23publicstaticvoidmain(String[]args){4Strings1="Programming";5Strings2=newString("Programming");6Strings3="Program";7Strings4="ming";8Strings5="Program"+"ming";9Strings6=s3+s4;10System.out.println(s1==s2);11System.out.println(s1==s5);12System.out.println(s1==s6);13System.out.println(s1==s6.intern());14System.out.println(s2==s2.intern());15}16}补充:解答上面的面试题需要清除两点:1.String对象的intern方法会得到字符串对象在常量池中对应的版本的引用(如果常量池中有一个字符串与String对象的equals结果是true),如果常量池中没有对应的字符串,则该字符串将被添加到常量池中,然后返回常量池中字符串的引用;2.字符串的+操作其本质是创建了StringBuilder对象进行append操作,然后将拼接后的StringBuilder对象用toString方法处理成String对象,这一点可以用javap-cStringEqualTest.class命令获得class文件对应的JVM字节码指令就可以看出来。

面试题:华为的面试题中曾经问过这样一个问题-"为什么不能根据返回类型来区分重载",快说出你的答案吧!

Bootstrap:一般用本地代码实现,负责加载JVM基础核心类库(rt.jar);Extension:从java.ext.dirs系统属性所指定的目录中加载类库,它的父加载器是Bootstrap;System:又叫应用类加载器,其父类是Extension。它是应用最广泛的类加载器。它从环境变量classpath或者系统属性java.class.path所指定的目录中记载类,是用户自定义加载器的默认父加载器。22、char型变量中能不能存贮一个中文汉字,为什么?答:char类型可以存储一个中文汉字,因为Java中使用的编码是Unicode(不选择任何特定的编码,直接使用字符在字符集中的编号,这是统一的唯一方法),一个char类型占2个字节(16比特),所以放一个中文是没问题的。

补充:使用Unicode意味着字符在JVM内部和外部有不同的表现形式,在JVM内部都是Unicode,当这个字符被从JVM内部转移到外部时(例如存入文件系统中),需要进行编码转换。所以Java中有字节流和字符流,以及在字符流和字节流之间进行转换的转换流,如InputStreamReader和OutputStreamReader,这两个类是字节流和字符流之间的适配器类,承担了编码转换的任务;对于C程序员来说,要完成这样的编码转换恐怕要依赖于union(联合体/共用体)共享内存的特征来实现了。

1classPokerTest{23publicstaticvoidmain(String[]args){4Pokerpoker=newPoker();5poker.shuffle();//洗牌6Poker.Cardc1=poker.deal(0);//发第一张牌7//对于非静态内部类Card8//只有通过其外部类Poker对象才能创建Card对象9Poker.Cardc2=poker.newCard("红心",1);//自己创建一张牌1011System.out.println(c1);//洗牌后的第一张12System.out.println(c2);//打印:红心A13}14}面试题-下面的代码哪些地方会产生编译错误?

1classOuter{23classInner{}45publicstaticvoidfoo(){newInner();}67publicvoidbar(){newInner();}89publicstaticvoidmain(String[]args){10newInner();11}12}注意:Java中非静态内部类对象的创建要依赖其外部类对象,上面的面试题中foo和main方法都是静态方法,静态方法中没有this,也就是说没有所谓的外部类对象,因此无法创建内部类对象,如果要在静态方法中创建内部类对象,可以这样做:

newOuter().newInner();

25、Java中会存在内存泄漏吗,请简单描述。答:理论上Java因为有垃圾回收机制(GC)不会存在内存泄露问题(这也是Java被广泛使用于服务器端编程的一个重要原因);然而在实际开发中,可能会存在无用但可达的对象,这些对象不能被GC回收,因此也会导致内存泄露的发生。例如Hibernate的Session(一级缓存)中的对象属于持久态,垃圾回收器是不会回收这些对象的,然而这些对象中可能存在无用的垃圾对象,如果不及时关闭(close)或清空(flush)一级缓存就可能导致内存泄露。下面例子中的代码也会导致内存泄露。

26、抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰?答:都不能。抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。本地方法是由本地代码(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。synchronized和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。

27、阐述静态变量和实例变量的区别。答:静态变量是被static修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,一个类不管创建多少个对象,静态变量在内存中有且仅有一个拷贝;实例变量必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。静态变量可以实现让多个对象共享内存。

补充:在Java开发中,上下文类和工具类中通常会有大量的静态成员。

28、是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?答:不可以,静态方法只能访问静态成员,因为非静态方法的调用要先创建对象,在调用静态方法时可能对象并没有被初始化。

29、如何实现对象克隆?答:有两种方式:1).实现Cloneable接口并重写Object类中的clone()方法;2).实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆,代码如下。

1importjava.io.ByteArrayInputStream;2importjava.io.ByteArrayOutputStream;3importjava.io.ObjectInputStream;4importjava.io.ObjectOutputStream;5importjava.io.Serializable;67publicclassMyUtil{89privateMyUtil(){10thrownewAssertionError();11}1213@SuppressWarnings("unchecked")14publicstaticTclone(Tobj)throwsException{15ByteArrayOutputStreambout=newByteArrayOutputStream();16ObjectOutputStreamoos=newObjectOutputStream(bout);17oos.writeObject(obj);1819ByteArrayInputStreambin=newByteArrayInputStream(bout.toByteArray());20ObjectInputStreamois=newObjectInputStream(bin);21return(T)ois.readObject();2223//说明:调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法没有任何意义24//这两个基于内存的流只要垃圾回收器清理对象就能够释放资源,这一点不同于对外部资源(如文件流)的释放25}26}下面是测试代码:

补充:垃圾回收机制有很多种,包括:分代复制垃圾回收、标记垃圾回收、增量垃圾回收等方式。标准的Java进程既有栈又有堆。栈保存了原始型局部变量,堆保存了要创建的对象。Java平台对堆内存回收和再利用的基本算法被称为标记和清除,但是Java对其进行了改进,采用“分代式垃圾收集”。这种方法会跟Java对象的生命周期将堆内存划分为不同的区域,在垃圾收集过程中,可能会将对象移动到不同区域:-伊甸园(Eden):这是对象最初诞生的区域,并且对大多数对象来说,这里是它们唯一存在过的区域。-幸存者乐园(Survivor):从伊甸园幸存下来的对象会被挪到这里。-终身颐养园(Tenured):这是足够老的幸存对象的归宿。年轻代收集(Minor-GC)过程是不会触及这个地方的。当年轻代收集不能把对象放进终身颐养园时,就会触发一次完全收集(Major-GC),这里可能还会牵扯到压缩,以便为大对象腾出足够的空间。

31、Strings=newString("xyz");创建了几个字符串对象?答:两个对象,一个是静态区的"xyz",一个是用new创建在堆上的对象。

32、接口是否可继承(extends)接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concreteclass)?答:接口可以继承接口,而且支持多重继承。抽象类可以实现(implements)接口,抽象类可继承具体类也可以继承抽象类。

33、一个".java"源文件中是否可以包含多个类(不是内部类)?有什么限制?答:可以,但一个源文件中最多只能有一个公开类(publicclass)而且文件名必须和公开类的类名完全保持一致。

34、AnonymousInnerClass(匿名内部类)是否可以继承其它类?是否可以实现接口?答:可以继承其他类或实现其他接口,在Swing编程和Android开发中常用此方式来实现事件监听和回调。

35、内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制?答:一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员。

36、Java中的final关键字有哪些用法?答:(1)修饰类:表示该类不能被继承;(2)修饰方法:表示方法不能被重写;(3)修饰变量:表示变量只能一次赋值以后值不能被修改(常量)。

37、指出下面程序的运行结果。

1classA{23static{4System.out.print("1");5}67publicA(){8System.out.print("2");9}10}1112classBextendsA{1314static{15System.out.print("a");16}1718publicB(){19System.out.print("b");20}21}2223publicclassHello{2425publicstaticvoidmain(String[]args){26Aab=newB();27ab=newB();28}2930}

答:执行结果:1a2b2b。创建对象时构造器的调用顺序是:先初始化静态成员,然后调用父类构造器,再初始化非静态成员,最后调用自身构造器。

提示:如果不能给出此题的正确答案,说明之前第21题Java类加载机制还没有完全理解,赶紧再看看吧。

38、数据类型之间的转换:-如何将字符串转换为基本数据类型?-如何将基本数据类型转换为字符串?答:-调用基本数据类型对应的包装类中的方法parseXXX(String)或valueOf(String)即可返回相应基本类型;-一种方法是将基本数据类型与空字符串("")连接(+)即可获得其所对应的字符串;另一种方法是调用String类中的valueOf()方法返回相应字符串

39、如何实现字符串的反转及替换?答:方法很多,可以自己写实现也可以使用String或StringBuffer/StringBuilder中的方法。有一道很常见的面试题是用递归实现字符串反转,代码如下所示:

1publicstaticStringreverse(StringoriginStr){2if(originStr==null||originStr.length()<=1)3returnoriginStr;4returnreverse(originStr.substring(1))+originStr.charAt(0);5}40、怎样将GB2312编码的字符串转换为ISO-8859-1编码的字符串?答:代码如下所示:

-如何取得年月日、小时分钟秒?

-如何取得从1970年1月1日0时0分0秒到现在的毫秒数?

-如何取得某月的最后一天?

-如何格式化日期?

答:

问题1:创建java.util.Calendar实例,调用其get()方法传入不同的参数即可获得参数所对应的值。Java8中可以使用java.time.LocalDateTimel来获取,代码如下所示。

1publicclassDateTimeTest{2publicstaticvoidmain(String[]args){3Calendarcal=Calendar.getInstance();4System.out.println(cal.get(Calendar.YEAR));5System.out.println(cal.get(Calendar.MONTH));//0-116System.out.println(cal.get(Calendar.DATE));7System.out.println(cal.get(Calendar.HOUR_OF_DAY));8System.out.println(cal.get(Calendar.MINUTE));9System.out.println(cal.get(Calendar.SECOND));1011//Java812LocalDateTimedt=LocalDateTime.now();13System.out.println(dt.getYear());14System.out.println(dt.getMonthValue());//1-1215System.out.println(dt.getDayOfMonth());16System.out.println(dt.getHour());17System.out.println(dt.getMinute());18System.out.println(dt.getSecond());19}20}问题2:以下方法均可获得该毫秒数。

1Calendar.getInstance().getTimeInMillis();2System.currentTimeMillis();3Clock.systemDefaultZone().millis();//Java8问题3:代码如下所示。

42、打印昨天的当前时刻。

1importjava.util.Calendar;23classYesterdayCurrent{4publicstaticvoidmain(String[]args){5Calendarcal=Calendar.getInstance();6cal.add(Calendar.DATE,-1);7System.out.println(cal.getTime());8}9}在Java8中,可以用下面的代码实现相同的功能。

1importjava.time.LocalDateTime;23classYesterdayCurrent{45publicstaticvoidmain(String[]args){6LocalDateTimetoday=LocalDateTime.now();7LocalDateTimeyesterday=today.minusDays(1);89System.out.println(yesterday);10}11}43、比较一下Java和JavaSciprt。

答:JavaScript与Java是两个公司开发的不同的两个产品。Java是原SunMicrosystems公司推出的面向对象的程序设计语言,特别适合于互联网应用程序开发;而JavaScript是Netscape公司的产品,为了扩展Netscape浏览器的功能而开发的一种可以嵌入Web页面中运行的基于对象和事件驱动的解释性语言。JavaScript的前身是LiveScript;而Java的前身是Oak语言。

下面对两种语言间的异同作如下比较:

-基于对象和面向对象:Java是一种真正的面向对象的语言,即使是开发简单的程序,必须设计对象;JavaScript是种脚本语言,它可以用来制作与网络无关的,与用户交互作用的复杂软件。它是一种基于对象(Object-Based)和事件驱动(Event-Driven)的编程语言,因而它本身提供了非常丰富的内部对象供设计人员使用。

-解释和编译:Java的源代码在执行之前,必须经过编译。JavaScript是一种解释性编程语言,其源代码不需经过编译,由浏览器解释执行。(目前的浏览器几乎都使用了JIT(即时编译)技术来提升JavaScript的运行效率)

-代码格式不一样。

补充:上面列出的四点是网上流传的所谓的标准答案。其实Java和JavaScript最重要的区别是一个是静态语言,一个是动态语言。目前的编程语言的发展趋势是函数式语言和动态语言。在Java中类(class)是一等公民,而JavaScript中函数(function)是一等公民,因此JavaScript支持函数式编程,可以使用Lambda函数和闭包(closure),当然Java8也开始支持函数式编程,提供了对Lambda表达式以及函数式接口的支持。对于这类问题,在面试的时候最好还是用自己的语言回答会更加靠谱,不要背网上所谓的标准答案。

44、什么时候用断言(assert)?

答:断言在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制。一般来说,断言用于保证程序最基本、关键的正确性。断言检查通常在开发和测试时开启。为了保证程序的执行效率,在软件发布后断言检查通常是关闭的。断言是一个包含布尔表达式的语句,在执行这个语句时假定该表达式为true;如果表达式的值为false,那么系统会报告一个AssertionError。断言的使用如下面的代码所示:

assert(a>0);//throwsanAssertionErrorifa<=0

1

断言可以有两种形式:

assertExpression1;

assertExpression1:Expression2;

Expression1应该总是产生一个布尔值。

Expression2可以是得出一个值的任意表达式;这个值用于生成显示更多调试信息的字符串消息。

要在运行时启用断言,可以在启动JVM时使用-enableassertions或者-ea标记。要在运行时选择禁用断言,可以在启动JVM时使用-da或者-disableassertions标记。要在系统类中启用或禁用断言,可使用-esa或-dsa标记。还可以在包的基础上启用或者禁用断言。

注意:断言不应该以任何方式改变程序的状态。简单的说,如果希望在不满足某些条件时阻止代码的执行,就可以考虑用断言来阻止它。

45、Error和Exception有什么区别?

答:Error表示系统级的错误和程序不必处理的异常,是恢复不是不可能但很困难的情况下的一种严重问题;比如内存溢出,不可能指望程序能处理这样的情况;Exception表示需要捕捉或者需要程序进行处理的异常,是一种设计或实现问题;也就是说,它表示如果程序运行正常,从不会发生的情况。

面试题:2005年摩托罗拉的面试中曾经问过这么一个问题“Ifaprocessreportsastackoverflowrun-timeerror,what’sthemostpossiblecause”,给了四个选项a.lackofmemory;b.writeonaninvalidmemoryspace;c.recursivefunctioncalling;d.arrayindexoutofboundary.Java程序在运行时也可能会遭遇StackOverflowError,这是一个无法恢复的错误,只能重新修改代码了,这个面试题的答案是c。如果写了不能迅速收敛的递归,则很有可能引发栈溢出的错误,如下所示:

1classStackOverflowErrorTest{23publicstaticvoidmain(String[]args){4main(null);5}6}提示:用递归编写程序时一定要牢记两点:1.递归公式;2.收敛条件(什么时候就不再继续递归)。

46、try{}里有一个return语句,那么紧跟在这个try后的finally{}里的代码会不会被执行,什么时候被执行,在return前还是后

答:会执行,在方法返回调用者前执行。

注意:在finally中改变返回值的做法是不好的,因为如果存在finally代码块,try中的return语句不会立马返回调用者,而是记录下返回值待finally代码块执行完毕之后再向调用者返回其值,然后如果在finally中修改了返回值,就会返回修改后的值。显然,在finally中返回或者修改返回值会对程序造成很大的困扰,C#中直接用编译错误的方式来阻止程序员干这种龌龊的事情,Java中也可以通过提升编译器的语法检查级别来产生警告或错误,Eclipse中可以在如图所示的地方进行设置,强烈建议将此项设置为编译错误。

————————————————

47、Java语言如何进行异常处理,关键字:throws、throw、try、catch、finally分别如何使用?

48、运行时异常与受检异常有何异同?

-不要将异常处理用于正常的控制流(设计良好的API不应该强迫它的调用者为了正常的控制流而使用异常)

-对可以恢复的情况使用受检异常,对编程错误使用运行时异常

-避免不必要的使用受检异常(可以通过一些状态检测手段来避免异常的发生)

-优先使用标准的异常

-每个方法抛出的异常都要有文档

-保持异常的原子性

-不要在catch中忽略掉捕获到的异常

49、列出一些你常见的运行时异常?

-ArithmeticException(算术异常)

-ClassCastException(类转换异常)

-IllegalArgumentException(非法参数异常)

-IndexOutOfBoundsException(下标越界异常)

-NullPointerException(空指针异常)

-SecurityException(安全异常)

50、阐述final、finally、finalize的区别。

-finally:通常放在try…catch…的后面构造总是执行代码块,这就意味着程序无论正常执行还是发生异常,这里的代码只要JVM不关闭都能执行,可以将释放外部资源的代码写在finally块中。

-finalize:Object类中定义的方法,Java中允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在销毁对象时调用的,通过重写finalize()方法可以整理系统资源或者执行其他清理工作。

51、类ExampleA继承Exception,类ExampleB继承ExampleA。

有如下代码片断:

1try{2thrownewExampleB("b")3}catch(ExampleAe){4System.out.println("ExampleA");5}catch(Exceptione){6System.out.println("Exception");7}请问执行此段代码的输出是什么?

答:输出:ExampleA。(根据里氏代换原则[能使用父类型的地方一定能使用子类型],抓取ExampleA类型异常的catch块能够抓住try块中抛出的ExampleB类型的异常)

面试题-说出下面代码的运行结果。(此题的出处是《Java编程思想》一书)

1classAnnoyanceextendsException{}2classSneezeextendsAnnoyance{}34classHuman{56publicstaticvoidmain(String[]args)7throwsException{8try{9try{10thrownewSneeze();11}12catch(Annoyancea){13System.out.println("CaughtAnnoyance");14throwa;15}16}17catch(Sneezes){18System.out.println("CaughtSneeze");19return;20}21finally{22System.out.println("HelloWorld!");23}24}25}52、List、Set、Map是否继承自Collection接口?

答:List、Set是,Map不是。Map是键值对映射容器,与List和Set有明显的区别,而Set存储的零散的元素且不允许有重复元素(数学中的集合也是如此),List是线性结构的容器,适用于按数值索引访问元素的情形。

53、阐述ArrayList、Vector、LinkedList的存储性能和特性。

答:ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector中的方法由于添加了synchronized修饰,因此Vector是线程安全的容器,但性能上较ArrayList差,因此已经是Java中的遗留容器。LinkedList使用双向链表实现存储(将内存中零散的内存单元通过附加的引用关联起来,形成一个可以按序号索引的线性结构,这种链式存储方式与数组的连续存储方式相比,内存的利用率更高),按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。Vector属于遗留容器(Java早期的版本中提供的容器,除此之外,Hashtable、Dictionary、BitSet、Stack、Properties都是遗留容器),已经不推荐使用,但是由于ArrayList和LinkedListed都是非线程安全的,如果遇到多个线程操作同一个容器的场景,则可以通过工具类Collections中的synchronizedList方法将其转换成线程安全的容器后再使用(这是对装潢模式的应用,将已有对象传入另一个类的构造器中创建新的对象来增强实现)。

补充:遗留容器中的Properties类和Stack类在设计上有严重的问题,Properties是一个键和值都是字符串的特殊的键值对映射,在设计上应该是关联一个Hashtable并将其两个泛型参数设置为String类型,但是JavaAPI中的Properties直接继承了Hashtable,这很明显是对继承的滥用。这里复用代码的方式应该是Has-A关系而不是Is-A关系,另一方面容器都属于工具类,继承工具类本身就是一个错误的做法,使用工具类最好的方式是Has-A关系(关联)或Use-A关系(依赖)。同理,Stack类继承Vector也是不正确的。Sun公司的工程师们也会犯这种低级错误,让人唏嘘不已。

54、Collection和Collections的区别?

答:Collection是一个接口,它是Set、List等容器的父接口;Collections是个一个工具类,提供了一系列的静态方法来辅助容器操作,这些方法包括对容器的搜索、排序、线程安全化等等。

55、List、Map、Set三个接口存取元素时,各有什么特点?

56、TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?

答:TreeSet要求存放的对象所属的类必须实现Comparable接口,该接口提供了比较元素的compareTo()方法,当插入元素时会回调该方法比较元素的大小。TreeMap要求存放的键值对映射的键必须实现Comparable接口从而根据键对元素进行排序。Collections工具类的sort方法有两种重载的形式,第一种要求传入的待排序容器中存放的对象比较实现Comparable接口以实现元素的比较;第二种不强制性的要求容器中的元素必须可比较,但是要求传入第二个参数,参数是Comparator接口的子类型(需要重写compare方法实现元素的比较),相当于一个临时定义的排序规则,其实就是通过接口注入比较元素大小的算法,也是对回调模式的应用(Java中对函数式编程的支持)。

例子1:

1publicclassStudentimplementsComparable{2privateStringname;//姓名3privateintage;//年龄45publicStudent(Stringname,intage){6this.name=name;7this.age=age;8}910@Override11publicStringtoString(){12return"Student[name="+name+",age="+age+"]";13}1415@Override16publicintcompareTo(Studento){17returnthis.age-o.age;//比较年龄(年龄的升序)18}1920}例子2:

58、线程的sleep()方法和yield()方法有什么区别?

①sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会;

②线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态;

59、当一个线程进入一个对象的synchronized方法A之后,其它线程是否可进入此对象的synchronized方法B?

答:不能。其它线程只能访问该对象的非同步方法,同步方法则不能进入。因为非静态方法上的synchronized修饰符要求执行方法时要获得对象的锁,如果已经进入A方法说明对象锁已经被取走,那么试图进入B方法的线程就只能在等锁池(注意不是等待池哦)中等待对象的锁。

-wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁;

-sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要处理InterruptedException异常;

-notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且与优先级无关;

-notityAll():唤醒所有处于等待状态的线程,该方法并不是将对象的锁给所有线程,而是让它们竞争,只有获得锁的线程才能进入就绪状态;

补充:Java5通过Lock接口提供了显式的锁机制(explicitlock),增强了灵活性以及对线程的协调。Lock接口中定义了加锁(lock())和解锁(unlock())的方法,同时还提供了newCondition()方法来产生用于线程之间通信的Condition对象;此外,Java5还提供了信号量机制(semaphore),信号量可以用来限制对某个共享资源进行访问的线程的数量。在对资源进行访问之前,线程必须得到信号量的许可(调用Semaphore对象的acquire()方法);在完成对资源的访问后,线程必须向信号量归还许可(调用Semaphore对象的release()方法)。

下面的例子演示了100个线程同时向一个银行账户中存入1元钱,在没有使用同步机制和使用同步机制情况下的执行情况。

银行账户类:

在没有同步的情况下,执行结果通常是显示账户余额在10元以下,出现这种状况的原因是,当一个线程A试图存入1元的时候,另外一个线程B也能够进入存款的方法中,线程B读取到的账户余额仍然是线程A存入1元钱之前的账户余额,因此也是在原来的余额0上面做了加1元的操作,同理线程C也会做类似的事情,所以最后100个线程执行结束时,本来期望账户余额为100元,但实际得到的通常在10元以下(很可能是1元哦)。解决这个问题的办法就是同步,当一个线程对银行账户存钱时,需要将此账户锁定,待其操作完成后才允许其他的线程进行操作,代码有如下几种调整方案:

在银行账户的存款(deposit)方法上同步(synchronized)关键字

按照上述三种方式对代码进行修改后,重写执行测试代码Test01,将看到最终的账户余额为100元。当然也可以使用Semaphore或CountdownLatch来实现同步。

61、编写多线程程序有几种实现方式?

答:Java5以前实现多线程有两种实现方法:一种是继承Thread类;另一种是实现Runnable接口。两种方式都要通过重写run()方法来定义线程的行为,推荐使用后者,因为Java中的继承是单继承,一个类有一个父类,如果继承了Thread类就无法再继承其他类了,显然使用Runnable接口更为灵活。

补充:Java5以后创建线程还有第三种方式:实现Callable接口,该接口中的call方法可以在线程执行结束时产生一个返回值,代码如下所示:

1importjava.util.ArrayList;2importjava.util.List;3importjava.util.concurrent.Callable;4importjava.util.concurrent.ExecutorService;5importjava.util.concurrent.Executors;6importjava.util.concurrent.Future;789classMyTaskimplementsCallable{10privateintupperBounds;1112publicMyTask(intupperBounds){13this.upperBounds=upperBounds;14}1516@Override17publicIntegercall()throwsException{18intsum=0;19for(inti=1;i<=upperBounds;i++){20sum+=i;21}22returnsum;23}2425}2627classTest{2829publicstaticvoidmain(String[]args)throwsException{30List>list=newArrayList<>();31ExecutorServiceservice=Executors.newFixedThreadPool(10);32for(inti=0;i<10;i++){33list.add(service.submit(newMyTask((int)(Math.random()*100))));34}3536intsum=0;37for(Futurefuture:list){38//while(!future.isDone());39sum+=future.get();40}4142System.out.println(sum);43}44}62、synchronized关键字的用法?

63、举例说明同步和异步。

64、启动一个线程是调用run()还是start()方法?

答:启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行,这并不意味着线程就会立即运行。run()方法是线程启动后要进行回调(callback)的方法。

65、什么是线程池(threadpool)?

Java5+中的Executor接口定义一个执行线程的工具。它的子类型即线程池接口是ExecutorService。要配置一个线程池是比较复杂的,尤其是对于线程池的原理不是很清楚的情况下,因此在工具类Executors面提供了一些静态工厂方法,生成一些常用的线程池,如下所示:

-newSingleThreadExecutor:创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。

-newFixedThreadPool:创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。

-newCachedThreadPool:创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。

-newScheduledThreadPool:创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。

-newSingleThreadExecutor:创建一个单线程的线程池。此线程池支持定时以及周期性执行任务的需求。

第60题的例子中演示了通过Executors工具类创建线程池并使用线程池执行线程的代码。如果希望在服务器上使用线程池,强烈建议使用newFixedThreadPool方法来创建线程池,这样能获得更好的性能。

66、线程的基本状态以及状态之间的关系?

说明:其中Running表示运行状态,Runnable表示就绪状态(万事俱备,只欠CPU),Blocked表示阻塞状态,阻塞状态又有多种情况,可能是因为调用wait()方法进入等待池,也可能是执行同步方法或同步代码块进入等锁池,或者是调用了sleep()方法或join()方法等待休眠或其他线程结束,或是因为发生了I/O中断。

67、简述synchronized和java.util.concurrent.locks.Lock的异同?

答:Lock是Java5以后引入的新的API,和关键字synchronized相比主要相同点:Lock能完成synchronized所实现的所有功能;主要不同点:Lock有比synchronized更精确的线程语义和更好的性能,而且不强制性的要求一定要获得锁。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且最好在finally块中释放(这是释放外部资源的最好的地方)。

68、Java中如何实现序列化,有什么意义?

答:序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决对象流读写操作时可能引发的问题(如果不进行序列化可能会存在数据乱序的问题)。

要实现序列化,需要让一个类实现Serializable接口,该接口是一个标识性接口,标注该类对象是可被序列化的,然后使用一个输出流来构造一个对象输出流并通过writeObject(Object)方法就可以将实现对象写出(即保存其状态);如果需要反序列化则可以用一个输入流建立对象输入流,然后通过readObject方法从流中读取对象。序列化除了能够实现对象的持久化之外,还能够用于对象的深度克隆(可以参考第29题)。

69、Java中有几种类型的流?

答:字节流和字符流。字节流继承于InputStream、OutputStream,字符流继承于Reader、Writer。在java.io包中还有许多其他的流,主要是为了提高性能和使用方便。关于Java的I/O需要注意的有两点:一是两种对称性(输入和输出的对称性,字节和字符的对称性);二是两种设计模式(适配器模式和装潢模式)。另外Java中的流不同于C#的是它只有一个维度一个方向。

面试题-编程实现文件拷贝。(这个题目在笔试的时候经常出现,下面的代码给出了两种实现方案)

70、写一个方法,输入一个文件名和一个字符串,统计这个字符串在这个文件中出现的次数。答:代码如下:

1importjava.io.BufferedReader;2importjava.io.FileReader;34publicfinalclassMyUtil{56//工具类中的方法都是静态方式访问的因此将构造器私有不允许创建对象(绝对好习惯)7privateMyUtil(){8thrownewAssertionError();9}1011/**12*统计给定文件中给定字符串的出现次数13*14*@paramfilename文件名15*@paramword字符串16*@return字符串在文件中出现的次数17*/18publicstaticintcountWordInFile(Stringfilename,Stringword){19intcounter=0;20try(FileReaderfr=newFileReader(filename)){21try(BufferedReaderbr=newBufferedReader(fr)){22Stringline=null;23while((line=br.readLine())!=null){24intindex=-1;25while(line.length()>=word.length()&&(index=line.indexOf(word))>=0){26counter++;27line=line.substring(index+word.length());28}29}30}31}catch(Exceptionex){32ex.printStackTrace();33}34returncounter;35}3637}71、如何用Java代码列出一个目录下所有的文件?答:如果只要求列出当前文件夹下的文件,代码如下所示:

1importjava.io.File;23classTest12{45publicstaticvoidmain(String[]args){6Filef=newFile("/Users/Hao/Downloads");7for(Filetemp:f.listFiles()){8if(temp.isFile()){9System.out.println(temp.getName());10}11}12}13}如果需要对文件夹继续展开,代码如下所示:

1importjava.io.File;23classTest12{45publicstaticvoidmain(String[]args){6showDirectory(newFile("/Users/Hao/Downloads"));7}89publicstaticvoidshowDirectory(Filef){10_walkDirectory(f,0);11}1213privatestaticvoid_walkDirectory(Filef,intlevel){14if(f.isDirectory()){15for(Filetemp:f.listFiles()){16_walkDirectory(temp,level+1);17}18}19else{20for(inti=0;i

1classShowFileTest{23publicstaticvoidmain(String[]args)throwsIOException{4PathinitPath=Paths.get("/Users/Hao/Downloads");5Files.walkFileTree(initPath,newSimpleFileVisitor(){67@Override8publicFileVisitResultvisitFile(Pathfile,BasicFileAttributesattrs)9throwsIOException{10System.out.println(file.getFileName().toString());11returnFileVisitResult.CONTINUE;12}1314});15}16}72、用Java的套接字编程实现一个多线程的回显(echo)服务器。答:

下面是一段回显客户端测试代码:

1importjava.io.BufferedReader;2importjava.io.InputStreamReader;3importjava.io.PrintWriter;4importjava.net.Socket;5importjava.util.Scanner;67publicclassEchoClient{89publicstaticvoidmain(String[]args)throwsException{10Socketclient=newSocket("localhost",6789);11Scannersc=newScanner(System.in);12System.out.print("请输入内容:");13Stringmsg=sc.nextLine();14sc.close();15PrintWriterpw=newPrintWriter(client.getOutputStream());16pw.println(msg);17pw.flush();18BufferedReaderbr=newBufferedReader(newInputStreamReader(client.getInputStream()));19System.out.println(br.readLine());20client.close();21}22}如果希望用NIO的多路复用套接字实现服务器,代码如下所示。NIO的操作虽然带来了更好的性能,但是有些操作是比较底层的,对于初学者来说还是有些难于理解。

1importjava.nio.ByteBuffer;2importjava.nio.CharBuffer;3importjava.nio.charset.CharacterCodingException;4importjava.nio.charset.Charset;5importjava.nio.charset.CharsetDecoder;6importjava.nio.charset.CharsetEncoder;78publicfinalclassCharsetHelper{9privatestaticfinalStringUTF_8="UTF-8";10privatestaticCharsetEncoderencoder=Charset.forName(UTF_8).newEncoder();11privatestaticCharsetDecoderdecoder=Charset.forName(UTF_8).newDecoder();1213privateCharsetHelper(){14}1516publicstaticByteBufferencode(CharBufferin)throwsCharacterCodingException{17returnencoder.encode(in);18}1920publicstaticCharBufferdecode(ByteBufferin)throwsCharacterCodingException{21returndecoder.decode(in);22}23}73、XML文档定义有几种形式?它们之间有何本质区别?解析XML文档有哪几种方式?

74、你在项目中哪些地方用到了XML?

补充:现在有很多时髦的软件(如Sublime)已经开始将配置文件书写成JSON格式,我们已经强烈的感受到XML的另一项功能也将逐渐被业界抛弃。

75、阐述JDBC操作数据库的步骤。

答:下面的代码以连接本机的Oracle数据库为例,演示JDBC操作数据库的步骤。

加载驱动。

1Class.forName("oracle.jdbc.driver.OracleDriver");提示:关闭外部资源的顺序应该和打开的顺序相反,也就是说先关闭ResultSet、再关闭Statement、在关闭Connection。上面的代码只关闭了Connection(连接),虽然通常情况下在关闭连接时,连接上创建的语句和打开的游标也会关闭,但不能保证总是如此,因此应该按照刚才说的顺序分别关闭。此外,第一步加载驱动在JDBC4.0中是可以省略的(自动从类路径中加载驱动),但是我们建议保留。

76、Statement和PreparedStatement有什么区别?哪个性能更好?

答:与Statement相比,①PreparedStatement接口代表预编译的语句,它主要的优势在于可以减少SQL的编译错误并增加SQL的安全性(减少SQL注射攻击的可能性);②PreparedStatement中的SQL语句是可以带参数的,避免了用字符串连接拼接SQL语句的麻烦和不安全;③当批量处理SQL或频繁执行相同的查询时,PreparedStatement有明显的性能上的优势,由于数据库可以将编译优化后的SQL语句缓存起来,下次执行相同结构的语句时就会很快(不用再次编译和生成执行计划)。

补充:为了提供对存储过程的调用,JDBCAPI中还提供了CallableStatement接口。存储过程(StoredProcedure)是数据库中一组为了完成特定功能的SQL语句的集合,经编译后存储在数据库中,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。虽然调用存储过程会在网络开销、安全性、性能上获得很多好处,但是存在如果底层数据库发生迁移时就会有很多麻烦,因为每种数据库的存储过程在书写上存在不少的差别。

77、使用JDBC操作数据库时,如何提升读取数据的性能?如何提升更新数据的性能?

78、在进行数据库编程时,连接池有什么作用?

79、什么是DAO模式?

答:DAO(DataAccessObject)顾名思义是一个为数据库或其他持久化机制提供了抽象接口的对象,在不暴露底层持久化方案实现细节的前提下提供了各种数据访问操作。在实际的开发中,应该将所有对数据源的访问操作进行抽象化后封装在一个公共API中。用程序设计语言来说,就是建立一个接口,接口中定义了此应用程序中将会用到的所有事务方法。在这个应用程序中,当需要和数据源进行交互的时候则使用这个接口,并且编写一个单独的类来实现这个接口,在逻辑上该类对应一个特定的数据存储。DAO模式实际上包含了两个模式,一是DataAccessor(数据访问器),二是DataObject(数据对象),前者要解决如何访问数据的问题,而后者要解决的是如何用对象封装数据。

80、事务的ACID是指什么?

-原子性(Atomic):事务中各项操作,要么全做要么全不做,任何一项操作的失败都会导致整个事务的失败;

-一致性(Consistent):事务结束后系统状态是一致的;

-隔离性(Isolated):并发执行的事务彼此无法看到对方的中间状态;

-持久性(Durable):事务完成后所做的改动都会被持久化,即使发生灾难性的失败。通过日志和同步备份可以在故障发生后重建数据。

补充:关于事务,在面试中被问到的概率是很高的,可以问的问题也是很多的。首先需要知道的是,只有存在并发数据访问时才需要事务。当多个事务访问同一数据时,可能会存在5类问题,包括3类数据读取问题(脏读、不可重复读和幻读)和2类数据更新问题(第1类丢失更新和第2类丢失更新)。

脏读(DirtyRead):A事务读取B事务尚未提交的数据并在此基础上操作,而B事务执行回滚,那么A读取到的数据就是脏数据。

T1开始事务

T2开始事务

T3查询账户余额为1000元

T4取出500元余额修改为500元

T5查询账户余额为500元(脏读)

T6撤销事务余额恢复为1000元

T7汇入100元把余额修改为600元

T8提交事务

不可重复读(UnrepeatableRead):事务A重新读取前面读取过的数据,发现该数据已经被另一个已提交的事务B修改过了。

T4查询账户余额为1000元

T5取出100元修改余额为900元

T6提交事务

T7查询账户余额为900元(不可重复读)

幻读(PhantomRead):事务A重新执行一个查询,返回一系列符合查询条件的行,发现其中插入了被事务B提交的行。

T3统计总存款为10000元

T4新增一个存款账户存入100元

T5提交事务

T6再次统计总存款为10100元(幻读)

第1类丢失更新:事务A撤销时,把已经提交的事务B的更新数据覆盖了。

T5汇入100元修改余额为1100元

T7取出100元将余额修改为900元

T8撤销事务

T9余额恢复为1000元(丢失更新)

第2类丢失更新:事务A覆盖事务B已经提交的数据,造成事务B所做的操作丢失。

数据并发访问所产生的问题,在有些场景下可能是允许的,但是有些场景下可能就是致命的,数据库通常会通过锁机制来解决数据并发访问问题,按锁定对象不同可以分为表级锁和行级锁;按并发事务锁定关系可以分为共享锁和独占锁,具体的内容大家可以自行查阅资料进行了解。直接使用锁是非常麻烦的,为此数据库为用户提供了自动锁机制,只要用户指定会话的事务隔离级别,数据库就会通过分析SQL语句然后为事务访问的资源加上合适的锁,此外,数据库还会维护这些锁通过各种手段提高系统的性能,这些对用户来说都是透明的(就是说你不用理解,事实上我确实也不知道)。ANSI/ISOSQL92标准定义了4个等级的事务隔离级别,如下表所示:

需要说明的是,事务隔离级别和数据访问的并发性是对立的,事务隔离级别越高并发性就越差。所以要根据具体的应用来确定合适的事务隔离级别,这个地方没有万能的原则。

81、JDBC中如何进行事务处理?答:Connection提供了事务处理的方法,通过调用setAutoCommit(false)可以设置手动提交事务;当事务完成后用commit()显式提交事务;如果在事务处理过程中发生异常则通过rollback()进行事务回滚。除此之外,从JDBC3.0中还引入了Savepoint(保存点)的概念,允许通过代码设置保存点并让事务回滚到指定的保存点。

82、JDBC能否处理Blob和Clob?答:Blob是指二进制大对象(BinaryLargeObject),而Clob是指大字符对象(CharacterLargeObjec),因此其中Blob是为存储大的二进制数据而设计的,而Clob是为存储大的文本数据而设计的。JDBC的PreparedStatement和ResultSet都提供了相应的方法来支持Blob和Clob操作。下面的代码展示了如何使用JDBC操作LOB:下面以MySQL数据库为例,创建一个张有三个字段的用户表,包括编号(id)、姓名(name)和照片(photo),建表语句如下:

1createtabletb_user2(3idintprimarykeyauto_increment,4namevarchar(20)uniquenotnull,5photolongblob6);下面的Java代码向数据库中插入一条记录:

说明:计算机诞生初期处理的信息几乎都是数值,但是时过境迁,今天我们使用计算机处理的信息更多的时候不是数值而是字符串,正则表达式就是在进行字符串匹配和处理的时候最为强大的工具,绝大多数语言都提供了对正则表达式的支持。

84、Java中是如何支持正则表达式操作的?答:Java中的String类提供了支持正则表达式操作的方法,包括:matches()、replaceAll()、replaceFirst()、split()。此外,Java中可以用Pattern类表示正则表达式对象,它提供了丰富的API进行各种正则表达式操作,请参考下面面试题的代码。

面试题:-如果要从字符串中截取第一个英文左括号之前的字符串,例如:北京市(朝阳区)(西城区)(海淀区),截取结果为:北京市,那么正则表达式怎么写?

1importjava.util.regex.Matcher;2importjava.util.regex.Pattern;34classRegExpTest{56publicstaticvoidmain(String[]args){7Stringstr="北京市(朝阳区)(西城区)(海淀区)";8Patternp=Pattern.compile(".*(=\\()");9Matcherm=p.matcher(str);10if(m.find()){11System.out.println(m.group());12}13}14}说明:上面的正则表达式中使用了懒惰匹配和前瞻,如果不清楚这些内容,推荐读一下网上很有名的《正则表达式30分钟入门教程》。

85、获得一个类的类对象有哪些方式?答:-方法1:类型.class,例如:String.class-方法2:对象.getClass(),例如:"hello".getClass()-方法3:Class.forName(),例如:Class.forName("java.lang.String")

86、如何通过反射创建对象?答:-方法1:通过类对象调用newInstance()方法,例如:String.class.newInstance()-方法2:通过类对象的getConstructor()或getDeclaredConstructor()方法获得构造器(Constructor)对象并调用其newInstance()方法创建对象,例如:String.class.getConstructor(String.class).newInstance("Hello");

87、如何通过反射获取和设置对象私有字段的值?答:可以通过类对象的getDeclaredField()方法字段(Field)对象,然后再通过字段对象的setAccessible(true)将其设置为可以访问,接下来就可以通过get/set方法来获取/设置字段的值了。下面的代码实现了一个反射的工具类,其中的两个静态方法分别用于获取和设置私有字段的值,字段可以是基本类型也可以是对象类型且支持多级对象操作,例如ReflectionUtil.get(dog,"owner.car.engine.id");可以获得dog对象的主人的汽车的引擎的ID号。

91、用Java写一个单例类。

答:-饿汉式单例

1publicclassSingleton{2privateSingleton(){}3privatestaticSingletoninstance=newSingleton();4publicstaticSingletongetInstance(){5returninstance;6}7}答:UML是统一建模语言(UnifiedModelingLanguage)的缩写,它发表于1997年,综合了当时已经存在的面向对象的建模语言、方法和过程,是一个支持模型化和软件系统开发的图形化语言,为软件开发的所有阶段提供模型化和可视化支持。使用UML可以帮助沟通与交流,辅助应用设计和文档的生成,还能够阐释系统的结构和行为。

93、UML中有哪些常用的图?答:UML定义了多种图形化的符号来描述软件系统部分或全部的静态结构和动态结构,包括:用例图(usecasediagram)、类图(classdiagram)、时序图(sequencediagram)、协作图(collaborationdiagram)、状态图(statechartdiagram)、活动图(activitydiagram)、构件图(componentdiagram)、部署图(deploymentdiagram)等。在这些图形化符号中,有三种图最为重要,分别是:用例图(用来捕获需求,描述系统的功能,通过该图可以迅速的了解系统的功能模块及其关系)、类图(描述类以及类与类之间的关系,通过该图可以快速了解系统)、时序图(描述执行特定任务时对象之间的交互关系以及执行顺序,通过该图可以了解对象能接收的消息也就是说对象能够向外界提供的服务)。用例图:

94、用Java写一个冒泡排序。答:冒泡排序几乎是个程序员都写得出来,但是面试的时候如何写一个逼格高的冒泡排序却不是每个人都能做到,下面提供一个参考代码:

THE END
1.大唐移动SPANADT自动路测产品介绍v10经管文库大唐移动SPANADT自动路测产品介绍v10 https://bbs.pinggu.org/thread-12868682-1-1.html
2.链上数据分析基次:圆周率循环顶部从大盘的中长期角度来看,我觉得2022年后的变化跟过去有显著的差异,曾有人预言2024年将会是最后的牛市,因为往后将会进入一种常态震荡的状态。 趋势上的确显现了下一轮牛市的差距已经没有过往激烈,熊市也是一样,但凡是市场,牛熊还是存在的,虽然十倍百倍的机率下降了,但在正经的投资操盘上,还是有很多着墨之处。https://blog.csdn.net/qq_23725949/article/details/144073799
3.牛顿向前插值公式证明理想股票技术论坛通过推导和证明牛顿向前插值公式,深入理解和掌握牛顿插值法在数值计算中的应用,从而提高对数据的插值和外推能力。 ,理想股票技术论坛http://m.55188.com/tag-03445245.html
4.计算技巧掌握Excel加权平均数公式,快速准确计算加权平均值的技巧解析情留君醉 2024-11-26 22:18:02 没有更多内容 滇ICP备2023010045号-86 本文内容由互联网用户自发贡献,该文观点仅代表作者本人,因此内容不代表本站观点、本站不对文章中的任何观点负责,内容版权归原作者所有、内容只用于提供信息阅读,无任何商业用途。本站http://m.lffenquanban.com/tags-58177.html
5.上算DT个人资料简介(身高/生日/年龄)电影电视剧作品因在56网坚持原创视频和原创音乐而被很多网友熟知,大家都亲切的称她为DT,刚出道时建立的DT家族(粉丝团)至今也得到了很多粉丝的加入和支持,目前还在不断壮大当中【详细】上算DT个人资料来源于网络收集仅供参考,如有出入,以上算DT本人或官方发布消息为准!上算http://www.manmankan.com/dy2013/mingxing/201610/22241.shtml
6.上算DT个人资料/图片/视频全集上算DT的歌曲上算DT 地区:内地 出生地:中国 / 四川 / 自贡 生日:1987-10-26 职业:歌手 星座:天蝎座 别名:Desting / DT / 陈馨儿 上算DT,是一个56网我秀的美女主播,代表作品《我会想念你》、《几多十年》、《遇到》等。 分享:https://tv.sohu.com/star/NzE2MTEyXw==.shtml
7.上算DT枣庄找对象枣庄交友网枣庄交友网会员:上算DT-绅士。36岁,居住在山东 枣庄。身高:170cm,教育程度:本科,职业:自由职业。在情人网找对象希望得到感情补充,查看联系方式https://m.mgqr.com/user/1249611.html
8.说谎上算DT高音质在线试听说谎歌词歌曲下载上算DT - 说谎 歌手:上算DT 上算DT - 说谎 作词:施人诚 作曲:李双飞 是有过几个不错对象 说起来并不寂寞孤单 可能我浪荡让人家不安 才会结果都阵亡 我没有什么阴影魔障 你千万不要放在心上 我又不脆弱 何况那算什么伤 反正爱情不就都这样 我没有说谎 我何必说谎 你懂我的 我对https://m.kugou.com/mixsong/1ttxd8c7.html
9.DT时代来临,细数云计算的十大趋势DT是继IT(信息技术)之后的又一次技术变革,主旨是挖掘海量数据的价值,让数据成为新的经济增长引擎。笔者总结了DT时代云计算的十大发展趋势。 DT(DataTechnology)时代,是马云热衷于步道的新概念。这是继IT(信息技术)之后的又一次技术变革,主旨是挖掘海量数据的价值,让数据成为新的经济增长引擎。数据与金融、平台并列为https://www.51cto.com/article/486198.html
10.电感的选型(电感的选型和计算)我们使用电感上电压核算公式:V=L(dI/dt) 因此,当电感上的电压为正时(情况1),电感上的电流就会增加;当电感上的电压为负时(情况2),电感上的电流就会减小。 通过电感的电流如图2所示: 通过上图我们可以看到,流过电感的最大电流为DC电流加开关峰峰电流的一半。上图也称为纹波电流。 https://www.yibeiic.com/solution/16248.html
11.暴风科技:华泰联合证券有限责任公司中国国际金融股份有限公司波动对本次交易可能产生的影响,考虑到甘普科技、稻草熊影业、立动科技对上 市公司“DT 大娱乐”的战略意义及良好的协同效应,基于上述评估结果,经交易 各方友好协商,本次甘普科技 100%股权的最终交易价格为 105,000 万元,相比 评估值溢价约 9.87%;稻草熊影业 60%股权的最终交易价格为 108,000 万元,相 比评估值https://stock.stockstar.com/notice/JC2016031400003251_93.shtml
12.数据帝犀利演算:物理伤害暴击计算分析因为楼主精力有限,加上涉及数据的小数点都是0后十几位,算起来很麻烦,所以都是以5回合为上限 取5回合的原因除了容易计算外还有就是逆鳞这个套装也是5回合,这个后期如果有时间,楼主顺带一起算了 物理伤害暴击计算分析 一.DT(计算过程中不考虑自带的暴击几率和门派经脉的暴击几率) https://xyq.yzz.cn/skill/201606/1005239_all.shtml
13.科学计算器使用方法问:手机上科学计算器怎么用 答:安卓自带的计算器没法开立方 用计算器计算对数得用换底公式啊,任何计算器都一样 答:按下列操作;SHIFT>MOOE然后选择2 LinelO 问:在科学计算器中,"DT."应该怎样用按键按出? 答:科学计算器中按出“DT”键的方法步骤: 第一步:进入SD[标准偏差]模式或REG[求解]模式, 第二步:https://m.xyz.cn/toptag/kexuejisuanqishiyongfangfa-299778.html
14.我也算是耳机的入门用户嘞!拜亚动力DT1990PRO非典型听感分享目前手头吧只有一些国砖,而DT1990PRO和T1在国砖上的表现,我已经在另一篇文章里阐述过了。大家可以百度http://erji.net/forum.php?mod=viewthread&tid=2003965
15.民用飞机设计范文12篇(全文)随着现代电力电子技术的发展和飞机自动化水平的不断提高, 计算机和各种先进电气电子设备将越来越多地在飞机上使用, 飞机供电容量的增大与变频供电系统的供电质量问题也将日益突出, 这直接关系到先进电气设备功能的发挥和飞机的飞行安全。 飞机供电系统是飞机电能的生产、变换和输配等装置组成的一个完整系统, 其作用是https://www.99xueshu.com/w/ikeyao04rsap.html
16.德塔解读《超级计算数据中心设计要求》正式实施,DTCT绿色超级自规划期间就充分重视自然冷源、清洁能源和利旧改造,以保障环境与业务可持续发展;设计时关注储能蓄冷、建筑布局和低能耗设计,实现数据中心的全系统协同降能耗;结合工厂预制、本地生产和可再利用材料等方式,德塔森特可完成数据中心的快速低碳交付;DTCT云运维管理平台,可实现对数据中心效率提升、废料回收和设备维护的动态https://www.dtctcn.com/newsinfo/2184517.html
17.专业风速/风温/风量/风压测试仪DT本文介绍了DT-8894风速/风温/风量/风压测试仪的操作方法。仪器包括多种功能按键,如IRT用于远程表面温度测量,MAX/MIN用于记录温度的最大和最小值,AVG用于获取平均值。使用UNITS键选择风速或风量模式,HOLD键可锁定当前读数。风速测量需连接传感器并选择相应模式,风量测量则需设定风口面积并选择模式。仪器还具备非接触式红https://www.nbchao.com/k/8237/
18.恐艾都是SB吗源于网络艾滋病信息不真实有关2.dt为什么不算高危,dt有感染几率吗? 首先,从科学的角度说,不管是wt,还是dt,都是有感染几率的。 但是,从HIV病毒的自身来说,dt的感染几率无限接近于0,这是为什么呢? 我们知道,hiv病毒要从宿主进入另一个宿主的体内,需要体液交换,随后我们也会提到,那么体液交换究竟是怎样一个过程呢? http://www.for512.com/Item/17616.aspx
19.阿里云总裁胡晓明:计算是DT时代的主旋律,阿里云要帮助10000个在阿里云总裁胡晓明看来,计算是DT时代的主旋律。未来只需要一台计算机,这台超级计算机是在互联网上,就可以跑任何应用,满足大小数据处理的需求。 钛媒体注:今日,在首届阿里云分享会x云栖大会上,阿里云总裁胡晓明做了题为《计算将成DT世界引擎》的演讲,在胡晓明看来,从第一次工业革命到今天,社会经历了三次大的变革,引发https://www.tmtpost.com/1345421.html