网站开发常见模块,常见网站架构,建筑人才网评的助工,网站设计与网页建设这套面试题主要目的是帮助那些还没有java软件开发实际工作经验#xff0c;而正在努力寻找java软件开发工作的朋友在笔试时更好地赢得笔试和面试。由于这套面试题涉及的范围很泛#xff0c;很广#xff0c;很杂#xff0c;大家不可能一天两天就看完和学完这套面试宝典#…这套面试题主要目的是帮助那些还没有java软件开发实际工作经验而正在努力寻找java软件开发工作的朋友在笔试时更好地赢得笔试和面试。由于这套面试题涉及的范围很泛很广很杂大家不可能一天两天就看完和学完这套面试宝典即使你已经学过了有关的技术那么至少也需要一个月的时间才能消化和掌握这套面试宝典所以大家应该早作准备从拿到这套面试宝典之日起就要坚持在每天闲暇之余学习其中几道题目日积月累等到出去面试时一切都水到渠成面试时就自然会游刃有余了。答题时先答是什么再答有什么作用和要注意什么这部分最重要展现自己的心得答案的段落分别层次分明条理清晰都非常重要从这些表面的东西也可以看出一个人的习惯、办事风格、条理等。要讲你做出答案的思路过程或者说你记住答案的思想都写下来。把答题想着是辩论赛。答题就是给别人讲道理、摆事实。答题不局限于什么格式和形式就是要将自己的学识展现出来别因为人家题目本来就模棱两可你就心里胆怯和没底气了不敢回答了。你要大胆地指出对方题目很模糊和你的观点不要把面试官想得有多高其实他和你就是差不多的你想想如果他把你招进去了你们以后就是同事了可不是差不多的吗关于就业薪水如果你是应届生那不能要高工资好比大饼的故事没有文凭还想拿高工资就去中关村缺什么补什么吧少数人基础确实很好在校期间确实又做过一些项目那仍然是可以要到相对高的工资的。篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题需要全套面试笔记及答案可以在文末获取1.Java基础部分基础部分的顺序基本语法类相关的语法内部类的语法继承相关的语法异常的语法线程的语法集合的语法io 的语法虚拟机方面的语法。1、一个.java源文件中是否可以包括多个类不是内部类有什么限制√可以有多个类但只能有一个public的类并且public的类名必须与文件名相一致。2、Java有没有goto?√java中的保留字现在没有在java中使用。3、说说和的区别。√和都可以用作逻辑与的运算符表示逻辑与and当运算符两边的表达式的结果都为true时整个运算结果才为true否则只要有一方为false则结果为false。还具有短路的功能即如果第一个表达式为false则不再计算第二个表达式例如对于if(str ! null !str.equals(“”))表达式当str为null时后面的表达式不会执行所以不会出现NullPointerException如果将改为则会抛出NullPointerException异常。If(x33 y0) y会增长If(x33 y0)不会增长还可以用作位运算符当操作符两边的表达式不是boolean类型时表示按位与操作我们通常使用0x0f来与一个整数进行运算来获取该整数的最低4个bit位例如0x31 0x0f的结果为0x01。备注这道题先说两者的共同点再说出和的特殊之处并列举一些经典的例子来表明自己理解透彻深入、实际经验丰富。4、在JAVA中如何跳出当前的多重嵌套循环√在Java中要想跳出多重循环可以在外面的循环语句前定义一个标号然后在里层循环体的代码中使用带有标号的break 语句即可跳出外层循环。例如ok:for(int i0;i10;i) {for(int j0;j10;j) {System.out.println(“i” i “,j” j);if(j 5) break ok;}}另外我个人通常并不使用标号这种方式而是让外层的循环条件表达式的结果可以受到里层循环体代码的控制例如要在二维数组中查找到某个数字。int arr[][] {{1,2,3},{4,5,6,7},{9}};boolean found false;for(int i0;iarr.length !found;i) {for(int j0;jarr[i].length;j){System.out.println(“i” i “,j” j);if(arr[i][j] 5) {found true;break;}}}5、switch语句能否作用在byte上能否作用在long上能否作用在String上?在switchexpr1中expr1只能是一个整数表达式或者枚举常量更大字体整数表达式可以是int基本类型或Integer包装类型由于byte,short,char都可以隐含转换为int所以这些类型以及这些类型的包装类型也是可以的。显然long和String类型都不符合switch的语法规定并且不能被隐式转换成int类型所以它们不能作用于swtich语句中。6、short s1 1; s1 s1 1;有什么错? short s1 1; s1 1;有什么错?对于short s1 1; s1 s1 1; 由于s11运算时会自动提升表达式的类型所以结果是int型再赋值给short类型s1时编译器将报告需要强制转换类型的错误。对于short s1 1; s1 1;由于 是java语言规定的运算符java编译器会对它进行特殊处理因此可以正确编译。7、char型变量中能不能存贮一个中文汉字?为什么?char型变量是用来存储Unicode编码的字符的unicode编码字符集中包含了汉字所以char型变量中当然可以存储汉字啦。不过如果某个特殊的汉字没有被包含在unicode编码字符集中那么这个char型变量中就不能存储这个特殊汉字。补充说明unicode编码占用两个字节所以char类型的变量也是占用两个字节。备注后面一部分回答虽然不是在正面回答题目但是为了展现自己的学识和表现自己对问题理解的透彻深入可以回答一些相关的知识做到知无不言言无不尽。8、用最有效率的方法算出2乘以8等於几?2 3因为将一个数左移n位就相当于乘以了2的n次方那么一个数乘以8只要将其左移3位即可而位运算cpu直接支持的效率最高所以2乘以8等於几的最效率的方法是2 3。9、请设计一个一百亿的计算器首先要明白这道题目的考查点是什么一是大家首先要对计算机原理的底层细节要清楚、要知道加减法的位运算原理和知道计算机中的算术运算会发生越界的情况二是要具备一定的面向对象的设计思想。首先计算机中用固定数量的几个字节来存储的数值所以计算机中能够表示的数值是有一定的范围的为了便于讲解和理解我们先以byte 类型的整数为例它用1个字节进行存储表示的最大数值范围为-128到127。-1在内存中对应的二进制数据为11111111如果两个-1相加不考虑Java运算时的类型提升运算后会产生进位二进制结果为1,11111110由于进位后超过了byte类型的存储空间所以进位部分被舍弃即最终的结果为11111110也就是-2这正好利用溢位的方式实现了负数的运算。-128在内存中对应的二进制数据为10000000如果两个-128相加不考虑Java运算时的类型提升运算后会产生进位二进制结果为1,00000000由于进位后超过了byte类型的存储空间所以进位部分被舍弃即最终的结果为00000000也就是0这样的结果显然不是我们期望的这说明计算机中的算术运算是会发生越界情况的两个数值的运算结果不能超过计算机中的该类型的数值范围。由于Java中涉及表达式运算时的类型自动提升我们无法用byte类型来做演示这种问题和现象的实验大家可以用下面一个使用整数做实验的例子程序体验一下int a Integer.MAX_VALUE;int b Integer.MAX_VALUE;int sum a b;System.out.println(“a”a”,b”b”,sum”sum);先不考虑long类型由于int的正数范围为2的31次方表示的最大数值约等于2*1000*1000*1000也就是20亿的大小所以要实现一个一百亿的计算器我们得自己设计一个类可以用于表示很大的整数并且提供了与另外一个整数进行加减乘除的功能大概功能如下这个类内部有两个成员变量一个表示符号另一个用字节数组表示数值的二进制数有一个构造方法把一个包含有多位数值的字符串转换到内部的符号和字节数组中提供加减乘除的功能public class BigInteger{int sign;byte[] val;public Biginteger(String val) {sign ;val ;}public BigInteger add(BigInteger other) {}public BigInteger subtract(BigInteger other) {}public BigInteger multiply(BigInteger other){}public BigInteger divide(BigInteger other){}}备注要想写出这个类的完整代码是非常复杂的如果有兴趣的话可以参看jdk中自带的java.math.BigInteger类的源码。面试的人也知道谁都不可能在短时间内写出这个类的完整代码的他要的是你是否有这方面的概念和意识他最重要的还是考查你的能力所以你不要因为自己无法写出完整的最终结果就放弃答这道题你要做的就是你比别人写得多证明你比别人强你有这方面的思想意识就可以了毕竟别人可能连题目的意思都看不懂什么都没写你要敢于答这道题即使只答了一部分那也与那些什么都不懂的人区别出来拉开了距离算是矮子中的高个机会当然就属于你了。另外答案中的框架代码也很重要体现了一些面向对象设计的功底特别是其中的方法命名很专业用的英文单词很精准这也是能力、经验、专业性、英语水平等多个方面的体现会给人留下很好的印象在编程能力和其他方面条件差不多的情况下英语好除了可以使你获得更多机会外薪水可以高出一千元。10、使用final关键字修饰一个变量时是引用不能变还是引用的对象不能变使用final关键字修饰一个变量时是指引用变量不能变引用变量所指向的对象中的内容还是可以改变的。例如对于如下语句final StringBuffer anew StringBuffer(immutable);执行如下语句将报告编译期错误anew StringBuffer();但是执行如下语句则可以通过编译a.append( broken!);有人在定义方法的参数时可能想采用如下形式来阻止方法内部修改传进来的参数对象public void method(final StringBuffer param){}实际上这是办不到的在该方法内部仍然可以增加如下代码来修改参数对象param.append(a);11、和equals方法究竟有什么区别单独把一个东西说清楚然后再说清楚另一个这样它们的区别自然就出来了混在一起说则很难说清楚操作符专门用来比较两个变量的值是否相等也就是用于比较变量所对应的内存中所存储的数值是否相同要比较两个基本类型的数据或两个引用变量是否相等只能用操作符。如果一个变量指向的数据是对象类型的那么这时候涉及了两块内存对象本身占用一块内存堆内存变量也占用一块内存例如Objet obj new Object();变量obj是一个内存new Object()是另一个内存此时变量obj所对应的内存中存储的数值就是对象占用的那块内存的首地址。对于指向对象类型的变量如果要比较两个变量是否指向同一个对象即要看这两个变量所对应的内存中的数值是否相等这时候就需要用操作符进行比较。equals方法是用于比较两个独立对象的内容是否相同就好比去比较两个人的长相是否相同它比较的两个对象是独立的。例如对于下面的代码String anew String(foo);String bnew String(foo);两条new语句创建了两个对象然后用a,b这两个变量分别指向了其中一个对象这是两个不同的对象它们的首地址是不同的即a和b中存储的数值是不相同的所以表达式ab将返回false而这两个对象中的内容是相同的所以表达式a.equals(b)将返回true。在实际开发中我们经常要比较传递进行来的字符串内容是否等例如String input …;input.equals(“quit”)许多人稍不注意就使用进行比较了这是错误的随便从网上找几个项目实战的教学视频看看里面就有大量这样的错误。记住字符串的比较基本上都是使用equals方法。如果一个类没有自己定义equals方法那么它将继承Object类的equals方法Object类的equals方法的实现代码如下boolean equals(Object o){return thiso;}这说明如果一个类没有自己定义equals方法它默认的equals方法从Object 类继承的就是使用操作符也是在比较两个变量指向的对象是否是同一对象这时候使用equals和使用会得到同样的结果如果比较的是两个独立的对象则总返回false。如果你编写的类希望能够比较该类创建的两个实例对象的内容是否相同那么你必须覆盖equals方法由你自己写代码来决定在什么情况即可认为两个对象的内容是相同的。12、静态变量和实例变量的区别在语法定义上的区别静态变量前要加static关键字而实例变量前则不加。在程序运行时的区别实例变量属于某个对象的属性必须创建了实例对象其中的实例变量才会被分配空间才能使用这个实例变量。静态变量不属于某个实例对象而是属于类所以也称为类变量只要程序加载了类的字节码不用创建任何实例对象静态变量就会被分配空间静态变量就可以被使用了。总之实例变量必须创建对象后才可以通过这个对象来使用静态变量则可以直接使用类名来引用。例如对于下面的程序无论创建多少个实例对象永远都只分配了一个staticVar变量并且每创建一个实例对象这个staticVar就会加1但是每创建一个实例对象就会分配一个instanceVar即可能分配多个instanceVar并且每个instanceVar的值都只自加了1次。public class VariantTest{public static int staticVar 0;public int instanceVar 0;public VariantTest(){staticVar;instanceVar;System.out.println(“staticVar” staticVar ”,instanceVar” instanceVar);}}备注这个解答除了说清楚两者的区别外最后还用一个具体的应用例子来说明两者的差异体现了自己有很好的解说问题和设计案例的能力思维敏捷超过一般程序员有写作能力13、是否可以从一个static方法内部发出对非static方法的调用不可以。因为非static方法是要与对象关联在一起的必须创建一个对象后才可以在该对象上进行方法调用而static方法调用时不需要创建对象可以直接调用。也就是说当一个static方法被调用时可能还没有创建任何实例对象如果从一个static方法中发出对非static方法的调用那个非static方法是关联到哪个对象上的呢这个逻辑无法成立所以一个static方法内部不可以发出对非static方法的调用。14、Integer与int的区别int是java提供的8种原始数据类型之一。Java为每个原始类型提供了封装类Integer是java为int提供的封装类。int的默认值为0而Integer的默认值为null即Integer可以区分出未赋值和值为0的区别int则无法表达出未赋值的情况例如要想表达出没有参加考试和考试成绩为0的区别则只能使用Integer。在JSP开发中Integer的默认为null所以用el表达式在文本框中显示时值为空白字符串而int默认的默认值为0所以用el表达式在文本框中显示时结果为0所以int不适合作为web层的表单数据的类型。在Hibernate中如果将OID定义为Integer类型那么Hibernate就可以根据其值是否为null而判断一个对象是否是临时的如果将OID定义为了int类型还需要在hbm映射文件中设置其unsaved-value属性为0。另外Integer提供了多个与整数相关的操作方法例如将一个字符串转换成整数Integer中还定义了表示整数的最大值和最小值的常量。15、Math.round(11.5)等於多少? Math.round(-11.5)等於多少?Math类中提供了三个与取整有关的方法ceil、floor、round这些方法的作用与它们的英文名称的含义相对应例如ceil的英文意义是天花板该方法就表示向上取整Math.ceil(11.3)的结果为12,Math.ceil(-11.3)的结果是-11floor的英文意义是地板该方法就表示向下取整Math.ceil(11.6)的结果为11,Math.ceil(-11.6)的结果是-12最难掌握的是round方法它表示“四舍五入”算法为Math.floor(x0.5)即将原来的数字加上0.5后再向下取整所以Math.round(11.5)的结果为12Math.round(-11.5)的结果为-11。16、下面的代码有什么不妥之处?1. if(username.equals(“zxx”){}2.intx 1;return x1?true:false;17、请说出作用域publicprivateprotected以及不写时的区别这四个作用域的可见范围如下表所示。说明如果在修饰的元素上面没有写任何访问修饰符则表示friendly。作用域 当前类 同一package 子孙类 其他packagepublic √ √ √ √protected √ √ √ ×friendly √ √ × ×private √ × × ×备注只要记住了有4种访问权限4个访问范围然后将全选和范围在水平和垂直方向上分别按排从小到大或从大到小的顺序排列就很容易画出上面的图了。18、Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?Overload是重载的意思Override是覆盖的意思也就是重写。重载Overload表示同一个类中可以有多个名称相同的方法但这些方法的参数列表各不相同即参数个数或类型不同。重写Override表示子类中的方法可以与父类中的某个方法的名称和参数完全相同通过子类创建的实例对象调用这个方法时将调用子类中的定义方法这相当于把父类中定义的那个完全相同的方法给覆盖了这也是面向对象编程的多态性的一种表现。子类覆盖父类的方法时只能比父类抛出更少的异常或者是抛出父类抛出的异常的子异常因为子类可以解决父类的一些问题不能比父类有更多的问题。子类方法的访问权限只能比父类的更大不能更小。如果父类的方法是private类型那么子类则不存在覆盖的限制相当于子类中增加了一个全新的方法。至于Overloaded的方法是否可以改变返回值的类型这个问题要看你倒底想问什么呢这个题目很模糊。如果几个Overloaded的方法的参数列表不一样它们的返回者类型当然也可以不一样。但我估计你想问的问题是如果两个方法的参数列表完全一样是否可以让它们的返回值不同来实现重载Overload。这是不行的我们可以用反证法来说明这个问题因为我们有时候调用一个方法时也可以不定义返回结果变量即不要关心其返回结果例如我们调用map.remove(key)方法时虽然remove方法有返回值但是我们通常都不会定义接收返回结果的变量这时候假设该类中有两个名称和参数列表完全相同的方法仅仅是返回类型不同java就无法确定编程者倒底是想调用哪个方法了因为它无法通过返回结果类型来判断。override可以翻译为覆盖从字面就可以知道它是覆盖了一个方法并且对其重写以求达到不同的作用。对我们来说最熟悉的覆盖就是对接口方法的实现在接口中一般只是对方法进行了声明而我们在实现时就需要实现接口声明的所有方法。除了这个典型的用法以外我们在继承中也可能会在子类覆盖父类中的方法。在覆盖要注意以下的几点1、覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配才能达到覆盖的效果2、覆盖的方法的返回值必须和被覆盖的方法的返回一致3、覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致或者是其子类4、被覆盖的方法不能为private否则在其子类中只是新定义了一个方法并没有对其进行覆盖。overload对我们来说可能比较熟悉可以翻译为重载它是指我们可以定义一些名称相同的方法通过定义不同的输入参数来区分这些方法然后再调用时VM就会根据不同的参数样式来选择合适的方法执行。在使用重载要注意以下的几点1、在使用重载时只能通过不同的参数样式。例如不同的参数类型不同的参数个数不同的参数顺序当然同一方法内的几个参数类型必须不一样例如可以是fun(int,float)但是不能为fun(int,int)2、不能通过访问权限、返回类型、抛出的异常进行重载3、方法的异常类型和数目不会对重载造成影响4、对于继承来说如果某一方法在父类中是访问权限是priavte那么就不能在子类对其进行重载如果定义的话也只是定义了一个新方法而不会达到重载的效果。19、构造器Constructor是否可被override?构造器Constructor不能被继承因此不能重写Override但可以被重载Overload。20、接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承具体类(concrete class)? 抽象类中是否可以有静态的main方法接口可以继承接口。抽象类可以实现(implements)接口抽象类是可继承具体类。抽象类中可以有静态的main方法。备注只要明白了接口和抽象类的本质和作用这些问题都很好回答你想想如果你是java语言的设计者你是否会提供这样的支持如果不提供的话有什么理由吗如果你没有道理不提供那答案就是肯定的了。只有记住抽象类与普通类的唯一区别就是不能创建实例对象和允许有abstract方法。21、写clone()方法时通常都有一行代码是什么clone 有缺省行为super.clone();因为首先要把父类中的成员复制到位然后才是复制自己的成员。22、面向对象的特征有哪些方面计算机软件系统是现实生活中的业务在计算机中的映射而现实生活中的业务其实就是一个个对象协作的过程。面向对象编程就是按现实业务一样的方式将程序代码按一个个对象进行组织和编写让计算机系统能够识别和理解用对象方式组织和编写的程序代码这样就可以把现实生活中的业务对象映射到计算机系统中。面向对象的编程语言有封装、继承 、抽象、多态等4个主要的特征。1封装封装是保证软件部件具有优良的模块性的基础封装的目标就是要实现软件部件的“高内聚、低耦合”防止程序相互依赖性而带来的变动影响。在面向对象的编程语言中对象是封装的最基本单位面向对象的封装比传统语言的封装更为清晰、更为有力。面向对象的封装就是把描述一个对象的属性和行为的代码封装在一个“模块”中也就是一个类中属性用变量定义行为用方法进行定义方法可以直接访问同一个对象中的属性。通常情况下只要记住让变量和访问这个变量的方法放在一起将一个类中的成员变量全部定义成私有的只有这个类自己的方法才可以访问到这些成员变量这就基本上实现对象的封装就很容易找出要分配到这个类上的方法了就基本上算是会面向对象的编程了。把握一个原则把对同一事物进行操作的方法和相关的方法放在同一个类中把方法和它操作的数据放在同一个类中。例如人要在黑板上画圆这一共涉及三个对象人、黑板、圆画圆的方法要分配给哪个对象呢由于画圆需要使用到圆心和半径圆心和半径显然是圆的属性如果将它们在类中定义成了私有的成员变量那么画圆的方法必须分配给圆它才能访问到圆心和半径这两个属性人以后只是调用圆的画圆方法、表示给圆发给消息而已画圆这个方法不应该分配在人这个对象上这就是面向对象的封装性即将对象封装成一个高度自治和相对封闭的个体对象状态属性由这个对象自己的行为方法来读取和改变。一个更便于理解的例子就是司机将火车刹住了刹车的动作是分配给司机还是分配给火车显然应该分配给火车因为司机自身是不可能有那么大的力气将一个火车给停下来的只有火车自己才能完成这一动作火车需要调用内部的离合器和刹车片等多个器件协作才能完成刹车这个动作司机刹车的过程只是给火车发了一个消息通知火车要执行刹车动作而已。抽象抽象就是找出一些事物的相似和共性之处然后将这些事物归为一个类这个类只考虑这些事物的相似和共性之处并且会忽略与当前主题和目标无关的那些方面将注意力集中在与当前目标有关的方面。例如看到一只蚂蚁和大象你能够想象出它们的相同之处那就是抽象。抽象包括行为抽象和状态抽象两个方面。例如定义一个Person类如下class Person{String name;int age;}人本来是很复杂的事物有很多方面但因为当前系统只需要了解人的姓名和年龄所以上面定义的类中只包含姓名和年龄这两个属性这就是一种抽像使用抽象可以避免考虑一些与目标无关的细节。我对抽象的理解就是不要用显微镜去看一个事物的所有方面这样涉及的内容就太多了而是要善于划分问题的边界当前系统需要什么就只考虑什么。继承在定义和实现一个类的时候可以在一个已经存在的类的基础之上来进行把这个已经存在的类所定义的内容作为自己的内容并可以加入若干新的内容或修改原来的方法使之更适合特殊的需要这就是继承。继承是子类自动共享父类数据和方法的机制这是类之间的一种关系提高了软件的可重用性和可扩展性。多态多态是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定而是在程序运行期间才确定即一个引用变量倒底会指向哪个类的实例对象该引用变量发出的方法调用到底是哪个类中实现的方法必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类这样不用修改源程序代码就可以让引用变量绑定到各种不同的类实现上从而导致该引用调用的具体方法随之改变即不修改程序代码就可以改变程序运行时所绑定的具体代码让程序可以选择多个运行状态这就是多态性。多态性增强了软件的灵活性和扩展性。例如下面代码中的UserDao是一个接口它定义引用变量userDao指向的实例对象由daofactory.getDao()在执行的时候返回有时候指向的是UserJdbcDao这个实现有时候指向的是UserHibernateDao这个实现这样不用修改源代码就可以改变userDao指向的具体类实现从而导致userDao.insertUser()方法调用的具体代码也随之改变即有时候调用的是UserJdbcDao的insertUser方法有时候调用的是UserHibernateDao的insertUser方法UserDao userDao daofactory.getDao();userDao.insertUser(user);比喻人吃饭你看到的是左手还是右手23、java中实现多态的机制是什么靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象而程序调用的方法在运行期才动态绑定就是引用变量所指向的具体实例对象的方法也就是内存里正在运行的那个对象的方法而不是引用变量的类型中定义的方法。24、abstract class和interface有什么区别?含有abstract修饰符的class即为抽象类abstract 类不能创建的实例对象。含有abstract方法的类必须定义为abstract classabstract class类中的方法不必是抽象的。abstract class类中定义抽象方法必须在具体(Concrete)子类中实现所以不能有抽象构造方法或抽象静态方法。如果的子类没有实现抽象父类中的所有抽象方法那么子类也必须定义为abstract类型。接口interface可以说成是抽象类的一种特例接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型接口中的成员变量类型默认为public static final。下面比较一下两者的语法区别1.抽象类可以有构造方法接口中不能有构造方法。2.抽象类中可以有普通成员变量接口中没有普通成员变量3.抽象类中可以包含非抽象的普通方法接口中的所有方法必须都是抽象的不能有非抽象的普通方法。4. 抽象类中的抽象方法的访问类型可以是publicprotected和默认类型,虽然eclipse下不报错但应该也不行但接口中的抽象方法只能是public类型的并且默认即为public abstract类型。5. 抽象类中可以包含静态方法接口中不能包含静态方法6. 抽象类和接口中都可以包含静态成员变量抽象类中的静态成员变量的访问类型可以任意但接口中定义的变量只能是public static final类型并且默认即为public static final类型。7. 一个类可以实现多个接口但只能继承一个抽象类。下面接着再说说两者在应用上的区别接口更多的是在系统架构设计方法发挥作用主要用于定义模块之间的通信契约。而抽象类在代码实现方面发挥作用可以实现代码的重用例如模板方法设计模式是抽象类的一个典型应用假设某个项目的所有Servlet类都要用相同的方式进行权限判断、记录访问日志和处理异常那么就可以定义一个抽象的基类让所有的Servlet都继承这个抽象基类在抽象基类的service方法中完成权限判断、记录访问日志和处理异常的代码在各个子类中只是完成各自的业务逻辑代码伪代码如下public abstract class BaseServlet extends HttpServlet{public final void service(HttpServletRequest request, HttpServletResponse response) throws IOExcetion,ServletException {记录访问日志进行权限判断if(具有权限){try{doService(request,response);}catch(Excetpion e) {记录异常信息}}}protected abstract void doService(HttpServletRequest request, HttpServletResponse response) throws IOExcetion,ServletException;//注意访问权限定义成protected显得既专业又严谨因为它是专门给子类用的}public class MyServlet1 extends BaseServlet{protected void doService(HttpServletRequest request, HttpServletResponse response) throws IOExcetion,ServletException{本Servlet只处理的具体业务逻辑代码}}父类方法中间的某段代码不确定留给子类干就用模板方法设计模式。备注这道题的思路是先从总体解释抽象类和接口的基本概念然后再比较两者的语法细节最后再说两者的应用区别。比较两者语法细节区别的条理是先从一个类中的构造方法、普通成员变量和方法包括抽象方法静态变量和方法继承性等6个方面逐一去比较回答接着从第三者继承的角度的回答特别是最后用了一个典型的例子来展现自己深厚的技术功底。25、abstract的method是否可同时是static,是否可同时是native是否可同时是synchronized?abstract的method 不可以是static的因为抽象的方法是要被子类实现的而static与子类扯不上关系native方法表示该方法要用另外一种依赖平台的编程语言实现的不存在着被子类实现的问题所以它也不能是抽象的不能与abstract混用。例如FileOutputSteam类要硬件打交道底层的实现用的是操作系统相关的api实现例如在windows用c语言实现的所以查看jdk 的源代码可以发现FileOutputStream的open方法的定义如下private native void open(String name) throws FileNotFoundException;如果我们要用java调用别人写的c语言函数我们是无法直接调用的我们需要按照java的要求写一个c语言的函数又我们的这个c语言函数去调用别人的c语言函数。由于我们的c语言函数是按java的要求来写的我们这个c语言函数就可以与java对接上java那边的对接方式就是定义出与我们这个c函数相对应的方法java中对应的方法不需要写具体的代码但需要在前面声明native。关于synchronized与abstract合用的问题我觉得也不行因为在我几年的学习和开发中从来没见到过这种情况并且我觉得synchronized应该是作用在一个具体的方法上才有意义。而且方法上的synchronized同步所使用的同步锁对象是this而抽象方法上无法确定this是什么。26、什么是内部类Static Nested Class 和 Inner Class的不同。内部类就是在一个类的内部定义的类内部类中不能定义静态成员静态成员不是对象的特性只是为了找一个容身之处所以需要放到一个类中而已这么一点小事你还要把它放到类内部的一个类中过分了啊提供内部类不是为让你干这种事情无聊不让你干。我想可能是既然静态成员类似c语言的全局变量而内部类通常是用于创建内部对象用的所以把“全局变量”放在内部类中就是毫无意义的事情既然是毫无意义的事情就应该被禁止内部类可以直接访问外部类中的成员变量内部类可以定义在外部类的方法外面也可以定义在外部类的方法体中如下所示public class Outer{int out_x 0;public void method(){Inner1 inner1 new Inner1();public class Inner2 //在方法体内部定义的内部类{public method(){out_x 3;}}Inner2 inner2 new Inner2();}public class Inner1 //在方法体外面定义的内部类{}}在方法体外面定义的内部类的访问类型可以是public,protecte,默认的private等4种类型这就好像类中定义的成员变量有4种访问类型一样它们决定这个内部类的定义对其他类是否可见对于这种情况我们也可以在外面创建内部类的实例对象创建内部类的实例对象时一定要先创建外部类的实例对象然后用这个外部类的实例对象去创建内部类的实例对象代码如下Outer outer new Outer();Outer.Inner1 inner1 outer.new Innner1();在方法内部定义的内部类前面不能有访问类型修饰符就好像方法中定义的局部变量一样但这种内部类的前面可以使用final或abstract修饰符。这种内部类对其他类是不可见的其他类无法引用这种内部类但是这种内部类创建的实例对象可以传递给其他类访问。这种内部类必须是先定义后使用即内部类的定义代码必须出现在使用该类之前这与方法中的局部变量必须先定义后使用的道理也是一样的。这种内部类可以访问方法体中的局部变量但是该局部变量前必须加final修饰符。对于这些细节只要在eclipse写代码试试根据开发工具提示的各类错误信息就可以马上了解到。在方法体内部还可以采用如下语法来创建一种匿名内部类即定义某一接口或类的子类的同时还创建了该子类的实例对象无需为该子类定义名称public class Outer{public void start(){new Thread(new Runable(){public void run(){};}).start();}}最后在方法外部定义的内部类前面可以加上static关键字从而成为Static Nested Class它不再具有内部类的特性所有从狭义上讲它不是内部类。Static Nested Class与普通类在运行时的行为和功能上没有什么区别只是在编程引用时的语法上有一些差别它可以定义成public、protected、默认的、private等多种类型而普通类只能定义成public和默认的这两种类型。在外面引用Static Nested Class类的名称为“外部类名.内部类名”。在外面不需要创建外部类的实例对象就可以直接创建Static Nested Class例如假设Inner是定义在Outer类中的Static Nested Class那么可以使用如下语句创建Inner类Outer.Inner inner new Outer.Inner();由于static Nested Class不依赖于外部类的实例对象所以static Nested Class能访问外部类的非static成员变量。当在外部类中访问Static Nested Class时可以直接使用Static Nested Class的名字而不需要加上外部类的名字了在Static Nested Class中也可以直接引用外部类的static的成员变量不需要加上外部类的名字。在静态方法中定义的内部类也是Static Nested Class这时候不能在类前面加static关键字静态方法中的Static Nested Class与普通方法中的内部类的应用方式很相似它除了可以直接访问外部类中的static的成员变量还可以访问静态方法中的局部变量但是该局部变量前必须加final修饰符。备注首先根据你的印象说出你对内部类的总体方面的特点例如在两个地方可以定义可以访问外部类的成员变量不能定义静态成员这是大的特点。然后再说一些细节方面的知识例如几种定义方式的语法区别静态内部类以及匿名内部类。27、内部类可以引用它的包含类的成员吗有没有什么限制完全可以。如果不是静态内部类那没有什么限制如果你把静态嵌套类当作内部类的一种特例那在这种情况下不可以访问外部类的普通成员变量而只能访问外部类中的静态成员例如下面的代码class Outer{static int x;static class Inner{void test(){syso(x);}}}答题时也要能察言观色揣摩提问者的心思显然人家希望你说的是静态内部类不能访问外部类的成员但你一上来就顶牛这不好要先顺着人家让人家满意然后再说特殊情况让人家吃惊。28、Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类是否可以implements(实现)interface(接口)?可以继承其他类或实现其他接口。不仅是可以而是必须!29、super.getClass()方法调用下面程序的输出结果是多少import java.util.Date;publicclassTestextendsDate{publicstaticvoidmain(String[] args) {newTest().test();}publicvoidtest(){System.out.println(super.getClass().getName());}}很奇怪结果是Test这属于脑筋急转弯的题目在一个qq群有个网友正好问过这个问题我觉得挺有趣就研究了一下没想到今天还被你面到了哈哈。在test方法中直接调用getClass().getName()方法返回的是Test类名由于getClass()在Object类中定义成了final子类不能覆盖该方法所以在test方法中调用getClass().getName()方法其实就是在调用从父类继承的getClass()方法等效于调用super.getClass().getName()方法所以super.getClass().getName()方法返回的也应该是Test。如果想得到父类的名称应该用如下代码getClass().getSuperClass().getName();30、String是最基本的数据类型吗?基本数据类型包括byte、int、char、long、float、double、boolean和short。java.lang.String类是final类型的因此不可以继承这个类、不能修改这个类。为了提高效率节省空间我们应该用StringBuffer类31、String s Hello;s s world!;这两行代码执行后原始的String对象中的内容到底变了没有没有。因为String被设计成不可变(immutable)类所以它的所有对象都是不可变对象。在这段代码中s原先指向一个String对象内容是 Hello然后我们对s进行了操作那么s所指向的那个对象是否发生了改变呢答案是没有。这时s不指向原来那个对象了而指向了另一个 String对象内容为Hello world!原来那个对象还存在于内存之中只是s这个引用变量不再指向它了。通过上面的说明我们很容易导出另一个结论如果经常对字符串进行各种各样的修改或者说不可预见的修改那么使用String来代表字符串的话会引起很大的内存开销。因为 String对象建立之后不能再改变所以对于每一个不同的字符串都需要一个String对象来表示。这时应该考虑使用StringBuffer类它允许修改而不是每个不同的字符串都要生成一个新的对象。并且这两种类的对象转换十分容易。同时我们还可以知道如果要使用内容相同的字符串不必每次都new一个String。例如我们要在构造器中对一个名叫s的String引用变量进行初始化把它设置为初始值应当这样做public class Demo {private String s;...public Demo {s Initial Value;}...}而非s new String(Initial Value);后者每次都会调用构造器生成新对象性能低下且内存开销大并且没有意义因为String对象不可改变所以对于内容相同的字符串只要一个String对象来表示就可以了。也就说多次调用上面的构造器创建多个对象他们的String类型属性s都指向同一个对象。上面的结论还基于这样一个事实对于字符串常量如果内容相同Java认为它们代表同一个String对象。而用关键字new调用构造器总是会创建一个新的对象无论内容是否相同。至于为什么要把String类设计成不可变类是它的用途决定的。其实不只String很多Java标准类库中的类都是不可变的。在开发一个系统的时候我们有时候也需要设计不可变类来传递一组相关的值这也是面向对象思想的体现。不可变类有一些优点比如因为它的对象是只读的所以多线程并发访问也不会有任何问题。当然也有一些缺点比如每个不同的状态都要一个对象来代表可能会造成性能上的问题。所以Java标准类库还提供了一个可变版本即 StringBuffer。32、是否可以继承String类?String类是final类故不可以继承。33、String s new String(xyz);创建了几个String Object? 二者之间有什么区别两个或一个”xyz”对应一个对象这个对象放在字符串常量缓冲区常量”xyz”不管出现多少遍都是缓冲区中的那一个。New String每写一遍就创建一个新的对象它一句那个常量”xyz”对象的内容来创建出一个新String对象。如果以前就用过’xyz’这句代表就不会创建”xyz”自己了直接从缓冲区拿。34、String和StringBuffer的区别JAVA平台提供了两个类String和StringBuffer它们可以储存和操作字符串即包含多个字符的字符数据。这个String类提供了数值不可改变的字符串。而这个StringBuffer类提供的字符串进行修改。当你知道字符数据要改变的时候你就可以使用StringBuffer。典型地你可以使用StringBuffers来动态构造字符数据。另外String实现了equals方法new String(“abc”).equals(new String(“abc”)的结果为true,而StringBuffer没有实现equals方法所以new StringBuffer(“abc”).equals(new StringBuffer(“abc”)的结果为false。接着要举一个具体的例子来说明我们要把1到100的所有数字拼起来组成一个串。StringBuffer sbf new StringBuffer();for(int i0;i100;i){sbf.append(i);}上面的代码效率很高因为只创建了一个StringBuffer对象而下面的代码效率很低因为创建了101个对象。String str new String();for(int i0;i100;i){str str i;}在讲两者区别时应把循环的次数搞成10000然后用endTime-beginTime来比较两者执行的时间差异最后还要讲讲StringBuilder与StringBuffer的区别。String覆盖了equals方法和hashCode方法而StringBuffer没有覆盖equals方法和hashCode方法所以将StringBuffer对象存储进Java集合类中时会出现问题。35、如何把一段逗号分割的字符串转换成一个数组?如果不查jdk api我很难写出来我可以说说我的思路用正则表达式代码大概为String [] result orgStr.split(“,”);用 StingTokenizer ,代码为StringTokenizer tokener StringTokenizer(orgStr,”,”);String [] result new String[tokener .countTokens()];Int i0;while(tokener.hasNext(){result[i]toker.nextToken();}36、数组有没有length()这个方法? String有没有length()这个方法数组没有length()这个方法有length的属性。String有有length()这个方法。37、下面这条语句一共创建了多少个对象String sabcd;答对于如下代码String s1 a;String s2 s1 b;String s3 a b;System.out.println(s2 ab);System.out.println(s3 ab);第一条语句打印的结果为false第二条语句打印的结果为true这说明javac编译可以对字符串常量直接相加的表达式进行优化不必要等到运行期去进行加法运算处理而是在编译时去掉其中的加号直接将其编译成一个这些常量相连的结果。题目中的第一行代码被编译器在编译时优化后相当于直接定义了一个”abcd”的字符串所以上面的代码应该只创建了一个String对象。写如下两行代码String s a b c d;System.out.println(s abcd);最终打印的结果应该为true。38、try {}里有一个return语句那么紧跟在这个try后的finally {}里的code会不会被执行什么时候被执行在return前还是后?也许你的答案是在return之前但往更细地说我的答案是在return中间执行请看下面程序代码的运行结果publicclassTest {/***paramargs add by zxx ,Dec 9, 2008*/publicstaticvoidmain(String[] args) {//TODOAuto-generated method stubSystem.out.println(newTest().test());;}staticinttest(){intx 1;try{returnx;}finally{x;}}}---------执行结果 ---------1运行结果是1为什么呢主函数调用子函数并得到结果的过程好比主函数准备一个空罐子当子函数要返回结果时先把结果放在罐子里然后再将程序逻辑返回到主函数。所谓返回就是子函数说我不运行了你主函数继续运行吧这没什么结果可言结果是在说这话之前放进罐子里的。39、下面的程序代码输出的结果是多少public class smallT{public static void main(String args[]){smallT t new smallT();int b t.get();System.out.println(b);}public int get(){try{return 1 ;}finally{return 2 ;}}}返回的结果是2。我可以通过下面一个例子程序来帮助我解释这个答案从下面例子的运行结果中可以发现try中的return语句调用的函数先于finally中调用的函数执行也就是说return语句先执行finally语句后执行所以返回的结果是2。Return并不是让函数马上返回而是return语句执行后将把返回结果放置进函数栈中此时函数并不是马上返回它要执行finally语句后才真正开始返回。在讲解答案时可以用下面的程序来帮助分析publicclassTest {/***paramargs add by zxx ,Dec 9, 2008*/publicstaticvoidmain(String[] args) {//TODOAuto-generated method stubSystem.out.println(newTest().test());;}inttest(){try{returnfunc1();}finally{returnfunc2();}}intfunc1(){System.out.println(func1);return1;}intfunc2(){System.out.println(func2);return2;}}-----------执行结果-----------------func1func22结论finally中的代码比return 和break语句后执行40、final, finally, finalize的区别。final 用于声明属性方法和类分别表示属性不可变方法不可覆盖类不可继承。内部类要访问局部变量局部变量必须定义成final类型例如一段代码……finally是异常处理语句结构的一部分表示总是执行。finalize是Object类的一个方法在垃圾收集器执行的时候会调用被回收对象的此方法可以覆盖此方法提供垃圾收集时的其他资源回收例如关闭文件等。JVM不保证此方法总被调用41、运行时异常与一般异常有何异同异常表示程序运行过程中可能出现的非正常状态运行时异常表示虚拟机的通常操作中可能遇到的异常是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常但是并不要求必须声明抛出未被捕获的运行时异常。42、error和exception有什么区别?error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。 exception 表示一种设计或实现问题。也就是说它表示如果程序运行正常从不会发生的情况。43、Java中的异常处理机制的简单原理和应用。异常是指java程序运行时非编译所发生的非正常情况或错误与现实生活中的事件很相似现实生活中的事件可以包含事件发生的时间、地点、人物、情节等信息可以用一个对象来表示Java使用面向对象的方式来处理异常它把程序中发生的每个异常也都分别封装到一个对象来表示的该对象中包含有异常的信息。Java对异常进行了分类不同类型的异常分别用不同的Java类表示所有异常的根类为java.lang.ThrowableThrowable下面又派生了两个子类Error和ExceptionError 表示应用程序本身无法克服和恢复的一种严重问题程序只有死的份了例如说内存溢出和线程死锁等系统问题。Exception表示程序还能够克服和恢复的问题其中又分为系统异常和普通异常系统异常是软件本身缺陷所导致的问题也就是软件开发人员考虑不周所导致的问题软件使用者无法克服和恢复这种问题但在这种问题下还可以让软件系统继续运行或者让软件死掉例如数组脚本越界ArrayIndexOutOfBoundsException空指针异常NullPointerException、类转换异常ClassCastException普通异常是运行环境的变化或异常所导致的问题是用户能够克服的问题例如网络断线硬盘空间不够发生这样的异常后程序不应该死掉。java为系统异常和普通异常提供了不同的解决方案编译器强制普通异常必须try..catch处理或用throws声明继续抛给上层调用方法处理所以普通异常也称为checked异常而系统异常可以处理也可以不处理所以编译器不强制用try..catch处理或用throws声明所以系统异常也称为unchecked异常。提示答题者就按照三个级别去思考虚拟机必须宕机的错误程序可以死掉也可以不死掉的错误程序不应该死掉的错误44、请写出你最常见到的5个runtime exception。这道题主要考你的代码量到底多大如果你长期写代码的应该经常都看到过一些系统方面的异常你不一定真要回答出5个具体的系统异常但你要能够说出什么是系统异常以及几个系统异常就可以了当然这些异常完全用其英文名称来写是最好的如果实在写不出那就用中文吧有总比没有强所谓系统异常就是…..它们都是RuntimeException的子类在jdk doc中查RuntimeException类就可以看到其所有的子类列表也就是看到了所有的系统异常。我比较有印象的系统异常有NullPointerException、ArrayIndexOutOfBoundsException、ClassCastException。45、JAVA语言如何进行异常处理关键字throws,throw,try,catch,finally分别代表什么意义在try块中可以抛出异常吗46、java中有几种方法可以实现一个线程用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用java5以前有如下两种第一种new Thread(){}.start();这表示调用Thread子类对象的run方法new Thread(){}表示一个Thread的匿名子类的实例对象子类加上run方法后的代码如下new Thread(){public void run(){}}.start();第二种new Thread(new Runnable(){}).start();这表示调用Thread对象接受的Runnable对象的run方法new Runnable(){}表示一个Runnable的匿名子类的实例对象,runnable的子类加上run方法后的代码如下new Thread(new Runnable(){public void run(){}}).start();从java5开始还有如下一些线程池创建多线程的方式ExecutorService pool Executors.newFixedThreadPool(3)for(int i0;i10;i){pool.execute(new Runable(){public void run(){}});}Executors.newCachedThreadPool().execute(new Runable(){public void run(){}});Executors.newSingleThreadExecutor().execute(new Runable(){public void run(){}});有两种实现方法分别使用new Thread()和new Thread(runnable)形式第一种直接调用thread的run方法所以我们往往使用Thread子类即new SubThread()。第二种调用runnable的run方法。有两种实现方法分别是继承Thread类与实现Runnable接口用synchronized关键字修饰同步方法反对使用stop()是因为它不安全。它会解除由线程获取的所有锁定而且如果对象处于一种不连贯状态那么其他线程能在那种状态下检查和修改它们。结果很难检查出真正的问题所在。suspend()方法容易发生死锁。调用suspend()的时候目标线程会停下来但却仍然持有在这之前获得的锁定。此时其他任何线程都不能访问锁定的资源除非被挂起的线程恢复运行。对任何线程来说如果它们想恢复目标线程同时又试图使用任何一个锁定的资源就会造成死锁。所以不应该使用suspend()而应在自己的Thread类中置入一个标志指出线程应该活动还是挂起。若标志指出线程应该挂起便用wait()命其进入等待状态。若标志指出线程应当恢复则用一个notify()重新启动线程。47、sleep() 和 wait() 有什么区别?网上的答案sleep是线程类Thread的方法导致此线程暂停执行指定时间给执行机会给其他线程但是监控状态依然保持到时后会自动恢复。调用sleep不会释放对象锁。 wait是Object类的方法对此对象调用wait方法导致本线程放弃对象锁进入等待此对象的等待锁定池只有针对此对象发出notify方法或notifyAll后本线程才进入对象锁定池准备获得对象锁进入运行状态。sleep就是正在执行的线程主动让出cpucpu去执行其他线程在sleep指定的时间过后cpu才会回到这个线程上继续往下执行如果当前线程进入了同步锁sleep方法并不会释放锁即使当前线程使用sleep方法让出了cpu但其他被同步锁挡住了的线程也无法得到执行。wait是指在一个已经进入了同步锁的线程内让自己暂时让出同步锁以便其他正在等待此锁的线程可以得到同步锁并运行只有其他线程调用了notify方法notify并不释放锁只是告诉调用过wait方法的线程可以去参与获得锁的竞争了但不是马上得到锁因为锁还在别人手里别人还没释放。如果notify方法后面的代码还有很多需要这些代码执行完后才会释放锁可以在notfiy方法后增加一个等待和一些代码看看效果调用wait方法的线程就会解除wait状态和程序可以再次得到锁后继续向下运行。对于wait的讲解一定要配合例子代码来说明才显得自己真明白。packagecom.huawei.interview;publicclassMultiThread {/***paramargs*/publicstaticvoidmain(String[] args) {//TODOAuto-generated method stubnewThread(newThread1()).start();try{Thread.sleep(10);}catch(InterruptedException e) {//TODOAuto-generated catch blocke.printStackTrace();}newThread(newThread2()).start();}privatestaticclassThread1implementsRunnable{Overridepublicvoidrun() {//TODOAuto-generated method stub//由于这里的Thread1和下面的Thread2内部run方法要用同一对象作为监视器我们这里不能用this因为在Thread2里面的this和这个Thread1的this不是同一个对象。我们用MultiThread.class这个字节码对象当前虚拟机里引用这个变量时指向的都是同一个对象。synchronized(MultiThread.class) {System.out.println(enter thread1...);System.out.println(thread1 is waiting);try{//释放锁有两种方式第一种方式是程序自然离开监视器的范围也就是离开了synchronized关键字管辖的代码范围另一种方式就是在synchronized关键字管辖的代码内部调用监视器对象的wait方法。这里使用wait方法释放锁。MultiThread.class.wait();}catch(InterruptedException e) {//TODOAuto-generated catch blocke.printStackTrace();}System.out.println(thread1 is going on...);System.out.println(thread1 is being over!);}}}privatestaticclassThread2implementsRunnable{Overridepublicvoidrun() {//TODOAuto-generated method stubsynchronized(MultiThread.class) {System.out.println(enter thread2...);System.out.println(thread2 notify other thread can release wait status..);//由于notify方法并不释放锁 即使thread2调用下面的sleep方法休息了10毫秒但thread1仍然不会执行因为thread2没有释放锁所以Thread1无法得不到锁。MultiThread.class.notify();System.out.println(thread2 is sleeping ten millisecond...);try{Thread.sleep(10);}catch(InterruptedException e) {//TODOAuto-generated catch blocke.printStackTrace();}System.out.println(thread2 is going on...);System.out.println(thread2 is being over!);}}}}48、同步和异步有何异同在什么情况下分别使用他们举例说明。如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到或者正在读的数据可能已经被另一个线程写过了那么这些数据就是共享数据必须进行同步存取。当应用程序在对象上调用了一个需要花费很长时间来执行的方法并且不希望让程序等待方法的返回时就应该使用异步编程在很多情况下采用异步途径往往更有效率。49. 下面两个方法同步吗自己发明class Test{synchronizedstaticvoidsayHello3(){}synchronizedvoidgetX(){}}50、多线程有几种实现方法?同步有几种实现方法?多线程有两种实现方法分别是继承Thread类与实现Runnable接口同步的实现方面有两种分别是synchronized,wait与notifywait():使一个线程处于等待状态并且释放所持有的对象的lock。sleep():使一个正在运行的线程处于睡眠状态是一个静态方法调用此方法要捕InterruptedException异常。notify():唤醒一个处于等待状态的线程注意的是在调用此方法的时候并不能确切的唤醒某一M确定唤醒哪个线程而且不是按优先级。Allnotity():唤醒所有处入等待状态的线程注意并不是给所有唤醒线程一个对象的锁而是让它们竞争。51、启动一个线程是用run()还是start()? .启动一个线程是调用start()方法使线程就绪状态以后可以被调度为运行状态一个线程必须关联一些具体的执行代码run()方法是该线程所关联的执行代码。52、当一个线程进入一个对象的一个synchronized方法后其它线程是否可进入此对象的其它方法?分几种情况1.其他方法前是否加了synchronized关键字如果没加则能。2.如果这个方法内部调用了wait则可以进入其他synchronized方法。3.如果其他个方法都加了synchronized关键字并且内部没有调用wait则不能。4.如果其他方法是static它用的同步锁是当前类的字节码与非静态的方法不能同步因为非静态的方法用的是this。53、线程的基本概念、线程的基本状态以及状态之间的关系一个程序中可以有多条执行线索同时执行一个线程就是程序中的一条执行线索每个线程上都关联有要执行的代码即可以有多段程序代码同时运行每个程序至少都有一个线程即main方法执行的那个线程。如果只是一个cpu它怎么能够同时执行多段程序呢这是从宏观上来看的cpu一会执行a线索一会执行b线索切换时间很快给人的感觉是a,b在同时执行好比大家在同一个办公室上网只有一条链接到外部网线其实这条网线一会为a传数据一会为b传数据由于切换时间很短暂所以大家感觉都在同时上网。状态就绪运行synchronize阻塞wait和sleep挂起结束。wait必须在synchronized内部调用。调用线程的start方法后线程进入就绪状态线程调度系统将就绪状态的线程转为运行状态遇到synchronized语句时由运行状态转为阻塞当synchronized获得锁后由阻塞转为运行在这种情况可以调用wait方法转为挂起状态当线程关联的代码执行完后线程变为结束状态。54、简述synchronized和java.util.concurrent.locks.Lock的异同主要相同点Lock能完成synchronized所实现的所有功能主要不同点Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁而Lock一定要求程序员手工释放并且必须在finally从句中释放。Lock还有更强大的功能例如它的tryLock方法可以非阻塞方式去拿锁。举例说明对下面的题用lock进行了改写packagecom.huawei.interview;importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;publicclassThreadTest {/***paramargs*/privateintj;privateLock lock newReentrantLock();publicstaticvoidmain(String[] args) {//TODOAuto-generated method stubThreadTest tt newThreadTest();for(inti0;i2;i){newThread(tt.newAdder()).start();newThread(tt.newSubtractor()).start();}}privateclassSubtractorimplementsRunnable{Overridepublicvoidrun() {//TODOAuto-generated method stubwhile(true){/*synchronized (ThreadTest.this) {System.out.println(j-- j--);//这里抛异常了锁能释放吗}*/lock.lock();try{System.out.println(j-- j--);}finally{lock.unlock();}}}}privateclassAdderimplementsRunnable{Overridepublicvoidrun() {//TODOAuto-generated method stubwhile(true){/*synchronized (ThreadTest.this) {System.out.println(j j);}*/lock.lock();try{System.out.println(j j);}finally{lock.unlock();}}}}}55、设计4个线程其中两个线程每次对j增加1另外两个线程对j每次减少1。写出程序。以下程序使用内部类实现线程对j增减的时候没有考虑顺序问题。public class ThreadTest1{private int j;public static void main(String args[]){ThreadTest1 ttnew ThreadTest1();Inc inctt.new Inc();Dec dectt.new Dec();for(int i0;i2;i){Thread tnew Thread(inc);t.start();tnew Thread(dec);t.start();}}private synchronized void inc(){j;System.out.println(Thread.currentThread().getName()-inc:j);}private synchronized void dec(){j--;System.out.println(Thread.currentThread().getName()-dec:j);}class Inc implements Runnable{public void run(){for(int i0;i100;i){inc();}}}class Dec implements Runnable{public void run(){for(int i0;i100;i){dec();}}}}----------随手再写的一个-------------class A{JManger j new JManager();main(){new A().call();}void call{for(int i0;i2;i){new Thread(new Runnable(){ public void run(){while(true){j.accumulate()}}}).start();new Thread(new Runnable(){ public void run(){while(true){j.sub()}}}).start();}}}class JManager{private j 0;public synchronized void subtract(){j--}public synchronized void accumulate(){j;}}56、子线程循环10次接着主线程循环100接着又回到子线程循环10次接着再回到主线程又循环100如此循环50次请写出程序。最终的程序代码如下publicclassThreadTest {/***paramargs*/publicstaticvoidmain(String[] args) {//TODOAuto-generated method stubnewThreadTest().init();}publicvoidinit(){finalBusiness business newBusiness();newThread(newRunnable(){publicvoidrun() {for(inti0;i50;i){business.SubThread(i);}}}).start();for(inti0;i50;i){business.MainThread(i);}}privateclassBusiness{booleanbShouldSub true;//这里相当于定义了控制该谁执行的一个信号灯publicsynchronizedvoidMainThread(inti){if(bShouldSub)try{this.wait();}catch(InterruptedException e) {//TODOAuto-generated catch blocke.printStackTrace();}for(intj0;j5;j){System.out.println(Thread.currentThread().getName() :i i ,j j);}bShouldSub true;this.notify();}publicsynchronizedvoidSubThread(inti){if(!bShouldSub)try{this.wait();}catch(InterruptedException e) {//TODOAuto-generated catch blocke.printStackTrace();}for(intj0;j10;j){System.out.println(Thread.currentThread().getName() :i i ,j j);}bShouldSub false;this.notify();}}}备注不可能一上来就写出上面的完整代码最初写出来的代码如下问题在于两个线程的代码要参照同一个变量即这两个线程的代码要共享数据所以把这两个线程的执行代码搬到同一个类中去packagecom.huawei.interview.lym;publicclassThreadTest {privatestaticbooleanbShouldMainfalse;publicstaticvoidmain(String[] args) {//TODOAuto-generated method stub/*new Thread(){public void run(){for(int i0;i50;i){for(int j0;j10;j){System.out.println(i i ,j j);}}}}.start();*///final String str new String();newThread(newRunnable(){publicvoidrun(){for(inti0;i50;i){synchronized(ThreadTest.class) {if(bShouldMain){try{ThreadTest.class.wait();}catch(InterruptedException e) {e.printStackTrace();}}for(intj0;j10;j){System.out.println(Thread.currentThread().getName() i i ,j j);}bShouldMaintrue;ThreadTest.class.notify();}}}}).start();for(inti0;i50;i){synchronized(ThreadTest.class) {if(!bShouldMain){try{ThreadTest.class.wait();}catch(InterruptedException e) {e.printStackTrace();}}for(intj0;j5;j){System.out.println(Thread.currentThread().getName() i i ,j j);}bShouldMainfalse;ThreadTest.class.notify();}}}}下面使用jdk5中的并发库来实现的import java.util.concurrent.Executors;import java.util.concurrent.ExecutorService;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;import java.util.concurrent.locks.Condition;public class ThreadTest{private static Lock lock new ReentrantLock();private static Condition subThreadCondition lock.newCondition();private static boolean bBhouldSubThread false;public static void main(String [] args){ExecutorService threadPool Executors.newFixedThreadPool(3);threadPool.execute(new Runnable(){public void run(){for(int i0;i50;i){lock.lock();try{if(!bBhouldSubThread)subThreadCondition.await();for(int j0;j10;j){System.out.println(Thread.currentThread().getName() ,j j);}bBhouldSubThread false;subThreadCondition.signal();}catch(Exception e){}finally{lock.unlock();}}}});threadPool.shutdown();for(int i0;i50;i){lock.lock();try{if(bBhouldSubThread)subThreadCondition.await();for(int j0;j10;j){System.out.println(Thread.currentThread().getName() ,j j);}bBhouldSubThread true;subThreadCondition.signal();}catch(Exception e){}finally{lock.unlock();}}}}57、介绍Collection框架的结构答随意发挥题天南海北谁便谈只要让别觉得你知识渊博理解透彻即可。58、Collection框架中实现比较要实现什么接口comparable/comparator59、ArrayList和Vector的区别答这两个类都实现了List接口List接口继承了Collection接口他们都是有序集合即存储在这两个集合中的元素的位置都是有顺序的相当于一种动态的数组我们以后可以按位置索引号取出某个元素并且其中的数据是允许重复的这是HashSet之类的集合的最大不同处HashSet之类的集合不可以按索引号去检索其中的元素也不允许有重复的元素本来题目问的与hashset没有任何关系但为了说清楚ArrayList与Vector的功能我们使用对比方式更有利于说明问题。接着才说ArrayList与Vector的区别这主要包括两个方面.1同步性Vector是线程安全的也就是说是它的方法之间是线程同步的而ArrayList是线程序不安全的它的方法之间是线程不同步的。如果只有一个线程会访问到集合那最好是使用ArrayList因为它不考虑线程安全效率会高些如果有多个线程会访问到集合那最好是使用Vector因为不需要我们自己再去考虑和编写线程安全的代码。备注对于VectorArrayList、HashtableHashMap要记住线程安全的问题记住Vector与Hashtable是旧的是java一诞生就提供了的它们是线程安全的ArrayList与HashMap是java2时才提供的它们是线程不安全的。所以我们讲课时先讲老的。2数据增长ArrayList与Vector都有一个初始的容量大小当存储进它们里面的元素的个数超过了容量时就需要增加ArrayList与Vector的存储空间每次要增加存储空间时不是只增加一个存储单元而是增加多个存储单元每次增加的存储单元的个数在内存空间利用与程序效率之间要取得一定的平衡。Vector默认增长为原来两倍而ArrayList的增长策略在文档中没有明确规定从源代码看到的是增长为原来的1.5倍。ArrayList与Vector都可以设置初始的空间大小Vector还可以设置增长的空间大小而ArrayList没有提供设置增长空间的方法。总结即Vector增长原来的一倍ArrayList增加原来的0.5倍。60、HashMap和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算法都大概一样所以性能不会有很大的差异。就HashMap与HashTable主要从三方面来说。一.历史原因:Hashtable是基于陈旧的Dictionary类的HashMap是Java 1.2引进的Map接口的一个实现二.同步性:Hashtable是线程安全的也就是说是同步的而HashMap是线程序不安全的不是同步的三.值只有HashMap可以让你将空值作为一个表的条目的key或value61、List 和 Map 区别?一个是存储单列数据的集合另一个是存储键和值这样的双列数据的集合List中存储的数据是有顺序并且允许重复Map中存储的数据是没有顺序的其键是不能重复的它的值是可以有重复的。62、List, Set, Map是否继承自Collection接口?ListSet是Map不是63、List、Map、Set三个接口存取元素时各有什么特点这样的题属于随意发挥题这样的题比较考水平两个方面的水平一是要真正明白这些内容二是要有较强的总结和表述能力。如果你明白但表述不清楚在别人那里则等同于不明白。首先List与Set具有相似性它们都是单列元素的集合所以它们有一个功共同的父接口叫Collection。Set里面不允许有重复的元素所谓重复即不能有两个相等注意不是仅仅是相同的对象 即假设Set集合中有了一个A对象现在我要向Set集合再存入一个B对象但B对象与A对象equals相等则B对象存储不进去所以Set集合的add方法有一个boolean的返回值当集合中没有某个元素此时add方法可成功加入该元素时则返回true当集合含有与某个元素equals相等的元素时此时add方法无法加入该元素返回结果为false。Set取元素时没法说取第几个只能以Iterator接口取得所有的元素再逐一遍历各个元素。List表示有先后顺序的集合 注意不是那种按年龄、按大小、按价格之类的排序。当我们多次调用add(Obj e)方法时每次加入的对象就像火车站买票有排队顺序一样按先来后到的顺序排序。有时候也可以插队即调用add(int index,Obj e)方法就可以指定当前对象在集合中的存放位置。一个对象可以被反复存储进List中每调用一次add方法这个对象就被插入进集合中一次其实并不是把这个对象本身存储进了集合中而是在集合中用一个索引变量指向这个对象当这个对象被add多次时即相当于集合中有多个索引指向了这个对象如图x所示。List除了可以以Iterator接口取得所有的元素再逐一遍历各个元素之外还可以调用get(index i)来明确说明取第几个。Map与List和Set不同它是双列的集合其中有put方法定义如下put(obj key,obj value)每次存储时要存储一对key/value不能存储重复的key这个重复的规则也是按equals比较相等。取则可以根据key获得相应的value即get(Object key)返回值为key 所对应的value。另外也可以获得所有的key的结合还可以获得所有的value的结合还可以获得key和value组合成的Map.Entry对象的集合。List 以特定次序来持有元素可有重复元素。Set 无法拥有重复元素,内部排序。Map 保存key-value值value可多值。HashSet按照hashcode值的某种运算方式进行存储而不是直接按hashCode值的大小进行存储。例如abc --- 78def --- 62xyz --- 65在hashSet中的存储顺序不是62,65,78这些问题感谢以前一个叫崔健的学员提出最后通过查看源代码给他解释清楚看本次培训学员当中有多少能看懂源码。LinkedHashSet按插入的顺序存储那被存储对象的hashcode方法还有什么作用呢学员想想!hashset集合比较两个对象是否相等首先看hashcode方法是否相等然后看equals方法是否相等。new 两个Student插入到HashSet中看HashSet的size实现hashcode和equals方法后再看size。同一个对象可以在Vector中加入多次。往集合里面加元素相当于集合里用一根绳子连接到了目标对象。往HashSet中却加不了多次的。64、说出ArrayList,Vector, LinkedList的存储性能和特性ArrayList和Vector都是使用数组方式存储数据此数组元素数大于实际存储的数据以便增加和插入元素它们都允许直接按序号索引元素但是插入元素要涉及数组元素移动等内存操作所以索引数据快而插入数据慢Vector由于使用了synchronized方法线程安全通常性能上较ArrayList差而LinkedList使用双向链表实现存储按序号索引数据需要进行前向或后向遍历但是插入数据时只需要记录本项的前后项即可所以插入速度较快。LinkedList也是线程不安全的LinkedList提供了一些方法使得LinkedList可以被当作堆栈和队列来使用。65、去掉一个Vector集合中重复的元素Vector newVector new Vector();For (int i0;ivector.size();i){Object obj vector.get(i);if(!newVector.contains(obj);newVector.add(obj);}还有一种简单的方式HashSet set new HashSet(vector);66、Collection 和 Collections的区别。Collection是集合类的上级接口继承与他的接口主要有Set 和List.Collections是针对集合类的一个帮助类他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。67、Set里的元素是不能重复的那么用什么方法来区分重复与否呢? 是用还是equals()? 它们有何区别?Set里的元素是不能重复的元素重复与否是使用equals()方法进行判断的。equals()和方法决定引用值是否指向同一对象equals()在类中被覆盖为的是当两个分离的对象的内容和类型相配的话返回真值。68、你所知道的集合类都有哪些主要方法最常用的集合类是 List 和 Map。 List 的具体实现包括 ArrayList 和 Vector它们是可变大小的列表比较适合构建、存储和操作任何类型对象的元素列表。 List 适用于按数值索引访问元素的情形。Map 提供了一个更通用的元素存储方法。 Map 集合类用于存储元素对称作键和值其中每个键映射到一个值。ArrayList/VectoràListàCollectionHashSet/TreeSetàSetPropetiesàHashTableàMapTreemap/HashMap我记的不是方法名而是思想我知道它们都有增删改查的方法但这些方法的具体名称我记得不是很清楚对于set大概的方法是add,remove, contains对于map大概的方法就是put,removecontains等因为我只要在eclispe下按点操作符很自然的这些方法就出来了。我记住的一些思想就是List类会有get(int index)这样的方法因为它可以按顺序取元素而set类中没有get(int index)这样的方法。List和set都可以迭代出所有元素迭代时先要得到一个iterator对象所以set和list类都有一个iterator方法用于返回那个iterator对象。map可以返回三个集合一个是返回所有的key的集合另外一个返回的是所有value的集合再一个返回的key和value组合成的EntrySet对象的集合map也有get方法参数是key返回值是key对应的value。69、两个对象值相同(x.equals(y) true)但却可有不同的hash code这句话对不对?对。如果对象要保存在HashSet或HashMap中它们的equals相等那么它们的hashcode值就必须相等。如果不是要保存在HashSet或HashMap则与hashcode没有什么关系了这时候hashcode不等是可以的例如arrayList存储的对象就不用实现hashcode当然我们没有理由不实现通常都会去实现的。70、TreeSet里面放对象如果同时放入了父类和子类的实例对象那比较时使用的是父类的compareTo方法还是使用的子类的compareTo方法还是抛异常应该是没有针对问题的确切的答案当前的add方法放入的是哪个对象就调用哪个对象的compareTo方法至于这个compareTo方法怎么做就看当前这个对象的类中是如何编写这个方法的实验代码publicclassParentimplementsComparable {privateintage 0;publicParent(intage){this.age age;}publicintcompareTo(Object o) {//TODOAuto-generated method stubSystem.out.println(method of parent);Parent o1 (Parent)o;returnageo1.age?1:ageo1.age?-1:0;}}publicclassChildextendsParent {publicChild(){super(3);}publicintcompareTo(Object o) {//TODOAuto-generated method stubSystem.out.println(method of child);// Child o1 (Child)o;return1;}}publicclassTreeSetTest {/***paramargs*/publicstaticvoidmain(String[] args) {//TODOAuto-generated method stubTreeSet set newTreeSet();set.add(newParent(3));set.add(newChild());set.add(newParent(4));System.out.println(set.size());}}*******************************************************************************71、说出一些常用的类包接口请各举5个要让人家感觉你对java ee开发很熟所以不能仅仅只列core java中的那些东西要多列你在做ssh项目中涉及的那些东西。就写你最近写的那些程序中涉及的那些类。常用的类BufferedReader BufferedWriter FileReader FileWirter String Integerjava.util.DateSystemClassList,HashMap常用的包java.lang java.io java.util java.sql ,javax.servlet,org.apache.strtuts.action,org.hibernate常用的接口Remote List Map Document NodeList ,Servlet,HttpServletRequest,HttpServletResponse,Transaction(Hibernate)、Session(Hibernate),HttpSession72、java中有几种类型的流JDK为每种类型的流提供了一些抽象类以供继承请说出他们分别是哪些类字节流字符流。字节流继承于InputStream OutputStream字符流继承于InputStreamReader OutputStreamWriter。在java.io包中还有许多其他的流主要是为了提高性能和使用方便。73、字节流与字符流的区别要把一片二进制数据数据逐一输出到某个设备中或者从某个设备中逐一读取一片二进制数据不管输入输出设备是什么我们要用统一的方式来完成这些操作用一种抽象的方式进行描述这个抽象描述方式起名为IO流对应的抽象类为OutputStream和InputStream 不同的实现类就代表不同的输入和输出设备它们都是针对字节进行操作的。在应用中经常要完全是字符的一段文本输出去或读进来用字节流可以吗计算机中的一切最终都是二进制的字节形式存在。对于“中国”这些字符首先要得到其对应的字节然后将字节写入到输出流。读取时首先读到的是字节可是我们要把它显示为字符我们需要将字节转换成字符。由于这样的需求很广泛人家专门提供了字符流的包装类。底层设备永远只接受字节数据有时候要写字符串到底层设备需要将字符串转成字节再进行写入。字符流是字节流的包装字符流则是直接接受字符串它内部将串转成字节再写入底层设备这为我们向IO设别写入或读取字符串提供了一点点方便。字符向字节转换时要注意编码的问题因为字符串转成字节数组其实是转成该字符的某种编码的字节形式读取也是反之的道理。讲解字节流与字符流关系的代码案例import java.io.BufferedReader;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.FileReader;import java.io.FileWriter;import java.io.InputStreamReader;import java.io.PrintWriter;public class IOTest {public static void main(String[] args) throws Exception {String str 中国人;/*FileOutputStream fos new FileOutputStream(1.txt);fos.write(str.getBytes(UTF-8));fos.close();*//*FileWriter fw new FileWriter(1.txt);fw.write(str);fw.close();*/PrintWriter pw new PrintWriter(1.txt,utf-8);pw.write(str);pw.close();/*FileReader fr new FileReader(1.txt);char[] buf new char[1024];int len fr.read(buf);String myStr new String(buf,0,len);System.out.println(myStr);*//*FileInputStream fr new FileInputStream(1.txt);byte[] buf new byte[1024];int len fr.read(buf);String myStr new String(buf,0,len,UTF-8);System.out.println(myStr);*/BufferedReader br new BufferedReader(new InputStreamReader(new FileInputStream(1.txt),UTF-8));String myStr br.readLine();br.close();System.out.println(myStr);}}74、什么是java序列化如何实现java序列化或者请解释Serializable接口的作用。我们有时候将一个java对象变成字节流的形式传出去或者从一个字节流中恢复成一个java对象例如要将java对象存储到硬盘或者传送给网络上的其他计算机这个过程我们可以自己写代码去把一个java对象变成某个格式的字节流再传输但是jre本身就提供了这种支持我们可以调用OutputStream的writeObject方法来做如果要让java 帮我们做要被传输的对象必须实现serializable接口这样javac编译时就会进行特殊处理编译的类才可以被writeObject方法操作这就是所谓的序列化。需要被序列化的类必须实现Serializable接口该接口是一个mini接口其中没有需要实现的方法implements Serializable只是为了标注该对象是可被序列化的。例如在web开发中如果对象被保存在了Session中tomcat在重启时要把Session对象序列化到硬盘这个对象就必须实现Serializable接口。如果对象要经过分布式系统进行网络传输或通过rmi等远程调用这就需要在网络上传输对象被传输的对象就必须实现Serializable接口。75、描述一下JVM加载class文件的原理机制?JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader 是一个重要的Java运行时系统组件。它负责在运行时查找和装入类文件的类。76、heap和stack有什么区别。java的内存分为两类一类是栈内存一类是堆内存。栈内存是指程序进入一个方法时会为这个方法单独分配一块私属存储空间用于存储这个方法内部的局部变量当这个方法结束时分配给这个方法的栈会释放这个栈中的变量也将随之释放。堆是与栈作用不同的内存一般用于存放不放在当前方法栈中的那些数据例如使用new创建的对象都放在堆里所以它不会随方法的结束而消失。方法中的局部变量使用final修饰后放在堆中而不是栈中。77、GC是什么? 为什么要有GC?GC是垃圾收集的意思Gabage Collection,内存处理是编程人员容易出现问题的地方忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的Java语言没有提供释放已分配内存的显示操作方法。78、垃圾回收的优点和原理。并考虑2种回收机制。Java语言中一个显著的特点就是引入了垃圾回收机制使c程序员最头疼的内存管理的问题迎刃而解它使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制Java中的对象不再有作用域的概念只有对象的引用才有作用域。垃圾回收可以有效的防止内存泄露有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收增量垃圾回收。79、垃圾回收器的基本原理是什么垃圾回收器可以马上回收内存吗有什么办法主动通知虚拟机进行垃圾回收对于GC来说当程序员创建对象时GC就开始监控这个对象的地址、大小以及使用情况。通常GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是可达的哪些对象是不可达的。当GC确定一些对象为不可达时GC就有责任回收这些内存空间。可以。程序员可以手动执行System.gc()通知GC运行但是Java语言规范并不保证GC一定会执行。80、什么时候用assert。assertion(断言)在软件开发中是一种常用的调试方式很多开发语言中都支持这种机制。在实现中assertion就是在程序中的一条语句它对一个boolean表达式进行检查一个正确程序必须保证这个boolean表达式的值为true如果该值为false说明程序已经处于不正确的状态下assert将给出警告或退出。一般来说assertion用于保证程序最基本、关键的正确性。assertion检查通常在开发和测试时开启。为了提高性能在软件发布后assertion检查通常是关闭的。packagecom.huawei.interview;publicclassAssertTest {/***paramargs*/publicstaticvoidmain(String[] args) {//TODOAuto-generated method stubinti 0;for(i0;i5;i){System.out.println(i);}//假设程序不小心多了一句--i;--i;asserti5;}}81、java中会存在内存泄漏吗请简单描述。所谓内存泄露就是指一个不再被程序使用的对象或变量一直被占据在内存中。java中有垃圾回收机制它可以保证一对象不再被引用的时候即对象编程了孤儿的时候对象将自动被垃圾回收器从内存中清除掉。由于Java 使用有向图的方式进行垃圾回收管理可以消除引用循环的问题例如有两个对象相互引用只要它们和根进程不可达的那么GC也是可以回收它们的例如下面的代码可以看到这种情况的内存回收packagecom.huawei.interview;importjava.io.IOException;publicclassGarbageTest {/***paramargs*throwsIOException*/publicstaticvoidmain(String[] args)throwsIOException {//TODOAuto-generated method stubtry{gcTest();}catch(IOException e) {//TODOAuto-generated catch blocke.printStackTrace();}System.out.println(has exited gcTest!);System.in.read();System.in.read();System.out.println(out begin gc!);for(inti0;i100;i){System.gc();System.in.read();System.in.read();}}privatestaticvoidgcTest()throwsIOException {System.in.read();System.in.read();Person p1 newPerson();System.in.read();System.in.read();Person p2 newPerson();p1.setMate(p2);p2.setMate(p1);System.out.println(before exit gctest!);System.in.read();System.in.read();System.gc();System.out.println(exit gctest!);}privatestaticclassPerson{byte[] data newbyte[20000000];Person mate null;publicvoidsetMate(Person other){mate other;}}}java中的内存泄露的情况长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露尽管短生命周期对象已经不再需要但是因为长生命周期对象持有它的引用而导致不能被回收这就是java中内存泄露的发生场景通俗地说就是程序员可能创建了一个对象以后一直不再使用这个对象这个对象却一直被引用即这个对象无用但是却无法被垃圾回收器回收的这就是java中可能出现内存泄露的情况例如缓存系统我们加载了一个对象放在缓存中(例如放在一个全局map对象中)然后一直不再使用它这个对象一直被缓存引用但却不再被使用。检查java中的内存泄露一定要让程序将各种分支情况都完整执行到程序结束然后看某个对象是否被使用过如果没有则才能判定这个对象属于内存泄露。如果一个外部类的实例对象的方法返回了一个内部类的实例对象这个内部类对象被长期引用了即使那个外部类实例对象不再被使用但由于内部类持久外部类的实例对象这个外部类对象将不会被垃圾回收这也会造成内存泄露。下面内容来自于网上主要特点就是清空堆栈中的某个元素并不是彻底把它从数组中拿掉而是把存储的总数减少本人写得可以比这个好在拿掉某个元素时顺便也让它从数组中消失将那个元素所在的位置的值设置为null即可我实在想不到比那个堆栈更经典的例子了,以致于我还要引用别人的例子下面的例子不是我想到的是书上看到的当然如果没有在书上看到可能过一段时间我自己也想的到可是那时我说是我自己想到的也没有人相信的。public class Stack {private Object[] elementsnew Object[10];private int size 0;public void push(Object e){ensureCapacity();elements[size] e;}public Object pop(){if( size 0)throw new EmptyStackException();return elements[--size];}private void ensureCapacity(){if(elements.length size){Object[] oldElements elements;elements new Object[2 * elements.length1];System.arraycopy(oldElements,0, elements, 0, size);}}}上面的原理应该很简单假如堆栈加了10个元素然后全部弹出来虽然堆栈是空的没有我们要的东西但是这是个对象是无法回收的这个才符合了内存泄露的两个条件无用无法回收。但是就是存在这样的东西也不一定会导致什么样的后果如果这个堆栈用的比较少也就浪费了几个K内存而已反正我们的内存都上G了哪里会有什么影响再说这个东西很快就会被回收的有什么关系。下面看两个例子。例子1public class Bad{public static Stack sStack();static{s.push(new Object());s.pop(); //这里有一个对象发生内存泄露s.push(new Object()); //上面的对象可以被回收了等于是自愈了}}因为是static就一直存在到程序退出但是我们也可以看到它有自愈功能就是说如果你的Stack最多有100个对象那么最多也就只有100个对象无法被回收其实这个应该很容易理解Stack内部持有100个引用最坏的情况就是他们都是无用的因为我们一旦放新的进取以前的引用自然消失内存泄露的另外一种情况当一个对象被存储进HashSet集合中以后就不能修改这个对象中的那些参与计算哈希值的字段了否则对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了在这种情况下即使在contains方法使用该对象的当前引用作为的参数去HashSet集合中检索对象也将返回找不到对象的结果这也会导致无法从HashSet集合中单独删除当前对象造成内存泄露。82、能不能自己写个类也叫java.lang.String可以但在应用的时候需要用自己的类加载器去加载否则系统的类加载器永远只是去加载jre.jar包中的那个java.lang.String。由于在tomcat的web应用程序中都是由webapp自己的类加载器先自己加载WEB-INF/classess目录中的类然后才委托上级的类加载器加载如果我们在tomcat的web应用程序中写一个java.lang.String这时候Servlet程序加载的就是我们自己写的java.lang.String但是这么干就会出很多潜在的问题原来所有用了java.lang.String类的都将出现问题。虽然java提供了endorsed技术可以覆盖jdk中的某些类具体做法是….。但是能够被覆盖的类是有限制范围反正不包括java.lang这样的包中的类。下面的例如主要是便于大家学习理解只用不要作为答案的一部分否则人家怀疑是题目泄露了例如运行下面的程序packagejava.lang;publicclassString {/***paramargs*/publicstaticvoidmain(String[] args) {//TODOAuto-generated method stubSystem.out.println(string);}}报告的错误如下java.lang.NoSuchMethodError: mainException in thread main这是因为加载了jre自带的java.lang.String而该类中没有main方法。83. Java代码查错1.abstract class Name {private String name;public abstract boolean isStupidName(String name) {}}大侠们这有何错误?答案: 错。abstract method必须以分号结尾且不带花括号。2.public class Something {void doSomething () {private String s ;int l s.length();}}有错吗?答案: 错。局部变量前不能放置任何访问修饰符 (privatepublic和protected)。final可以用来修饰局部变量(final如同abstract和strictfp都是非访问修饰符strictfp只能修饰class和method而非variable)。3.abstract class Something {private abstract String doSomething ();}这好像没什么错吧?答案: 错。abstract的methods不能以private修饰。abstract的methods就是让子类implement(实现)具体细节的怎么可以用private把abstractmethod封锁起来呢? (同理abstract method前不能加final)。4.public class Something {public int addOne(final int x) {return x;}}这个比较明显。答案: 错。int x被修饰成final意味着x不能在addOne method中被修改。5.public class Something {public static void main(String[] args) {Other o new Other();new Something().addOne(o);}public void addOne(final Other o) {o.i;}}class Other {public int i;}和上面的很相似都是关于final的问题这有错吗?答案: 正确。在addOne method中参数o被修饰成final。如果在addOne method里我们修改了o的reference(比如: o new Other();)那么如同上例这题也是错的。但这里修改的是o的member vairable(成员变量)而o的reference并没有改变。6.class Something {int i;public void doSomething() {System.out.println(i i);}}有什么错呢? 看不出来啊。答案: 正确。输出的是i 0。int i属於instant variable (实例变量或叫成员变量)。instant variable有default value。int的default value是0。7.class Something {final int i;public void doSomething() {System.out.println(i i);}}和上面一题只有一个地方不同就是多了一个final。这难道就错了吗?答案: 错。final int i是个final的instant variable (实例变量或叫成员变量)。final的instant variable没有default value必须在constructor (构造器)结束之前被赋予一个明确的值。可以修改为final int i 0;。8.public class Something {public static void main(String[] args) {Something s new Something();System.out.println(s.doSomething() returns doSomething());}public String doSomething() {return Do something ...;}}看上去很完美。答案: 错。看上去在main里call doSomething没有什么问题毕竟两个methods都在同一个class里。但仔细看main是static的。static method不能直接call non-static methods。可改成System.out.println(s.doSomething() returns s.doSomething());。同理static method不能访问non-static instant variable。9.此处Something类的文件名叫OtherThing.javaclass Something {private static void main(String[] something_to_do) {System.out.println(Do something ...);}}这个好像很明显。答案: 正确。从来没有人说过Java的Class名字必须和其文件名相同。但public class的名字必须和文件名相同。10interface A{int x 0;}class B{int x 1;}class C extends B implements A {public void pX(){System.out.println(x);}public static void main(String[] args) {new C().pX();}}答案错误。在编译时会发生错误(错误描述不同的JVM有不同的信息意思就是未明确的x调用两个x都匹配就象在同时import java.util和java.sql两个包时直接声明Date一样。对于父类的变量,可以用super.x来明确而接口的属性默认隐含为 public static final.所以可以通过A.x来明确。11.interface Playable {void play();}interface Bounceable {void play();}interface Rollable extends Playable, Bounceable {Ball ball new Ball(PingPang);}class Ball implements Rollable {private String name;public String getName() {return name;}public Ball(String name) {this.name name;}public void play() {ball new Ball(Football);System.out.println(ball.getName());}}这个错误不容易发现。答案: 错。interface Rollable extends Playable, Bounceable没有问题。interface可继承多个interfaces所以这里没错。问题出在interface Rollable里的Ball ball new Ball(PingPang);。任何在interface里声明的interface variable (接口变量也可称成员变量)默认为public static final。也就是说Ball ball new Ball(PingPang);实际上是public static final Ball ball new Ball(PingPang);。在Ball类的Play()方法中ball new Ball(Football);改变了ball的reference而这里的ball来自Rollable interfaceRollable interface里的ball是public static final的final的object是不能被改变reference的。因此编译器将在ball new Ball(Football);这里显示有错。二. 算法与编程1、编写一个程序将a.txt文件中的单词与b.txt文件中的单词交替合并到c.txt文件中a.txt文件中的单词用回车符分隔b.txt文件中用回车或空格进行分隔。package cn.itcast;import java.io.File;import java.io.FileReader;import java.io.FileWriter;public class MainClass{public static void main(String[] args) throws Exception{FileManager a new FileManager(a.txt,new char[]{\n});FileManager b new FileManager(b.txt,new char[]{\n, });FileWriter c new FileWriter(c.txt);String aWord null;String bWord null;while((aWord a.nextWord()) !null ){c.write(aWord \n);bWord b.nextWord();if(bWord ! null)c.write(bWord \n);}while((bWord b.nextWord()) ! null){c.write(bWord \n);}c.close();}}class FileManager{String[] words null;int pos 0;public FileManager(String filename,char[] seperators) throws Exception{File f new File(filename);FileReader reader new FileReader(f);char[] buf new char[(int)f.length()];int len reader.read(buf);String results new String(buf,0,len);String regex null;if(seperators.length 1 ){regex seperators[0] | seperators[1];}else{regex seperators[0];}words results.split(regex);}public String nextWord(){if(pos words.length)return null;return words[pos];}}2、编写一个程序将d:\java目录下的所有.java文件复制到d:\jad目录下并将原来文件的扩展名从.java改为.jad。大家正在做上面这道题网上迟到的朋友也请做做这道题找工作必须能编写这些简单问题的代码答listFiles方法接受一个FileFilter对象这个FileFilter对象就是过虑的策略对象不同的人提供不同的FileFilter实现即提供了不同的过滤策略。import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.FilenameFilter;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;public class Jad2Java {public static void main(String[] args) throws Exception {File srcDir new File(java);if(!(srcDir.exists() srcDir.isDirectory()))throw new Exception(目录不存在);File[] files srcDir.listFiles(new FilenameFilter(){public boolean accept(File dir, String name) {return name.endsWith(.java);}});System.out.println(files.length);File destDir new File(jad);if(!destDir.exists()) destDir.mkdir();for(File f :files){FileInputStream fis new FileInputStream(f);String destFileName f.getName().replaceAll(\\.java$, .jad);FileOutputStream fos new FileOutputStream(new File(destDir,destFileName));copy(fis,fos);fis.close();fos.close();}}private static void copy(InputStream ips,OutputStream ops) throws Exception{int len 0;byte[] buf new byte[1024];while((len ips.read(buf)) ! -1){ops.write(buf,0,len);}}}由本题总结的思想及策略模式的解析1.class jad2java{1. 得到某个目录下的所有的java文件集合1.1 得到目录 File srcDir new File(d:\\java);1.2 得到目录下的所有java文件File[] files srcDir.listFiles(new MyFileFilter());1.3 只想得到.java的文件 class MyFileFilter implememyts FileFilter{public boolean accept(File pathname){return pathname.getName().endsWith(.java)}}2.将每个文件复制到另外一个目录并改扩展名2.1 得到目标目录如果目标目录不存在则创建之2.2 根据源文件名得到目标文件名注意要用正则表达式注意.的转义。2.3 根据表示目录的File和目标文件名的字符串得到表示目标文件的File。//要在硬盘中准确地创建出一个文件需要知道文件名和文件的目录。2.4 将源文件的流拷贝成目标文件流拷贝方法独立成为一个方法方法的参数采用抽象流的形式。//方法接受的参数类型尽量面向父类越抽象越好这样适应面更宽广。}分析listFiles方法内部的策略模式实现原理File[] listFiles(FileFilter filter){File[] files listFiles();//Arraylist acceptedFilesList new ArrayList();File[] acceptedFiles new File[files.length];int pos 0;for(File file: files){boolean accepted filter.accept(file);if(accepted){//acceptedFilesList.add(file);acceptedFiles[pos] file;}}Arrays.copyOf(acceptedFiles,pos);//return (File[])accpetedFilesList.toArray();}3、编写一个截取字符串的函数输入为一个字符串和字节数输出为按字节截取的字符串但要保证汉字不被截取半个如“我ABC”4应该截取“我AB”输入“我ABC汉DEF”6应该输出“我ABC”而不是“我ABC汉的半个”。答首先要了解中文字符有多种编码及各种编码的特征。假设n为要截取的字节数。public static void main(String[] args) throws Exception{String str 我a爱中华abc我爱传智def;String str 我ABC汉;int num trimGBK(str.getBytes(GBK),5);System.out.println(str.substring(0,num) );}public static int trimGBK(byte[] buf,int n){int num 0;boolean bChineseFirstHalf false;for(int i0;in;i){if(buf[i]0 !bChineseFirstHalf){bChineseFirstHalf true;}else{num;bChineseFirstHalf false;}}return num;}4、有一个字符串其中包含中文字符、英文字符和数字字符请统计和打印出各个字符的个数。答哈哈其实包含中文字符、英文字符、数字字符原来是出题者放的烟雾弹。String content “中国aadf的111萨bbb菲的zz萨菲”;HashMap map new HashMap();for(int i0;icontent.length;i){char c content.charAt(i);Integer num map.get(c);if(num null)num 1;elsenum num 1;map.put(c,num);}for(Map.EntrySet entry : map){system.out.println(entry.getkey() “:” entry.getValue());}估计是当初面试的那个学员表述不清楚问题很可能是如果一串字符如aaaabbc中国1512要分别统计英文字符的数量中文字符的数量和数字字符的数量假设字符中没有中文字符、英文字符、数字字符之外的其他特殊字符。int engishCount;int chineseCount;int digitCount;for(int i0;istr.length;i){char ch str.charAt(i);if(ch’0’ ch’9’){digitCount}else if((ch’a’ ch’z’) || (ch’A’ ch’Z’)){engishCount;}else{chineseCount;}}System.out.println(……………);5、说明生活中遇到的二叉树用java实现二叉树这是组合设计模式。我有很多个(假设10万个)数据要保存起来以后还需要从保存的这些数据中检索是否存在某个数据我想说出二叉树的好处该怎么说呢那就是说别人的缺点假如存在数组中那么碰巧要找的数字位于99999那个地方那查找的速度将很慢因为要从第1个依次往后取取出来后进行比较。平衡二叉树构建平衡二叉树需要先排序我们这里就不作考虑了可以很好地解决这个问题但二叉树的遍历前序中序后序效率要比数组低很多原理如下图代码如下packagecom.huawei.interview;publicclassNode {publicintvalue;publicNode left;publicNode right;publicvoidstore(intvalue){if(valuethis.value){if(left null){left newNode();left.valuevalue;}else{left.store(value);}}elseif(valuethis.value){if(right null){right newNode();right.valuevalue;}else{right.store(value);}}}publicbooleanfind(intvalue){System.out.println(happen this.value);if(value this.value){returntrue;}elseif(valuethis.value){if(right null)returnfalse;returnright.find(value);}else{if(left null)returnfalse;returnleft.find(value);}}publicvoidpreList(){System.out.print(this.value ,);if(left!null) left.preList();if(right!null) right.preList();}publicvoidmiddleList(){if(left!null) left.preList();System.out.print(this.value ,);if(right!null) right.preList();}publicvoidafterList(){if(left!null) left.preList();if(right!null) right.preList();System.out.print(this.value ,);}publicstaticvoidmain(String [] args){int[] data newint[20];for(inti0;idata.length;i){data[i] (int)(Math.random()*100) 1;System.out.print(data[i] ,);}System.out.println();Node root newNode();root.value data[0];for(inti1;idata.length;i){root.store(data[i]);}root.find(data[19]);root.preList();System.out.println();root.middleList();System.out.println();root.afterList();}}-----------------又一次临场写的代码---------------------------import java.util.Arrays;import java.util.Iterator;public class Node {private Node left;private Node right;private int value;//private int num;public Node(int value){this.value value;}public void add(int value){if(value this.value){if(right ! null)right.add(value);else{Node node new Node(value);right node;}}else{if(left ! null)left.add(value);else{Node node new Node(value);left node;}}}public boolean find(int value){if(value this.value) return true;else if(value this.value){if(right null) return false;else return right.find(value);}else{if(left null) return false;else return left.find(value);}}public void display(){System.out.println(value);if(left ! null) left.display();if(right ! null) right.display();}/*public Iterator iterator(){}*/public static void main(String[] args){int[] values new int[8];for(int i0;i8;i){int num (int)(Math.random() * 15);//System.out.println(num);//if(Arrays.binarySearch(values, num)0)if(!contains(values,num))values[i] num;elsei--;}System.out.println(Arrays.toString(values));Node root new Node(values[0]);for(int i1;ivalues.length;i){root.add(values[i]);}System.out.println(root.find(13));root.display();}public static boolean contains(int [] arr, int value){int i 0;for(;iarr.length;i){if(arr[i] value) return true;}return false;}}6、从类似如下的文本文件中读取出所有的姓名并打印出重复的姓名和重复的次数并按重复次数排序1,张三,282,李四,353,张三,284,王五,355,张三,286,李四,357,赵六,288,田七,35程序代码如下答题要博得用人单位的喜欢包名用该公司面试前就提前查好该公司的网址如果查不到现场问也是可以的。还要加上实现思路的注释packagecom.huawei.interview;importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStream;importjava.io.InputStreamReader;importjava.util.Comparator;importjava.util.HashMap;importjava.util.Iterator;importjava.util.Map;importjava.util.TreeSet;publicclassGetNameTest {/***paramargs*/publicstaticvoidmain(String[] args) {//TODOAuto-generated method stub//InputStream ips GetNameTest.class.getResourceAsStream(/com/huawei/interview/info.txt);//用上一行注释的代码和下一行的代码都可以因为info.txt与GetNameTest类在同一包下面所以可以用下面的相对路径形式Map results newHashMap();InputStream ips GetNameTest.class.getResourceAsStream(info.txt);BufferedReader in newBufferedReader(newInputStreamReader(ips));String line null;try{while((linein.readLine())!null){dealLine(line,results);}sortResults(results);}catch(IOException e) {//TODOAuto-generated catch blocke.printStackTrace();}}staticclassUser{publicString name;publicInteger value;publicUser(String name,Integer value){this.name name;this.value value;}Overridepublicbooleanequals(Object obj) {//TODOAuto-generated method stub//下面的代码没有执行说明往treeset中增加数据时不会使用到equals方法。booleanresult super.equals(obj);System.out.println(result);returnresult;}}privatestaticvoidsortResults(Map results) {//TODOAuto-generated method stubTreeSet sortedResults newTreeSet(newComparator(){publicintcompare(Object o1, Object o2) {//TODOAuto-generated method stubUser user1 (User)o1;User user2 (User)o2;/*如果compareTo返回结果0则认为两个对象相等新的对象不会增加到集合中去* 所以不能直接用下面的代码否则那些个数相同的其他姓名就打印不出来。* *///return user1.value-user2.value;//return user1.valueuser2.value?-1:user1.valueuser2.value?0:1;if(user1.valueuser2.value){return-1;}elseif(user1.valueuser2.value){return1;}else{returnuser1.name.compareTo(user2.name);}}});Iterator iterator results.keySet().iterator();while(iterator.hasNext()){String name (String)iterator.next();Integer value (Integer)results.get(name);if(value 1){sortedResults.add(newUser(name,value));}}printResults(sortedResults);}privatestaticvoidprintResults(TreeSet sortedResults){Iterator iterator sortedResults.iterator();while(iterator.hasNext()){User user (User)iterator.next();System.out.println(user.name : user.value);}}publicstaticvoiddealLine(String line,Map map){if(!.equals(line.trim())){String [] results line.split(,);if(results.length 3){String name results[1];Integer value (Integer)map.get(name);if(value null) value 0;map.put(name,value 1);}}}}7、写一个Singleton出来。第一种饱汉模式public class SingleTon {private SingleTon(){}//实例化放在静态代码块里可提高程序的执行效率但也可能更占用空间private final static SingleTon instance new SingleTon();public static SingleTon getInstance(){return instance;}}第二种饥汉模式public class SingleTon {private SingleTon(){}private static instance null;//new SingleTon();public static synchronized SingleTon getInstance(){if(instance null)instance new SingleTon();return instance;}}第三种用枚举public enum SingleTon{ONE;}第三更实际的应用在什么情况用单例public class SequenceGenerator{//下面是该类自身的业务功能代码private int count 0;public synchronized int getSequence(){count;}//下面是把该类变成单例的代码private SequenceGenerator(){}private final static instance new SequenceGenerator();public static SingleTon getInstance(){return instance;}}第四public class MemoryDao{private HashMap map new HashMap();public void add(Student stu1){map.put(SequenceGenerator.getInstance().getSequence(),stu1);}//把MemoryDao变成单例}Singleton模式主要作用是保证在Java应用程序中一个类Class只有一个实例存在。一般Singleton模式通常有几种种形式:第一种形式: 定义一个类它的构造函数为private的它有一个static的private的该类变量在类初始化时实例话通过一个public的getInstance方法获取对它的引用,继而调用其中的方法。public class Singleton {private Singleton(){}//在自己内部定义自己一个实例是不是很奇怪//注意这是private 只供内部调用private static Singleton instance new Singleton();//这里提供了一个供外部访问本class的静态方法可以直接访问public static Singleton getInstance() {return instance;}}第二种形式:public class Singleton {private static Singleton instance null;public static synchronized Singleton getInstance() {//这个方法比上面有所改进不用每次都进行生成对象只是第一次//使用时生成实例提高了效率if (instancenull)instancenew Singleton();return instance;}}其他形式:定义一个类它的构造函数为private的所有方法为static的。一般认为第一种形式要更加安全些8、递归算法题1一个整数大于0不用循环和本地变量按照n2n4n8n的顺序递增当值大于5000时把值按照指定顺序输出来。例n1237则输出为12372474494898969896494824741237提示写程序时先致谢按递增方式的代码写好递增的以后再增加考虑递减部分。public static void doubleNum(int n){System.out.println(n);if(n5000)doubleNum(n*2);System.out.println(n);}9、递归算法题2第1个人10第2个比第1个人大2岁依次递推请用递归方式计算出第8个人多大packagecn.itcast;importjava.util.Date;publicclassA1 {publicstaticvoidmain(String [] args){System.out.println(computeAge(8));}publicstaticintcomputeAge(intn){if(n1)return10;returncomputeAge(n-1) 2;}}publicstaticvoidtoBinary(intn,StringBuffer result){if(n/2 ! 0)toBinary(n/2,result);result.append(n%2);}10、排序都有哪几种方法请列举。用JAVA实现一个快速排序。本人只研究过冒泡排序、选择排序和快速排序下面是快速排序的代码public class QuickSort {/*** 快速排序* param strDate* param left* param right*/public void quickSort(String[] strDate,int left,int right){String middle,tempDate;int i,j;ileft;jright;middlestrDate[(ij)/2];do{while(strDate[i].compareTo(middle)0 iright)i; //找出左边比中间值大的数while(strDate[j].compareTo(middle)0 jleft)j--; //找出右边比中间值小的数if(ij){ //将左边大的数和右边小的数进行替换tempDatestrDate[i];strDate[i]strDate[j];strDate[j]tempDate;i;j--;}}while(ij); //当两者交错时停止if(iright){quickSort(strDate,i,right);//从}if(jleft){quickSort(strDate,left,j);}}/*** param args*/public static void main(String[] args){String[] strVoidnew String[]{11,66,22,0,55,22,0,32};QuickSort sortnew QuickSort();sort.quickSort(strVoid,0,strVoid.length-1);for(int i0;istrVoid.length;i){System.out.println(strVoid[i] );}}}11、有数组a[n]用java代码将数组元素顺序颠倒//用下面的也可以//for(int i0,int ja.length-1;ij;i,j--) 是否等效于 for(int i0;ia.length/2;i)呢import java.util.Arrays;public class SwapDemo{public static void main(String[] args){int [] a new int[]{(int)(Math.random() * 1000),(int)(Math.random() * 1000),(int)(Math.random() * 1000),(int)(Math.random() * 1000),(int)(Math.random() * 1000) };System.out.println(a);System.out.println(Arrays.toString(a));swap(a);System.out.println(Arrays.toString(a));}public static void swap(int a[]){int len a.length;for(int i0;ilen/2;i){int tmp a[i];a[i] a[len-1-i];a[len-1-i] tmp;}}}12金额转换阿拉伯数字的金额转换成中国传统的形式如1011一千零一拾一元整输出。去零的代码return sb.reverse().toString().replaceAll(零[拾佰仟],零).replaceAll(零万,万).replaceAll(零元,元).replaceAll(零,零);public class RenMingBi {/*** param args add by zxx ,Nov 29, 2008*/private static final char[] data new char[]{零,壹,贰,叁,肆,伍,陆,柒,捌,玖};private static final char[] units new char[]{元,拾,佰,仟,万,拾,佰,仟,亿};public static void main(String[] args) {// TODO Auto-generated method stubSystem.out.println(convert(135689123));}public static String convert(int money){StringBuffer sbf new StringBuffer();int unit 0;while(money!0){sbf.insert(0,units[unit]);int number money%10;sbf.insert(0, data[number]);money / 10;}return sbf.toString();}}三. htmlJavaScriptajax部分1. 判断第二个日期比第一个日期大如何用脚本判断用户输入的的字符串是下面的时间格式2004-11-21 必须要保证用户的输入是此格式并且是时间比如说月份不大于12等等另外我需要用户输入两个并且后一个要比前一个晚只允许用JAVASCRIPT请详细帮助作答,//这里可用正则表达式判断提前判断一下格式然后按下提取各时间字段内容script typetext/javascriptwindow.onload function(){//这么写是为了实现js代码与html代码的分离当我修改js时不能影响html代码。document.getElementById(frm1).onsubmit function(){var d1 this.d1.value;var d2 this.d2.value;if(!verifyDate (d1)) {alert(第一个日期格式不对);return false;}if(!verifyDate (d2)) {alert(第二个日期格式不对);return false;}if(!compareDate(d1,d2)) {alert(第二个日期比第一日期小);return false;}};}function compareDate(d1,d2){var arrayD1 d1.split(-);var date1 new Date(arrayD1[0],arrayD1[1],arrayD1[2]);var arrayD2 d2.split(-);var date2 new Date(arrayD2[0],arrayD2[1],arrayD2[2]);if(date1 date2) return false;return true;}function verifyDate(d){var datePattern /^\d{4}-(0?[1-9]|1[0-2])-(0?[1-9]|[1-2]\d|3[0-1])$/;return datePattern.test(d);}/scriptform idfrm1 actionxxx.htmlinput typetext named1 /input typetext named2 /input typesubmit//form2.用table显示n条记录每3行换一次颜色即123用红色字体456用绿色字体789用红颜色字体。bodytable idtbltrtd1/td/trtrtd2/td/trtrtd3/td/trtrtd4/td/trtrtd5/td/trtrtd6/td/trtrtd7/td/trtrtd8/td/trtrtd9/td/trtrtd10/td/tr/table/bodyscript typetext/javascriptwindow.onloadfunction(){var tbl document.getElementById(tbl);rows tbl.getElementsByTagName(tr);for(i0;irows.length;i){var j parseInt(i/3);if(j%20) rows[i].style.backgroundColor#f00;else rows[i].style.backgroundColor#0f0;}}/script3、HTML 的 form 提交之前如何验证数值文本框的内容全部为数字?否则的话提示用户并终止提交?form onsubmit’return chkForm(this)’input typetext named1/input typesubmit//formscript type”text/javascript” /function chkForm(this){var value thist.d1.value;var len value.length;for(var i0;ilen;i){if(value.charAt(i)9 || value.charAt(i)0){alert(含有非数字字符); return false;}}return true;}/script4、请写出用于校验HTML文本框中输入的内容全部为数字的javascript代码input typetext idd1 onblur chkNumber (this)/script type”text/javascript” /function chkNumber(eleText){var value eleText.value;var len value.length;for(var i0;ilen;i){if(value.charAt(i)9 || value.charAt(i)0){alert(含有非数字字符);eleText.focus();break;}}}/script除了写完代码还应该在网页上写出实验步骤和在代码中加入实现思路让面试官一看就明白你的意图和检查你的结果。5、说说你用过那些ajax技术和框架说说它们的区别四.Java web部分1、Tomcat的优化经验答:去掉对web.xml的监视把jsp提前编辑成Servlet。有富余物理内存的情况加大tomcat使用的jvm的内存2、HTTP请求的GET与POST方式的区别答:servlet有良好的生存期的定义包括加载和实例化、初始化、处理请求以及服务结束。这个生存期由javax.servlet.Servlet接口的init,service和destroy方法表达。3、解释一下什么是servlet;答:servlet有良好的生存期的定义包括加载和实例化、初始化、处理请求以及服务结束。这个生存期由javax.servlet.Servlet接口的init,service和destroy方法表达。4、说一说Servlet的生命周期?答:servlet有良好的生存期的定义包括加载和实例化、初始化、处理请求以及服务结束。这个生存期由javax.servlet.Servlet接口的init,service和destroy方法表达。Servlet被服务器实例化后容器运行其init方法请求到达时运行其service方法service方法自动派遣运行与请求对应的doXXX方法doGetdoPost等当服务器决定将实例销毁的时候调用其destroy方法。web容器加载servlet生命周期开始。通过调用servlet的init()方法进行servlet的初始化。通过调用service()方法实现根据请求的不同调用不同的do***()方法。结束服务web容器调用servlet的destroy()方法。5、Servlet的基本架构public class ServletName extends HttpServlet {public void doPost(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {}public void doGet(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {}}6、SERVLET API中forward() 与redirect()的区别答:前者仅是容器中控制权的转向在客户端浏览器地址栏中不会显示出转向后的地址后者则是完全的跳转浏览器将会得到跳转的地址并重新发送请求链接。这样从浏览器的地址栏中可以看到跳转后的链接地址。所以前者更加高效在前者可以满足需要时尽量使用forward()方法并且这样也有助于隐藏实际的链接。在有些情况下比如需要跳转到一个其它服务器上的资源则必须使用sendRedirect()方法。7、什么情况下调用doGet()和doPost()Jsp页面中的FORM标签里的method属性为get时调用doGet()为post时调用doPost()。8、Request对象的主要方法setAttribute(String name,Object)设置名字为name的request的参数值getAttribute(String name)返回由name指定的属性值getAttributeNames()返回request对象所有属性的名字集合结果是一个枚举的实例getCookies()返回客户端的所有Cookie对象结果是一个Cookie数组getCharacterEncoding()返回请求中的字符编码方式getContentLength()返回请求的Body的长度getHeader(String name)获得HTTP协议定义的文件头信息getHeaders(String name)返回指定名字的request Header的所有值结果是一个枚举的实例getHeaderNames()返回所以request Header的名字结果是一个枚举的实例getInputStream()返回请求的输入流用于获得请求中的数据getMethod()获得客户端向服务器端传送数据的方法getParameter(String name)获得客户端传送给服务器端的有name指定的参数值getParameterNames()获得客户端传送给服务器端的所有参数的名字结果是一个枚举的实例getParametervalues(String name)获得有name指定的参数的所有值getProtocol()获取客户端向服务器端传送数据所依据的协议名称getQueryString()获得查询字符串getRequestURI()获取发出请求字符串的客户端地址getRemoteAddr()获取客户端的IP地址getRemoteHost()获取客户端的名字getSession([Boolean create])返回和请求相关SessiongetServerName()获取服务器的名字getServletPath()获取客户端所请求的脚本文件的路径getServerPort()获取服务器的端口号removeAttribute(String name)删除请求中的一个属性9、forward 和redirect的区别forward是服务器请求资源服务器直接访问目标地址的URL把那个URL的响应内容读取过来然后把这些内容再发给浏览器浏览器根本不知道服务器发送的内容是从哪儿来的所以它的地址栏中还是原来的地址。redirect就是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址一般来说浏览器会用刚才请求的所有参数重新请求所以session,request参数都可以获取。10、request.getAttribute() 和 request.getParameter() 有何区别?11. jsp有哪些内置对象?作用分别是什么? 分别有什么方法答:JSP共有以下9个内置的对象request 用户端请求此请求会包含来自GET/POST请求的参数response 网页传回用户端的回应pageContext 网页的属性是在这里管理session 与请求有关的会话期application servlet 正在执行的内容out 用来传送回应的输出config servlet的构架部件page JSP网页本身exception 针对错误网页未捕捉的例外request表示HttpServletRequest对象。它包含了有关浏览器请求的信息并且提供了几个用于获取cookie, header, 和session数据的有用的方法。response表示HttpServletResponse对象并提供了几个用于设置送回 浏览器的响应的方法如cookies,头信息等out对象是javax.jsp.JspWriter的一个实例并提供了几个方法使你能用于向浏览器回送输出结果。pageContext表示一个javax.servlet.jsp.PageContext对象。它是用于方便存取各种范围的名字空间、servlet相关的对象的API并且包装了通用的servlet相关功能的方法。session表示一个请求的javax.servlet.http.HttpSession对象。Session可以存贮用户的状态信息applicaton 表示一个javax.servle.ServletContext对象。这有助于查找有关servlet引擎和servlet环境的信息config表示一个javax.servlet.ServletConfig对象。该对象用于存取servlet实例的初始化参数。page表示从该页面产生的一个servlet实例12. jsp有哪些动作?作用分别是什么?这个问题似乎不重要不明白为何有此题答:JSP共有以下6种基本动作jsp:include在页面被请求的时候引入一个文件。jsp:useBean寻找或者实例化一个JavaBean。jsp:setProperty设置JavaBean的属性。jsp:getProperty输出某个JavaBean的属性。jsp:forward把请求转到一个新的页面。jsp:plugin根据浏览器类型为Java插件生成OBJECT或EMBED标记13、JSP的常用指令isErrorPage(是否能使用Exception对象)isELIgnored(是否忽略表达式)14. JSP中动态INCLUDE与静态INCLUDE的区别答动态INCLUDE用jsp:include动作实现jsp:include pageincluded.jsp flushtrue /它总是会检查所含文件中的变化适合用于包含动态页面并且可以带参数 静态INCLUDE用include伪码实现,定不会检查所含文件的变化适用于包含静态页面 % include fileincluded.htm %15、两种跳转方式分别是什么?有什么区别?下面的回答严重错误应该是想问forward和sendRedirect 的区别毕竟出题的人不是专业搞文字艺术的人可能表达能力并不见得很强用词不一定精准加之其自身的技术面也可能存在一些问题不一定真正将他的意思表达清楚了严格意思上来讲一些题目可能根本就无人能答所以答题时要掌握主动只要把自己知道的表达清楚就够了而不要去推敲原始题目的具体含义是什么不要一味想着是在答题答有两种分别为jsp:include pageincluded.jsp flushtruejsp:forward page nextpage.jsp/前者页面不会转向include所指的页面只是显示该页的结果主页面还是原来的页面。执行完后还会回来相当于函数调用。并且可以带参数.后者完全转向新页面不会再回来。相当于go to 语句。16、页面间对象传递的方法requestsessionapplicationcookie等17、JSP和Servlet有哪些相同点和不同点他们之间的联系是什么JSP是Servlet技术的扩展本质上是Servlet的简易方式更强调应用的外表表达。JSP编译后是类servlet。Servlet和JSP最主要的不同点在于Servlet的应用逻辑是在Java文件中并且完全从表示层中的HTML里分离开来。而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件。JSP侧重于视图Servlet主要用于控制逻辑。18、MVC的各个部分都有那些技术来实现?如何实现?答:MVC是ModelViewController的简写。Model 代表的是应用的业务逻辑通过JavaBeanEJB组件实现 View 是应用的表示面由JSP页面产生Controller 是提供应用的处理过程控制一般是一个Servlet通过这种设计模型把应用逻辑处理过程和显示逻辑分成不同的组件实现。这些组件可以进行交互和重用。19、我们在web应用开发过程中经常遇到输出某种编码的字符如iso8859-1等如何输出一个某种编码的字符串Public String translate (String str) {String tempStr ;try {tempStr new String(str.getBytes(ISO-8859-1), GBK);tempStr tempStr.trim();}catch (Exception e) {System.err.println(e.getMessage());}return tempStr;}20现在输入n个数字以逗号分开然后可选择升或者降序排序按提交键就在另一页面显示按什么排序结果为提供reset五. 数据库部分1、用两种方式根据部门号从高到低工资从低到高列出每个员工的信息。employee:eid,ename,salary,deptid;select * from employee order by deptid desc,salary2、列出各个部门中工资高于本部门的平均工资的员工数和部门号并按部门号排序select avg(salary) from emp123 group by deptid;select emp123.id,emp123.deptid tid from emp123 where salary(select avg(salary) from emp123 group by deptid )where deptidtid; 错误select count(*) ,deptid from (select emp123.id,emp123.deptid tid from emp123 where salary(select avg(salary) from emp123 where deptidtid)) group by deptid;select deptid,count(*) from emp123 awhere a.salary(select avg(salary) from emp123 b where a.deptidb.deptid)group by deptid order by deptid;创建表mysql create table employee921(id int primary key auto_increment,name varchar(50),salary bigint,deptid int);插入实验数据mysql insert into employee921 values(null,zs,1000,1),(null,ls,1100,1),(null,ww,1100,1),(null,zl,900,1) ,(null,zl,1000,2), (null,zl,900,2) ,(null,zl,1000,2) , (null,zl,1100,2);编写sql语句select avg(salary) from employee921 group by deptid;mysql select employee921.id,employee921.name,employee921.salary,employee921.deptid tid from employee921 where salary (select avg(salary) from employee921 where deptid tid);效率低的一个语句仅供学习参考使用在group by之后不能使用where只能使用having在group by之前可以使用where即表示对过滤后的结果分组mysql select employee921.id,employee921.name,employee921.salary,employee921.deptid tid from employee921 where salary (select avg(salary) from employee921 group by deptid having deptid tid);select count(*) ,tidfrom (select employee921.id,employee921.name,employee921.salary,employee921.deptid tidfrom employee921where salary (select avg(salary) from employee921 where deptid tid)) as tgroup by tid ;另外一种方式关联查询select a.ename,a.salary,a.deptidfrom emp a,(select deptd,avg(salary) avgsal from emp group by deptid ) bwhere a.deptidb.deptid and a.salaryb.avgsal;3、存储过程与触发器必须讲经常被面试到?create procedure insert_Student (_name varchar(50),_age int ,out _id int)begininsert into student value(null,_name,_age);select max(stuId) into _id from student;end;call insert_Student(wfz,23,id);select id;mysql create trigger update_Student BEFORE update on student FOR EACH ROW- select * from student;触发器不允许返回结果create trigger update_Student BEFORE update on student FOR EACH ROWinsert into student value(null,zxx,28);mysql的触发器目前不能对当前表进行操作create trigger update_Student BEFORE update on student FOR EACH ROWdelete from articles where id8;这个例子不是很好最好是用删除一个用户时顺带删除该用户的所有帖子这里要注意使用OLD.id触发器用处还是很多的比如校内网、开心网、Facebook你发一个日志自动通知好友其实就是在增加日志时做一个后触发再向通知表中写入条目。因为触发器效率高。而UCH没有用触发器效率和数据处理能力都很低。存储过程的实验步骤mysql delimiter |mysql create procedure insertArticle_Procedure (pTitle varchar(50),pBid int,outpId int)- begin- insert into article1 value(null,pTitle,pBid);- select max(id) into pId from article1;- end;- |Query OK, 0 rows affected (0.05 sec)mysql call insertArticle_Procedure(传智播客,1,pid);- |Query OK, 0 rows affected (0.00 sec)mysql delimiter ;mysql select pid;------| pid |------| 3 |------1 row in set (0.00 sec)mysql select * from article1;------------------------| id | title | bid |------------------------| 1 | test | 1 || 2 | chuanzhiboke | 1 || 3 | 传智播客 | 1 |------------------------3 rows in set (0.00 sec)触发器的实验步骤create table board1(id int primary key auto_increment,name varchar(50),articleCount int);create table article1(id int primary key auto_increment,title varchar(50),bid int references board1(id));delimiter |create trigger insertArticle_Trigger after insert on article1 for each row begin- update board1 set articleCountarticleCount1 where id NEW.bid;- end;- |delimiter ;insert into board1 value (null,test,0);insert into article1 value(null,test,1);还有每插入一个帖子都希望将版面表中的最后发帖时间帖子总数字段进行同步更新用触发器做效率就很高。下次课设计这样一个案例写触发器时对于最后发帖时间可能需要用declare方式声明一个变量或者是用NEW.posttime来生成。4、数据库三范式是什么?第一范式1NF字段具有原子性,不可再分。所有关系型数据库系统都满足第一范式数据库表中的字段都是单一属性的不可再分。例如姓名字段其中的姓和名必须作为一个整体无法区分哪部分是姓哪部分是名如果要区分出姓和名必须设计成两个独立的字段。第二范式2NF第二范式2NF是在第一范式1NF的基础上建立起来的即满足第二范式2NF必须先满足第一范式1NF。要求数据库表中的每个实例或行必须可以被惟一地区分。通常需要为表加上一个列以存储各个实例的惟一标识。这个惟一属性列被称为主关键字或主键。第二范式2NF要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性如果存在那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列以存储各个实例的惟一标识。简而言之第二范式就是非主属性非部分依赖于主关键字。第三范式的要求如下满足第三范式3NF必须先满足第二范式2NF。简而言之第三范式3NF要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。所以第三范式具有如下特征1每一列只有一个值2每一行都能区分。3每一个表都不包含其他表已经包含的非主关键字信息。例如帖子表中只能出现发帖人的id而不能出现发帖人的id还同时出现发帖人姓名否则只要出现同一发帖人id的所有记录它们中的姓名部分都必须严格保持一致这就是数据冗余。5、说出一些数据库优化方面的经验?用PreparedStatement 一般来说比Statement性能高一个sql 发给服务器去执行涉及步骤语法检查、语义分析 编译缓存“inert into user values(1,1,1)”-à二进制“inert into user values(2,2,2)”-à二进制“inert into user values(?,?,?)”-à二进制有外键约束会影响插入和删除性能如果程序能够保证数据的完整性那在设计数据库时就去掉外键。比喻就好比免检产品就是为了提高效率充分相信产品的制造商对于hibernate来说就应该有一个变化empleyee-Deptment对象现在设计时就成了employeeàdeptid看mysql帮助文档子查询章节的最后部分例如根据扫描的原理下面的子查询语句要比第二条关联查询的效率高1. select e.name,e.salary where e.managerid(select id from employee where namezxx);2. select e.name,e.salary,m.name,m.salary from employees e,employees m wheree.managerid m.id and m.namezxx;表中允许适当冗余譬如主题帖的回复数量和最后回复时间等将姓名和密码单独从用户表中独立出来。这可以是非常好的一对一的案例哟sql语句全部大写特别是列名和表名都大写。特别是sql命令的缓存功能更加需要统一大小写sql语句à发给oracle服务器à语法检查和编译成为内部指令à缓存和执行指令。根据缓存的特点不要拼凑条件而是用?和PreparedStatment还有索引对查询性能的改进也是值得关注的。备注下面是关于性能的讨论举例4航班 3个城市m*nselect * from flight,city where flight.startcityidcity.cityid and city.namebeijing;m nselect * from flight where startcityid (select cityid from city where citynamebeijing);select flight.id,beijing,flight.flightTime from flight where startcityid (select cityid from city where citynamebeijing)6、union和union all有什么不同?假设我们有一个表Student包括以下字段与数据drop table student;create table student(id int primary key,name nvarchar2(50) not null,score number not null);insert into student values(1,Aaron,78);insert into student values(2,Bill,76);insert into student values(3,Cindy,89);insert into student values(4,Damon,90);insert into student values(5,Ella,73);insert into student values(6,Frado,61);insert into student values(7,Gill,99);insert into student values(8,Hellen,56);insert into student values(9,Ivan,93);insert into student values(10,Jay,90);commit;Union和Union All的区别。select *from studentwhere id 4unionselect *from studentwhere id 2 and id 6结果将是1 Aaron 782 Bill 763 Cindy 894 Damon 905 Ella 73如果换成Union All连接两个结果集则返回结果是1 Aaron 782 Bill 763 Cindy 893 Cindy 894 Damon 905 Ella 73可以看到Union和Union All的区别之一在于对重复结果的处理。Union去掉重复数据UNION在进行表链接后会筛选掉重复的记录所以在表链接后会对所产生的结果集进行排序运算删除重复的记录再返回结果。实际大部分应用中是不会产生重复的记录最常见的是过程表与历史表UNION。如select * from gc_dfysunionselect * from ls_jg_dfys这个SQL在运行时先取出两个表的结果再用排序空间进行排序删除重复的记录最后返回结果集如果表数据量大的话可能会导致用磁盘进行排序。而UNION ALL只是简单的将两个结果合并后就返回。这样如果返回的两个结果集中有重复的数据那么返回的结果集就会包含重复的数据了。从效率上说UNION ALL 要比UNION快很多所以如果可以确认合并的两个结果集中不包含重复的数据的话那么就使用UNION ALL7.分页语句取出sql表中第31到40的记录以自动增长ID为主键sql server方案1select top 10 * from t where id not in (select top 30 id from t order by id ) orde by idsql server方案2select top 10 * from t where id in (select top 40 id from t order by id) order by id descmysql方案select * from t order by id limit 30,10oracle方案select * from (select rownum r,* from t where r40) where r30--------------------待整理进去的内容-------------------------------------pageSize20;pageNo 5;1.分页技术1直接利用sql语句进行分页效率最高和最推荐的mysql:sql select * from articles limit (pageNo-1)*pageSize , pageSize;oracle: sql select * from (select rownum r,* from (select * from articles order by postime desc) where rownum pageNo*pageSize ) tmp where r (pageNo-1)*pageSize;注释第7行保证rownum的顺序是确定的因为oracle的索引会造成rownum返回不同的值简洋提示没有order by时rownum按顺序输出一旦有了order byrownum不按顺序输出了这说明rownum是排序前的编号。如果对order by从句中的字段建立了索引那么rownum也是按顺序输出的因为这时候生成原始的查询结果集时会参照索引表的顺序来构建。sqlserver:sql select top 10 * from id not id(select top (pageNo-1)*pageSize id from articles)DataSource ds new InitialContext().lookup(jndiurl);Connection cn ds.getConnection();//select * from user where id? ---binary directivePreparedStatement pstmt cn.prepareSatement(sql);ResultSet rs pstmt.executeQuery()while(rs.next()){out.println(rs.getString(1));}2.不可滚动的游标pageSize20;pageNo 5;cn nullstmt null;rs null;try{sqlserver:sql select * from articles;DataSource ds new InitialContext().lookup(jndiurl);Connection cn ds.getConnection();//select * from user where id? ---binary directivePreparedStatement pstmt cn.prepareSatement(sql);ResultSet rs pstmt.executeQuery()for(int j0;j(pageNo-1)*pageSize;j){rs.next();}int i0;while(rs.next() i10){i;out.println(rs.getString(1));}}cacth(){}finnaly{if(rs!null)try{rs.close();}catch(Exception e){}if(stm.........if(cn............}3.可滚动的游标pageSize20;pageNo 5;cn nullstmt null;rs null;try{sqlserver:sql select * from articles;DataSource ds new InitialContext().lookup(jndiurl);Connection cn ds.getConnection();//select * from user where id? ---binary directivePreparedStatement pstmt cn.prepareSatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,...);//根据上面这行代码的异常SQLFeatureNotSupportedException就可判断驱动是否支持可滚动游标ResultSet rs pstmt.executeQuery()rs.absolute((pageNo-1)*pageSize)int i0;while(rs.next() i10){i;out.println(rs.getString(1));}}cacth(){}finnaly{if(rs!null)try{rs.close();}catch(Exception e){}if(stm.........if(cn............}8.用一条SQL语句 查询出每门课都大于80分的学生姓名name kecheng fenshu张三 语文 81张三 数学 75李四 语文 76李四 数学 90王五 语文 81王五 数学 100王五 英语 90准备数据的sql代码create table score(id int primary key auto_increment,name varchar(20),subject varchar(20),score int);insert into score values(1,张三,语文,81),(2,张三,数学,75),(3,李四,语文,76),(4,李四,数学,90),(5,王五,语文,81),(6,王五,数学,100),(7,王五 ,英语,90);提示当百思不得其解时请理想思维把小变成大做把大变成小做答案A: select distinct name from score where name not in (select distinct name from score where score80)B:select distince name t1 from score where 80 all (select score from score where namet1);9.所有部门之间的比赛组合一个叫department的表里面只有一个字段name,一共有4条纪录分别是a,b,c,d,对应四个球对现在四个球对进行比赛用一条sql语句显示所有可能的比赛组合.答select a.name, b.namefrom team a, team bwhere a.name b.name10.每个月份的发生额都比101科目多的科目请用SQL语句实现从TestDB数据表中查询出所有月份的发生额都比101科目相应月份的发生额高的科目。请注意TestDB中有很多科目都有112月份的发生额。AccID科目代码Occmonth发生额月份DebitOccur发生额。数据库名JcyAudit数据集Select * from TestDB准备数据的sql代码drop table if exists TestDB;create table TestDB(id int primary key auto_increment,AccID varchar(20), Occmonth date, DebitOccur bigint);insert into TestDB values(null,101,1988-1-1,100),(null,101,1988-2-1,110),(null,101,1988-3-1,120),(null,101,1988-4-1,100),(null,101,1988-5-1,100),(null,101,1988-6-1,100),(null,101,1988-7-1,100),(null,101,1988-8-1,100);--复制上面的数据故意把第一个月份的发生额数字改小一点insert into TestDB values(null,102,1988-1-1,90),(null,102,1988-2-1,110),(null,102,1988-3-1,120),(null,102,1988-4-1,100),(null,102,1988-5-1,100),(null,102,1988-6-1,100),(null,102,1988-7-1,100),(null,102,1988-8-1,100);--复制最上面的数据故意把所有发生额数字改大一点insert into TestDB values(null,103,1988-1-1,150),(null,103,1988-2-1,160),(null,103,1988-3-1,180),(null,103,1988-4-1,120),(null,103,1988-5-1,120),(null,103,1988-6-1,120),(null,103,1988-7-1,120),(null,103,1988-8-1,120);--复制最上面的数据故意把所有发生额数字改大一点insert into TestDB values(null,104,1988-1-1,130),(null,104,1988-2-1,130),(null,104,1988-3-1,140),(null,104,1988-4-1,150),(null,104,1988-5-1,160),(null,104,1988-6-1,170),(null,104,1988-7-1,180),(null,104,1988-8-1,140);--复制最上面的数据故意把第二个月份的发生额数字改小一点insert into TestDB values(null,105,1988-1-1,100),(null,105,1988-2-1,80),(null,105,1988-3-1,120),(null,105,1988-4-1,100),(null,105,1988-5-1,100),(null,105,1988-6-1,100),(null,105,1988-7-1,100),(null,105,1988-8-1,100);答案select distinct AccID from TestDBwhere AccID not in(select TestDB.AccIDfrom TestDB,(select * from TestDB where AccID101) as db101where TestDB.Occmonthdb101.Occmonth and TestDB.DebitOccurdb101.DebitOccur);11.统计每年每月的信息year month amount1991 1 1.11991 2 1.21991 3 1.31991 4 1.41992 1 2.11992 2 2.21992 3 2.31992 4 2.4查成这样一个结果year m1 m2 m3 m41991 1.1 1.2 1.3 1.41992 2.1 2.2 2.3 2.4提示这个与工资条非常类似与学生的科目成绩也很相似。准备sql语句drop table if exists sales;create table sales(id int auto_increment primary key,year varchar(10), month varchar(10), amount float(2,1));insert into sales values(null,1991,1,1.1),(null,1991,2,1.2),(null,1991,3,1.3),(null,1991,4,1.4),(null,1992,1,2.1),(null,1992,2,2.2),(null,1992,3,2.3),(null,1992,4,2.4);答案一、select sales.year ,(select t.amount from sales t where t.month1 and t.year sales.year) 1,(select t.amount from sales t where t.month1 and t.year sales.year) 2,(select t.amount from sales t where t.month1 and t.year sales.year) 3,(select t.amount from sales t where t.month1 and t.year sales.year) as 4from sales group by year;12.显示文章标题发帖人、最后回复时间表id,title,postuser,postdate,parentid准备sql语句drop table if exists articles;create table articles(id int auto_increment primary key,title varchar(50), postuser varchar(10), postdate datetime,parentid int references articles(id));insert into articles values(null,第一条,张三,1998-10-10 12:32:32,null),(null,第二条,张三,1998-10-10 12:34:32,null),(null,第一条回复1,李四,1998-10-10 12:35:32,1),(null,第二条回复1,李四,1998-10-10 12:36:32,2),(null,第一条回复2,王五,1998-10-10 12:37:32,1),(null,第一条回复3,李四,1998-10-10 12:38:32,1),(null,第二条回复2,李四,1998-10-10 12:39:32,2),(null,第一条回复4,王五,1998-10-10 12:39:40,1);答案select a.title,a.postuser,(select max(postdate) from articles where parentida.id) replyfrom articles a where a.parentid is null;注释子查询可以用在选择列中也可用于where的比较条件中还可以用于from从句中。13.删除除了id号不同,其他都相同的学生冗余信息2.学生表 如下:id号 学号 姓名 课程编号 课程名称 分数1 2005001 张三 0001 数学 692 2005002 李四 0001 数学 893 2005001 张三 0001 数学 69A: delete from tablename where id号 not in(select min(id号) from tablename group by 学号,姓名,课程编号,课程名称,分数)实验create table student2(id int auto_increment primary key,code varchar(20),name varchar(20));insert into student2 values(null,2005001,张三),(null,2005002,李四),(null,2005001,张三);//如下语句mysql报告错误可能删除依赖后面统计语句而删除又导致统计语句结果不一致。delete from student2 where id not in(select min(id) from student2 group by name);//但是如下语句没有问题select * from student2 where id not in(select min(id) from student2 group by name);//于是我想先把分组的结果做成虚表然后从虚表中选出结果最后再将结果作为删除的条件数据。delete from student2 where id not in(select mid from (select min(id) midfrom student2 group by name) as t);或者delete from student2 where id not in(select min(id) from (select * from student2) as t group by t.name);14.航空网的几个航班查询题表结构如下flight{flightID,StartCityID ,endCityID,StartTime}city{cityID, CityName)实验环境create table city(cityID int auto_increment primary key,cityName varchar(20));create table flight (flightID int auto_increment primary key,StartCityID int references city(cityID),endCityID int references city(cityID),StartTime timestamp);//航班本来应该没有日期部分才好但是下面的题目当中涉及到了日期insert into city values(null,北京),(null,上海),(null,广州);insert into flight values(null,1,2,9:37:23),(null,1,3,9:37:23),(null,1,2,10:37:23),(null,2,3,10:37:23);1、查询起飞城市是北京的所有航班按到达城市的名字排序参与运算的列是我起码能够显示出来的那些列但最终我不一定把它们显示出来。各个表组合出来的中间结果字段中必须包含所有运算的字段。select * from flight f,city cwhere f.endcityid c.cityid and startcityid (select c1.cityid from city c1 where c1.cityname 北京)order by c.cityname asc;mysql select flight.flightid,北京 startcity, e.cityname from flight,city e where flight.endcityide.cityid and flight.startcityid(select cityid from city where cityname北京);mysql select flight.flightid,s.cityname,e.cityname from flight,city s,city e where flight.startcityids.cityid and s.cityname北京 and flight.endCityIde.cityID order by e.cityName desc;2、查询北京到上海的所有航班纪录起飞城市到达城市起飞时间航班号select c1.CityName,c2.CityName,f.StartTime,f.flightIDfrom city c1,city c2,flight fwhere f.StartCityIDc1.cityIDand f.endCityIDc2.cityIDand c1.cityName北京and c2.cityName上海3、查询具体某一天2005-5-8的北京到上海的的航班次数select count(*) from(select c1.CityName,c2.CityName,f.StartTime,f.flightIDfrom city c1,city c2,flight fwhere f.StartCityIDc1.cityIDand f.endCityIDc2.cityIDand c1.cityName北京and c2.cityName上海and 查帮助获得的某个日期处理函数(startTime) like 2005-5-8%mysql中提取日期部分进行比较的示例代码如下select * from flight where date_format(starttime,%Y-%m-%d)1998-01-0215.查出比经理薪水还高的员工信息Drop table if not exists employees;create table employees(id int primary key auto_increment,name varchar(50),salary int,managerid int references employees(id));insert into employees values (null, lhm,10000,null), (null, zxx,15000,1),(null,flx,9000,1),(null,tg,10000,2),(null,wzg,10000,3);Wzg大于flx,lhm大于zxx解题思路根据sql语句的查询特点是逐行进行运算不可能两行同时参与运算。涉及了员工薪水和经理薪水所有一行记录要同时包含两个薪水所有想到要把这个表自关联组合一下。首先要组合出一个包含有各个员工及该员工的经理信息的长记录譬如左半部分是员工右半部分是经理。而迪卡尔积会组合出很多垃圾信息先去除这些垃圾信息。select e.* from employees e,employees m where e.manageridm.id and e.salarym.salary;16、求出小于45岁的各个老师所带的大于12岁的学生人数数据库中有3个表 teacher 表student表tea_stu关系表。teacher 表 teaID name agestudent 表 stuID name ageteacher_student表 teaID stuID要求用一条sql查询出这样的结果1.显示的字段要有老师name, age 每个老师所带的学生人数2 只列出老师age为40以下学生age为12以上的记录预备知识1.sql语句是对每一条记录依次处理条件为真则执行动作select,insert,delete,update2.只要是迪卡尔积就会产生“垃圾”信息所以只要迪卡尔积了我们首先就要想到清除“垃圾”信息实验准备drop table if exists tea_stu;drop table if exists teacher;drop table if exists student;create table teacher(teaID int primary key,name varchar(50),age int);create table student(stuID int primary key,name varchar(50),age int);create table tea_stu(teaID int references teacher(teaID),stuID int references student(stuID));insert into teacher values(1,zxx,45), (2,lhm,25) , (3,wzg,26) , (4,tg,27);insert into student values(1,wy,11), (2,dh,25) , (3,ysq,26) , (4,mxc,27);insert into tea_stu values(1,1), (1,2), (1,3);insert into tea_stu values(2,2), (2,3), (2,4);insert into tea_stu values(3,3), (3,4), (3,1);insert into tea_stu values(4,4), (4,1), (4,2) , (4,3);结果2当你的才华还撑不起你的野心时那你就应该静下心来学习。 清醒时做事糊涂时读书大怒时睡觉独处时思考。 再难也要坚持再好也要淡泊再差也要自信再多也要节省。 你所浪费的今天是昨天死去的人奢望的明天。你所厌恶的现在是未来的你回不去的曾经。 你成不了心态的主人必然会沦为情绪的奴隶。 生命太短一分钟都不要留给那些让你不快的人或事。 没有人陪你走一辈子所以你要适应孤独。没有人会帮你一辈子所以你要一直奋斗。 路是自己的不必用别人的标准来框定自己的人生。篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题需要全套面试笔记及答案可以点击下方名片获取