震撼,java面试题整合(良心制作)11万多字拿去。持续更新【可以收藏】

时间:2022-05-21 11:47:26

一、javaSE面试题整合

  1. JDK中哪些类是不能继承的?【信雅达面试题】

【参考答案】

不能继承的是类是那些用final关键字修饰的类。一般比较基本的类型或防止扩展类无意间破坏原来方法的实现的类型都应该是final的。

  1. String是最基本的数据类型吗? 【天能智健面试题】

【参考答案】

基本数据类型包括byte、int、char、long、float、double、boolean和short。

所以String不属于基本数据类型范畴内,但String属于最常见一种引用类型。

接口

数组

  1. Java对象初始化顺序?【腾鹏科技面试题】

【参考答案】

分为两种,一种是本类的初始化,一种是含有父类的初始化顺序。这里分开来说,

本类的初始化顺序是:静态变量、静态初始化块、变量、初始化块、构造函数

继承类的初始化顺序是:父类静态变量、父类静态初始化块、子类静态变量、子类静态初始块、父类变量、父类初始化块、父类构造函数、子类变量、子类初始化块、子类构造函数。

【分析】

static{
  System.out.println("静态块");
 }
 {
  System.out.println("初始化模块"); }
 public ClassName() {
  System.out.println("构造方法");
 }

说明:

原则上回答全面的话,应该是完整的说出带有继承的这种类的初始化过程,下面有个步骤可以参考:

  1. 装载程序的时候首先找到的是它的基(父)类,如果有多层基(父)类则会一级一级的往上找最后找到根基(父)类。
           2.执行根基础(父)类中的static初始化,再执行下一个衍生类中的static,依此类推,一直保持这个顺序。
           3.此时类已经装载完毕,开始创建对象,所有的基本数据类型都会设成它们的默认值,对象句柄设为null
           4.调用基础(父)类的构造方法,基础(父)类的构建采用与衍生类构造方法完全相同的处理过程。
           5.构造方法初始完之后,进行变量的初始化。
           6.执行构造方法中剩余的部分。
  1. 写几个线程安全类,不安全的,支持排序的类名?【软通动力面试题】

【参考答案】

  • 线程安全类:Vector 、Hashtable、Stack。
  • 线程不安全的类:ArrayList、Linkedlist、HashSet、TreeSet、HashMap、TreeMap等。
  • 支持排序的类有HashSet、LinkedHashSet、TreeSet等(Set接口下的实现都支持排序)

【分析】

此题主要考查集合框架的知识。在集合框架中Collection接口为集合的根类型,提供集合操作的常用API方法,该接口下派生出两个子接口,一个是不支持排序的List接口,一个是有自身排序的Set接口,所以回答排序与不排序分别从两接口的实现中在作答。线程安全上来说,Vector类比同属于List接口的ArrayList要早,是一个线程安全的类,在JDK1.2以后才推出一个异步的ArrayList类,比Vector类效率高。同理Stack继承自Vector也线程安全的类,另外在在Map接口的实现在Hashtable也是个线程安全的类。

  1. 哪几个方法可以实现一个线程?【上海华信面试题】

【参考答案】

一是继承Thread ,重写 Thread 类的方法 run方法;另种是实现 runnable 接口并实现 run方法。

【分析】

考查线程的基本实现,很多公司喜欢考查这方面知识,另外补充一下关于线程的run方法,在多线程API中启动一个线程是调用start()方法,线程进入就绪状态。

  1. STOP()和SUSPEND()不推荐使用的原因?

【参考答案】

stop()是因为它不安全。它会解除由线程获取的所有锁定,当在一个线程对象上调用stop()方法时,这个线程对象所运行的线程就会立即停止,假如一个线程正在执行:synchronized void { x = 3; y = 4;} 由于方法是同步的,多个线程访问时总能保证x,y被同时赋值,而如果一个线程正在执行到x = 3;时,被调用了 stop()方法,即使在同步块中,它也干脆地stop了,这样就产生了不完整的残废数据。而多线程编程中最最基础的条件要保证数据的完整性,所以请忘记线程的stop方法,以后我们再也不要说“停止线程”了。而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改它们。

suspend()方法容易发生死锁。调用suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定。此时,其他任何线程都不能访问锁定的资源,除非被"挂起"的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就 会造成死锁。所以不应该使用suspend(),而应在自己的Thread类中置入一个标志,指出线程应该活动还是挂起。若标志指出线程应该挂起,便用 wait()命其进入等待状态。若标志指出线程应当恢复,则用一个notify()重新启动线程。

【分析】

  1. "=="和equals方法有什么区别?【中科软】

【参考答案】

==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用==操作符。

如果一个变量指向的数据是对象类型的,那么,这时候涉及了两块内存,对象本身占用一块内存(堆内存),变量也占用一块内存,例如Objet obj = new Object();变量obj是一个内存,new Object()是另一个内存,此时,变量obj所对应的内存中存储的数值就是对象占用的那块内存的首地址。对于指向对象类型的变量,如果要比较两个变量是否指向同一个对象,即要看这两个变量所对应的内存中的数值是否相等,这时候就需要用==操作符进行比较。

equals方法是用于比较两个独立对象的内容是否相同,就好比去比较两个人的长相是否相同,它比较的两个对象是独立的。例如,对于下面的代码:

String a=new String("foo");

String b=new String("foo");

两条new语句创建了两个对象,然后用a,b这两个变量分别指向了其中一个对象,这是两个不同的对象,它们的首地址是不同的,即a和b中存储的数值是不相同的,所以,表达式a==b将返回false,而这两个对象中的内容是相同的,所以,表达式a.equals(b)将返回true。

在实际开发中,我们经常要比较传递进行来的字符串内容是否等,例如,String input = …;input.equals(“quit”),如果一个类没有自己定义equals方法,那么它将继承Object类的equals方法,Object类的equals方法的实现代码如下:

boolean equals(Object o){

return this==o;

}

这说明,如果一个类没有自己定义equals方法,它默认的equals方法(从Object 类继承的)就是使用==操作符,也是在比较两个变量指向的对象是否是同一对象,这时候使用equals和使用==会得到同样的结果,如果比较的是两个独立的对象则总返回false。如果你编写的类希望能够比较该类创建的两个实例对象的内容是否相同,那么你必须覆盖equals方法,由你自己写代码来决定在什么情况即可认为两个对象的内容是相同的。

  1. 静态变量和实例变量的区别?

【参考答案】

在语法定义上的区别:静态变量前要加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);

}

}

备注:这个解答除了说清楚两者的区别外,最后还用一个具体的应用例子来说明两者的差异,体现了自己有很好的解说问题和设计案例的能力,思维敏捷,超过一般程序员,有写作能力!

  1. 构造器的名能不能和类的名字相同?

【参考答案】

构造器的名称必须与类名相同。

【分析】

构造器或构造函数(有些书这样叫)主要用来对类的成员变量进行初始化,当类创建实例时调用。

  1. 在一个主方法类可不可以调用一个非静态的方法?

【参考答案】

不可以调用。因为Java的主方法(main)方法本身也是static类型方法,一个static类型方法,发起对另一个static方法的调用没有问题。

【分析】

静态方法可以调用其它的静态方法,但是不能调用非静态方法,这个好比Java中的类变量与实例变量的关系。类变量是被所有类成员共享,而实例变量只被该实例共享,

  1. GC是什么,为什么要使用它?【阿斯拓】

【参考答案】

GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域,从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。

【分析】

  1. 说一下垃圾回收的原理,可以直接从内存中回收吗?

【参考答案】

Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收,因为Java语言规范并不保证GC一定会执行。回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。

【分析】

  1. Java的异常有哪几种,有什么区别?

【参考答案】

两大类,一般异常和运行时异常。一般异常,这些异常是在定义方法时声明抛出的,这些异常必需用try catch抛出,或throws处理,如果不处理,程序将编译失败。比如:IOException、FileNotFoundException、SQLException等。

运行时异常是程序运行时可能报出的异常。可以用try catch抓取,也可以不做任何处理。例如:NullPointerException 异常就是一种比较常见的运行时异常。

【分析】

  1. Integer与int的区别?

【参考答案】

int是java提供的8种原始数据类型之一,另外Java为每个原始类型提供了封装类,Integer是java为int提供的封装类。int的默认值为0,而Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况。

  1. Java Reflection是什么【】

【参考答案】

JAVA反射,Reflection是Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说"自审",并能直接操作程序的内部属性。

【分析】

  1. 写几个java.lang.Object类中的方法名称。

【参考答案】

主要有equals()、toString()、getClass()、hashCode()、clone()、 notify()、wait()、notify()方法。

【分析】

这种题能记多少个就说多少个,不一定要求你所有的都记住,但是要理解其中部分重要方法的含义和作用。

  1. &和&&的区别?

【参考答案】

&和&&都可以用作逻辑与的运算符,表示逻辑与(and),当运算符两边的表达式的结果都为true时,整个运算结果才为true,否则,只要有一方为false,则结果为false。

&&还具有短路的功能,即如果第一个表达式为false,则不再计算第二个表达式。

&还可以用作位运算符,当&操作符两边的表达式不是boolean类型时,&表示按位与操作,我们通常使用0x0f来与一个整数进行&运算,来获取该整数的最低4个bit位。

【分析】

先说分别说两者的作用,再说出&&和&各自的不同之处。

  1. 数组有没有length()这个方法,String有没有length()这个方法。

【参考答案】

数组没有length()方法,但有length属性
    String有length()方法。

【分析】

考查平时使用数组和字符串的一些细节,一般在使用

  1. String s=new String(“xyz”)创建了几个对象

【参考答案】

2个string对象,一个是=null的s,一个是=“xyz”的string

两个或一个”xyz”对应一个对象,这个对象放在字符串常量缓冲区,常量”xyz”不管出现多少遍,都是缓冲区中的那一个。New String每写一遍,就创建一个新的对象,它一句那个常量”xyz”对象的内容来创建出一个新String对象。如果以前就用过’xyz’,这句代表就不会创建”xyz”自己了,直接从缓冲区拿。

【分析】

  1. 最常见的runtime exception运行时异常?

【参考答案】

ClassCastException(类型转换异常)、NumberFormatException(格式化异常)、

ArrayIndexOutOfBoundsException(数组越界异常)、ArithmeticException(算术异常)、  NullPointerException(空指针异常)等等

【分析】

这道题主要考查大家平时在项目开发过程中经常遇到的一些异常类型信息,通过这些异常来考查大家的项目经验与项目排错能力。

  1. 用JDBC来实现访问数据库记录可以采用下面的几个步骤:

【参考答案】

1、 通过驱动器管理器获取连接接口(Connection)。

2、 获得Statement或它的子类。

3、 指定Statement中的参数。

4、 通过Statement发送SQL语句。

5、 检查并处理返回的结果。

6、 关闭Statement。

7、 关闭连接接

【分析】

  1. Error和 exception的区别与联系?

【参考答案】

error 表示恢复不是不可能,但很困难的情况下的一种严重问题。比如说内存溢,网络故障等,不可能指望程序能处理的一类错误。
    Exception 表示一种由程序设计或实现问题,像我们常说的异常处理,就是属于这类,一般程序可以捕获和处理这些异常。

【分析】

这道题的难点在Error很多时候由于我们无法重现这种Error导致很多同学甚至不知道Error到底是什么,所以很容易把题目中的两种错误划上等号。

  1. 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。

  1. 面向对象的特征有哪些方面?

【参考答案】

面向对象的编程语言有封装、继承 、多态等3个主要的特征。

  1. 封装

封装是保证软件部件具有优良的模块性的基础,封装的目标就是要实现软件部件的“高内聚、低耦合”,防止程序相互依赖性而带来的变动影响。面向对象的封装就是把描述一个对象的属性和行为的代码封装在一个“模块”中,也就是一个类中,属性用变量定义,行为用方法进行定义,方法可以直接访问同一个对象中的属性。

  1. 继承

在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并可以加入若干新的内容,或修改原来的方法使之更适合特殊的需要,这就是继承。继承是子类自动共享父类数据和方法的机制,这是类之间的一种关系,提高了软件的可重用性和可扩展性。

  1. 多态

多态是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。多态性增强了软件的灵活性和扩展性。

  1. JVM工作原理?

运行jvm 字符码的工作是由解释器来完成的。解释执行过程分三步进行:

代码的装入、代码的校验、和代码的执行。

装入代码的工作由“类装载器class loader”完成。类装载器负责装入运行一个程序需要的所有代码,这也包括程序代码中的类所继承的类和被调用的类。当类装载器装入一个类时,该类被放在自己的名字空间中。除了通过符号引用自己名字空间以外的类,类之间没有其他办法可以影响其他类。在本台计算机的所有类都在同一地址空间中,而所有从外部引进的类,都有一个自己独立的名字空间。这使得本地类通过共享相同的名字空间获得较高的运行效率,同时又保证它们与从外部引进的类不会相互影响。当装入了运行程序需要的所有类后,解释器便可确定整个可执行程序的内存布局。解释器为符号引用与特定的地址空间建立对应关系及查询表。通过在这一阶段确定代码的内布局,java很好地解决了由超类改变而使子类

崩溃的问题,同时也防止了代码的非法访问。随后,被装入的代码由字节码校验器进行检查。校验器可以发现操作数栈益处、非法数据类型转化等多种错误。通过校验后,代码便开始执行了。

Java字节码的执行有两种方式:

1)即时编译方式:解释器先将字节编译成机器码,然后再执行该机器码。

2)解释执行方式:解释器通过每次解释并执行一小段代码来完成java字节。

码程序的所有操作。

  1. 说说Java中的内存分配?

Java把内存分成两种,一种叫做栈内存,一种叫做堆内存

在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作它用。

堆内存用于存放由new创建的对象和数组。在堆中分配的内存,由java虚拟机自动垃圾回收器来管理。在堆中产生了一个数组或者对象后,还可以在栈中定义一个特殊的变量,这个变量的取值等于数组或者对象在堆内存中的首地址,在栈中的这个特殊的变量就变成了数组或者对象的引用变量,以后就可以在程序中使用栈内存中的引用变量来访问堆中的数组或者对象,引用变量相当于为数组或者对象起的一个别名,或者代号。

引用变量是普通变量,定义时在栈中分配内存,引用变量在程序运行到作用域外释放。而数组&对象本身在堆中分配,即使程序运行到使用new产生数组和对象的语句所在地代码块之外,数组和对象本身占用的堆内存也不会被释放,数组和对象在没有引用变量指向它的时候,才变成垃圾,不能再被使用,但是仍然占着内存,在随后的一个不确定的时间被垃圾回收器释放掉。这个也是java比较占内存的主要原因。但是在写程序的时候,可以人为的控制。

  1. final, finally, finalize的区别。

【参考答案】

final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。

内部类要访问局部变量,局部变量必须定义成final类型,例如,一段代码……

finally是异常处理语句结构的一部分,表示总是执行。

finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。JVM不保证此方法总被调用

  1. ExtendsImplement的不同?

【参考答案】

extends是继承父类,只要那个类不是声明为final或者那个类定义为abstract的就能继承,JAVA中不支持多重继承,但是可以用接口来实现,这样就要用到implements,继承只能继承一个类,但implements可以实现多个接口,用逗号分开就行了

比如 class A extends B implements C,D,E

  1. 抽象类是否可以没有抽象方法?为什么?

【参考答案】

可以在java中用abstract关键字来修饰一个类时,这个类叫做抽象类。

抽象类中不一定要包含abstract方法,但一个类中包含了abstract方法,则这个类必须声明为abstract类。

  1. 静态的多态和动态的多态的区别?

【参考答案】

静态的多态: 即为重载 ;方法名相同,参数个数或类型不相同。(overloading)

动态的多态: 即为重写;子类覆盖父类的方法,将子类的实例传与父类的引用调用的是子类的方法  实现接口的实例传与接口的引用调用的实现类的方法。

  1. 说出一些常用的类,包,接口,请各举5个?

【参考答案】

常用的类:String、StringBuffer、 Integer 、Vector、ArrayList、Hashtable等

常用的包:java.lang   java.io  java.util 、java.sql 。

常用的接口:集合中的List、Set、 Map接口;与Servlet API相关的Servlet接口、HttpServletRequest,HttpServletResponse,HttpSession接口等。

  1. CollectionsCollection的区别【天晟科技】

【参考答案】

Collection是个java.util下的接口,它是各种集合结构的父接口,定义了集合对象的基本操作方法。Collections是个java.util下的工具类,它包含有各种有关集合操作的静态方法,主要是针对集合类的一个帮助类或者叫包装类,它提供一系列对各种集合的搜索,排序,线程安全化等操作方法。

  1. Class.forName的作用?为什么要用?

【参考答案】

按参数中指定的字符串形式的类名去搜索并加载相应的类,如果该类字节码已经被加载过,则返回代表该字节码的Class实例对象,否则,按类加载器的委托机制去搜索和加载该类,如果所有的类加载器都无法加载到该类,则抛出ClassNotFoundException。加载完这个Class字节码后,接着就可以使用Class字节码的newInstance方法去创建该类的实例对象了。有时候,我们程序中所有使用的具体类名在设计时(即开发时)无法确定,只有程序运行时才能确定,这时候就需要使用Class.forName去动态加载该类,这个类名通常是在配置文件中配置的,例如,spring的ioc中每次依赖注入的具体类就是这样配置的,jdbc的驱动类名通常也是通过配置文件来配置的,以便在产品交付使用后不用修改源程序就可以更换驱动类名。

  1. 接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承具体类【天威诚信面试题】

【参考答案】

接口可以继承接口。抽象类可以实现(implements)接口,抽象类是否可继承具体类。抽象类中可以有静态的main方法。

备注:只要明白了接口和抽象类的本质和作用,这些问题都很好回答,你想想,如果你是java语言的设计者,你是否会提供这样的支持,如果不提供的话,有什么理由吗?如果你没有道理不提供,那答案就是肯定的了。

只有记住抽象类与普通类的唯一区别就是不能创建实例对象和允许有abstract方法。

  1. char型变量中能不能存贮一个中文汉字?为什么?

【参考答案】

char型变量是用来存储Unicode编码的字符的,unicode编码字符集中包含了汉字,所以,char型变量中当然可以存储汉字啦。不过,如果某个特殊的汉字没有被包含在unicode编码字符集中,那么,这个char型变量中就不能存储这个特殊汉字。补充说明:unicode编码占用两个字节,所以,char类型的变量也是占用两个字节。

  1. 写clone()方法时,通常都有一行代码,是什么?

【参考答案】

clone 有缺省行为,super.clone();因为首先要把父类中的成员复制到位,然后才是复制自己的成员。

  1. 说说常用集合类有哪些?有哪些方法?

【参考答案】

通常我们使用的集合类都大多是由List、Set、Map这三类接口派生出来的类,例如:

ArrayList、Vector、LinkedList、Stack、TreeSet、Hashtable、HashMap等

集合类的大部分方法都是由Collection接口定义的,主要包括有:

add(E e)、remove(Object e)、addAll(),remove()、contains(Object obj)、clear()等

  1. 请说出作用域public,private,protected,以及不写时的区别?【天威诚信面试题】

【参考答案】

这四个作用域的可见范围如下表所示。

说明:如果在修饰的元素上面没有写任何访问修饰符,则表示friendly。

作用域    同一类  同一package 子孙类 其他package

public    √     √          √       √

protected  √     √          √      ×

friendly   √     √          ×      ×

private    √     ×          ×      ×

备注:只要记住了有4种访问权限,4个访问范围,然后将全选和范围在水平和垂直方向上分别按排从小到大或从大到小的顺序排列,就很容易画出上面的图了。

  1. 构造器Constructor是否可被override? 【亿阳通讯面试题】

【参考答案】

构造器Constructor不能被继承,因此不能重写Override,但可以被重载Overload。

  1. 是否可以从一个static方法内部发出对非static方法的调用? 【世承软件面试题

【参考答案】

不可以。因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用时不需要创建对象,可以直接调用。

  1. Math.round(11.5)等於多少? Math.round(-11.5)等於多少?【雾隐美地传媒】

【参考答案】

Math类中提供了三个与取整有关的方法:ceil、floor、round,这些方法的作用与它们的英文名称的含义相对应,例如,ceil的英文意义是天花板,该方法就表示向上取整,所以,Math.ceil(11.3)的结果为12,Math.ceil(-11.3)的结果是-11;floor的英文意义是地板,该方法就表示向下取整,所以,Math.floor(11.6)的结果为11,Math.floor(-11.6)的结果是-12;最难掌握的是round方法,它表示“四舍五入”,算法为Math.floor(x+0.5),即将原来的数字加上0.5后再向下取整,所以,Math.round(11.5)的结果为12,Math.round(-11.5)的结果为-11。

  1. abstract class(抽象类)和interface(接口)有什么区别? 【百度应用中心面试题】

【参考答案】

含有abstract修饰符的class即为抽象类,abstract 类不能创建的实例对象。含有abstract方法的类必须定义为abstract class,abstract class类中的方法不必是抽象的。abstract class类中定义抽象方法必须在具体(Concrete)子类中实现,所以,不能有抽象构造方法或抽象静态方法。如果的子类没有实现抽象父类中的所有抽象方法,那么子类也必须定义为abstract类型。

接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。

下面比较一下两者的语法区别:

1.抽象类可以有构造方法,接口中不能有构造方法。

2.抽象类中可以有普通成员变量,接口中没有普通成员变量

3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。

4. 抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然

eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。

5. 抽象类中可以包含静态方法,接口中不能包含静态方法

6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。

7. 一个类可以实现多个接口,但只能继承一个抽象类。

下面接着再说说两者在应用上的区别:

【分析】

这道题的思路是先从总体解释抽象类和接口的基本概念,然后再比较两者的语法细节,最后再说两者的应用区别。比较两者语法细节区别的条理是:先从一个类中的构造方法、普通成员变量和方法(包括抽象方法),静态变量和方法,继承性等方面来回答。

  1. Collection框架中实现比较要实现什么接口?

【参考答案】

Comparable、Comparator接口

  1. 是否可以继承String类?

【参考答案】

String类是final类故不可以继承。

  1. 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。

String覆盖了equals方法和hashCode方法,而StringBuffer没有覆盖equals方法和hashCode方法,所以,将StringBuffer对象存储进Java集合类中时会出现问题。

  1. StringBuffer与StringBuilder的区别

【参考答案】

StringBuffer和StringBuilder类都表示内容可以被修改的字符串,StringBuilder是线程不安全的,运行效率高,如果一个字符串变量是在方法里面定义,这种情况只可能有一个线程访问它,不存在不安全的因素了,则用StringBuilder。如果要在类里面定义成员变量,并且这个类的实例对象会在多线程环境下使用,那么最好用StringBuffer。

  1. try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后? 【杭州天眼科技】

【参考答案】

答案是在return之前。

【分析】

程序代码的运行结果:

public  class Test {

public static void main(String[] args) {

// TODO Auto-generated method stub

System.out.println(new Test().test());;

}

static int test()

{

int x = 1;

try

{

return x;

}

finally

{

++x;

}

}

}

---------执行结果 ---------

1

运行结果是1,为什么呢?主函数调用子函数并得到结果的过程,好比主函数准备一个空罐子,当子函数要返回结果时,先把结果放在罐子里,然后再将程序逻辑返回到主函数。所谓返回,就是子函数说,我不运行了,你主函数继续运行吧,这没什么结果可言,结果是在说这话之前放进罐子里的。

下面的程序代码输出的结果是多少?

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语句后才真正开始返回。

在讲解答案时可以用下面的程序来帮助分析:

public  class Test {

/**

* @param args add by zxx ,Dec 9, 2008

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

System.out.println(new Test().test());;

}

int test()

{

try

{

return func1();

}

finally

{

return func2();

}

}

int func1()

{

System.out.println("func1");

return 1;

}

int func2()

{

System.out.println("func2");

return 2;

}

}

-----------执行结果-----------------

func1

func2

2

结论:finally中的代码比return 和break语句后执行。

  1. Java中的异常处理机制的简单原理和应用。

【参考答案】

异常是指java程序运行时(非编译)所发生的非正常情况或错误,与现实生活中的事件很相似,现实生活中的事件可以包含事件发生的时间、地点、人物、情节等信息,可以用一个对象来表示,Java使用面向对象的方式来处理异常,它把程序中发生的每个异常也都分别封装到一个对象来表示的,该对象中包含有异常的信息。

Java对异常进行了分类,不同类型的异常分别用不同的Java类表示,所有异常的根类为java.lang.Throwable,Throwable下面又派生了两个子类:Error和Exception,Error 表示应用程序本身无法克服和恢复的一种严重问题,程序只有死的份了,例如,说内存溢出和线程死锁等系统问题。Exception表示程序还能够克服和恢复的问题,其中又分为系统异常和普通异常,系统异常是软件本身缺陷所导致的问题,也就是软件开发人员考虑不周所导致的问题,软件使用者无法克服和恢复这种问题,但在这种问题下还可以让软件系统继续运行或者让软件死掉,例如,数组脚本越界(ArrayIndexOutOfBoundsException),空指针异常(NullPointerException)、类转换异常(ClassCastException);普通异常是运行环境的变化或异常所导致的问题,是用户能够克服的问题,例如,网络断线,硬盘空间不够,发生这样的异常后,程序不应该死掉。

java为系统异常和普通异常提供了不同的解决方案,编译器强制普通异常必须try..catch处理或用throws声明继续抛给上层调用方法处理,所以普通异常也称为checked异常,而系统异常可以处理也可以不处理,所以,编译器不强制用try..catch处理或用throws声明,所以系统异常也称为unchecked异常。

  1. 多线程有几种实现方法?同步有几种实现方法?

【参考答案】

多线程有两种实现方法,分别是继承Thread类与实现Runnable接口。

同步的实现方面有两种,分别是synchronized,wait与notify 。

  1. wait():使一个线程处于等待状态,并且释放所持有的对象的lock。
  2. sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常。
  3. notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。
  4. allnotity():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。
  1. 启动一个线程是用run()还是start()?

【参考答案】

启动一个线程是调用start()方法,使线程就绪状态,以后可以被调度为运行状态,一个线程必须关联一些具体的执行代码,run()方法是该线程所关联的执行代码。

  1. 内部类可以引用外部类的成员吗?有没有什么限制?

【参考答案】

完全可以。如果不是静态内部类,那没有什么限制!

如果你把静态嵌套类当作内部类的一种特例,那在这种情况下不可以访问外部类的普通成员变量,而只能访问外部类中的静态成员。

  1. List和 Map 区别?【软通动力】

【参考答案】

一个是存储单列数据的集合,另一个是存储键和值这样的双列数据的集合,List中存储的数据是有顺序,并且允许重复;Map中存储的数据是没有顺序的,其键是不能重复的,它的值是可以有重复的。

  1. ArrayList和Vector的区别【博炎科技】

【参考答案】

这两个类都实现了List接口(List接口继承了Collection接口),他们都是有序集合,即存储在这两个集合中的元素的位置都是有顺序的,相当于一种动态的数组,我们以后可以按位置索引号取出某个元素,并且其中的数据是允许重复的。

接着说ArrayList与Vector的区别,这主要包括两个方面:
1、同步性:

Vector是线程安全的,也就是说是它的方法之间是线程同步的,而ArrayList是线程序不安全的,它的方法之间是线程不同步的。如果只有一个线程会访问到集合,那最好是使用ArrayList,因为它不考虑线程安全,效率会高些;如果有多个线程会访问到集合,那最好是使用Vector,因为不需要我们自己再去考虑和编写线程安全的代码。

备注:对于Vector&ArrayList、Hashtable&HashMap,要记住线程安全的问题,记住Vector与Hashtable是旧的,是java一诞生就提供了的,它们是线程安全的,ArrayList与HashMap是java2时才提供的,它们是线程不安全的。
2、数据增长:

ArrayList与Vector都有一个初始的容量大小,当存储进它们里面的元素的个数超过了容量时,就需要增加ArrayList与Vector的存储空间,每次要增加存储空间时,不是只增加一个存储单元,而是增加多个存储单元,每次增加的存储单元的个数在内存空间利用与程序效率之间要取得一定的平衡。Vector默认增长为原来两倍,而ArrayList的增长为原来的1.5倍。ArrayList与Vector都可以设置初始的空间大小,Vector还可以设置增长的空间大小,而ArrayList没有提供设置增长空间的方法。

  1. heap和stack有什么区别。

【参考答案】

Java的内存分为两类,一类是栈内存,一类是堆内存。栈内存是指程序进入一个方法时,会为这个方法单独分配一块私属存储空间,用于存储这个方法内部的局部变量,当这个方法结束时,分配给这个方法的栈会释放,这个栈中的变量也将随之释放。

堆是与栈作用不同的内存,一般用于存放不放在当前方法栈中的那些数据,例如,使用

new创建的对象都放在堆里,所以,它不会随方法的结束而消失。方法中的局部变量使

用final修饰后,放在堆中,而不是栈中。

  1. Java 类实现序列化的方法(二种)?如在collection框架中实现排序,要实现什么样的接口 

【参考答案】

  java.io.Serializable接口或实现Externalizable 接口。

  Collection框架中实现比较要实现Comparable 接口或 Comparator 接口并实现比较方法

  1. 什么是Java序列化,如何实现java序列化?或者请解释Serializable接口的作用。 【东软国际】

【参考答案】

序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。

序列化的实现:将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出,那么在另一端,通过ObjectInputStream对象的readObject(Object obj)获取到字节流数据后,要将字节流转换成原对象,这叫反序列化,以便将数据存储在文件中或在网络传输。

Serializable 接口描述启用其序列化功能,未实现此接口的类将无法使其任何状态序列化或反序列化。Serializable 接口没有方法或字段,仅用于标识可序列化的语义,标识实现了该接口的对象属性可被序列化。

  1. Java中有几种类型的流?JDK为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类?

【参考答案】

字节流,字符流两种类型流。字节流继承于InputStream、 OutputStream;字符流继承于ReaderWriter。 其它与IO操作相关的类都是派生至上述4个抽象类,如字节相关的:FileInputStream、FileOutputStream类;字符相关的:BufferedReader、BufferedWriter类

  1. JVM加载class文件原理?

【参考答案】

所谓装载就是寻找一个类或是一个接口的二进制形式并用该二进制形式来构造代表这个类或是这个接口的class对象的过程.
    在Java中,类装载器把一个类装入Java虚拟机中,要经过三个步骤来完成:装载、链接和初始化,其中链接又可以分成校验、准备、解析
    装载:查找和导入类或接口的二进制数据;
    链接:执行下面的校验、准备和解析步骤,其中解析步骤是可以选择的;
    校验:检查导入类或接口的二进制数据的正确性;
    准备:给类的静态变量分配并初始化存储空间;
    解析:将符号引用转成直接引用;
    初始化:激活类的静态变量的初始化Java代码和静态Java代码块
JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader 是一个重要的Java运行时系统组件。它负责在运行时查找和装入类文件的类
一个Java应用程序使用两种类型的类装载器:根装载器(bootstrap)和用户定义的装载器(user-defined)。
根装载器以某种默认的方式将类装入,包括那些Java API的类。在运行期间一个Java程序能安装用户自己定义的类装载器。根装载器是虚拟机固有的一部分,而用户定义的类装载器则不是,它是用Java语言写的,被编译成class文件之后然后再被装入到虚拟机,并像其它的任何对象一样可以被实例化。 Java类装载器的体系结构如下所示:
            Bootstrap(根装载器)
                |
            Extension (扩展装载器)
                 |
               System
                 |
              UserDefine1
                 /           \
UserDefine2  UserDefine3
                            |
                                UserDefine4
Java的类装载模型是一种代理(delegation)模型。当JVM 要求类装载器CL(ClassLoader)装载一个类时,CL首先将这个类装载请求转发给他的父装载器。只有当父装载器没有装载并无法装载这个类时,CL才获得装载这个类的机会。这样, 所有类装载器的代理关系构成了一种树状的关系。树的根是类的根装载器(bootstrap ClassLoader) , 在JVM 中它以"null"表示。除根装载器以外的类装载器有且仅有一个父装载器。在创建一个装载器时, 如果没有显式地给出父装载器, 那么JVM将默认系统装载器为其父装载器
下面针对各种类装载器分别进行详细的说明:
  根(Bootstrap) 装载器:该装载器没有父装载器,它是JVM实现的一部分,从sun.boot.class.path装载运行时库的核心代码。
  扩展(Extension) 装载器:继承的父装载器为根装载器,不像根装载器可能与运行时的操作系统有关,这个类装载器是用纯Java代码实现的,它从java.ext.dirs (扩展目录)中装载代码。
  系统(System or Application) 装载器:装载器为扩展装载器,我们都知道在安装JDK的时候要设置环境变量(CLASSPATH ),这个类装载器就是从java.class.path(CLASSPATH 环境变量)中装载代码的,它也是用纯Java代码实现的,同时还是用户自定义类装载器的缺省父装载器。
 小应用程序(Applet) 装载器: 装载器为系统装载器,它从用户指定的网络上的特定目录装载小应用程序代码。

  1. SOCKET中有几中连接方式,各有什么区别?

【参考答案】

Sockets有两种主要的操作方式:面向连接(TCP/IP)的和无连接(UDP)的。无连接的操作使用数据报协议,无连接的操作是快速的和高效的,但是数据安全性不佳. 面向连接的操作使用TCP协议.面向连接的操作比无连接的操作效率更低,但是数据的安全性更高

【分析】

  1. 抽象类能否被实例化 ?抽象类的作用是什么?

【参考答案】

抽象类一般不能被实例化;抽象类通常不是由程序员定义的,而是由项目经理或模块设计人 设计抽象类的原因通常是为了规范方法名 抽象类必须要继承,不然没法用,作为模块设计者,可以把让底层程序员直接用得方法直接调用,而一些需要让程序员覆盖后自己做得方法则定义称抽象方法

【分析】

  1. LinkedlistArraylist内部是如何实现的(更深入的问了LinkedList与ArrayList的区别) 【天威诚信面试题】

【参考答案】

ArrayList的内部实现是基于内部数组Object[],它更像是对数组实现的一种封装,所以在向ArrayList的前面或中间插入数据时,必须将其后的所有数据相应的后移,这样必然要花费较多时间。

而LinkedList的内部实现是基于一组双向链表实现的存储特性,所以提供了链表一样访问的API接口,它们在性能上有很大的差别。当你访问Linkedlist链表中的某个元素时,就必须从链表的一端开始沿着连接方向一个一个元素地去查找,直到找到所需的元素为止,所以,当你的操作是在一列数据的前面或中间添加或删除数据,并且按照顺序访问其中的元素时,就应该使用LinkedList了。

而当你的操作是在一列数据的后面添加数据而不是在前面或中间,并且需要随机地访问其中的元素时,使用ArrayList会提供比较好的性能。

【分析】

  1. Hashtable的原理【北辰网络】

【参考答案】

通过节点的关键码确定节点的存储位置,即给定节点的关键码k,通过一定的函数关系H(散列函数),得到函数值H(k),将此值解释为该节点的存储地址

  1. JDBC中的PreparedStatement相比Statement的好处?

【参考答案】

预编译语句java.sql.PreparedStatement ,扩展自 Statement,不但具有 Statement 的所有能力而且具有更强大的功能。不同的是,PreparedStatement 是在创建语句对象的同时给出要执行的sql语句。这样,sql语句就会被系统进行预编译,执行的速度会有所增加,尤其是在执行大语句的时候,效果更加理想

  1. 概述反射和序列化

【参考答案】

Reflection:是Java被视为动态语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等等)、superclass(例如Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods。

序列化:就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时的问题。

  1. Java中实现多态的机制是什么?

【参考答案】

重写,重载

方法的重写Overriding和重载Overloading是Java多态性的不同表现。

重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了。

果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型。

  1. Overload和Override的区别?Overloaded的方法是否可以改变返回值的类型? 【软通动力】

【参考答案】

Overload是重载的意思,Override是覆盖的意思,也就是重写。

重载Overload表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不同)。

重写Override表示子类中的方法可以与父类中的某个方法的名称和参数完全相同,通过子类创建的实例对象调用这个方法时,将调用子类中的定义方法,这相当于把父类中定义的那个完全相同的方法给覆盖了,这也是面向对象编程的多态性的一种表现。子类覆盖父类的方法时,只能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常,因为子类可以解决父类的一些问题,不能比父类有更多的问题。子类方法的访问权限只能比父类的更大,不能更小。如果父类的方法是private类型,那么,子类则不存在覆盖的限制,相当于子类中增加了一个全新的方法。

是否可以改变返回值类型,在重载的定义中,与方法是什么类型返回值无关。

【分析】

override可以翻译为覆盖,从字面就可以知道,它是覆盖了一个方法并且对其重写,以求达到不同的作用。对我们来说最熟悉的覆盖就是对接口方法的实现,在接口中一般只是对方法进行了声明,而我们在实现时,就需要实现接口声明的所有方法。除了这个典型的用法以外,我们在继承中也可能会在子类覆盖父类中的方法。在覆盖要注意以下的几点:

1、覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配,才能达到覆盖的效果;

2、覆盖的方法的返回值必须和被覆盖的方法的返回一致;

3、覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其子类;

4、被覆盖的方法不能为private,否则在其子类中只是新定义了一个方法,并没有对其进行覆盖。

overload对我们来说可能比较熟悉,可以翻译为重载,它是指我们可以定义一些名称相同的方法,通过定义不同的输入参数来区分这些方法,然后再调用时,VM就会根据不同的参数样式,来选择合适的方法执行。在使用重载要注意以下的几点:

1、在使用重载时只能通过不同的参数样式。例如,不同的参数类型,不同的参数个数,不同的参数顺序(当然,同一方法内的几个参数类型必须不一样,例如可以是fun(int,float),但是不能为fun(int,int));

2、不能通过访问权限、返回类型、抛出的异常进行重载;

3、方法的异常类型和数目不会对重载造成影响;

4、对于继承来说,如果某一方法在父类中是访问权限是priavte,那么就不能在子类对其进行重载,如果定义的话,也只是定义了一个新方法,而不会达到重载的效果。

  1. ClassLoader如何加载class 。

【参考答案】

jvm里有多个类加载,每个类加载可以负责加载特定位置的类,例如,bootstrap类加载负责加载jre/lib/rt.jar中的类, 我们平时用的jdk中的类都位于rt.jar中。extclassloader负责加载jar/lib/ext/*.jar中的类,appclassloader负责classpath指定的目录或jar中的类。除了bootstrap之外,其他的类加载器本身也都是java类,它们的父类是ClassLoader。

  1. ArrayList如何实现插入的数据按自定义的方式有序存放

【参考答案】

实现Comparable 比较接口,并实现compareTo方法。排序的方法,取决于compareTo方法中的比较定义的返回值,一般有3个返回值:1、-1、0表示不同的比较结果。

程序示例:

class MyBean implements Comparable{

public int compareTo(Object obj){

if(! obj instanceof MyBean)

throw new ClassCastException();

MyBean other = (MyBean) obj;

return age > other.age?1:age== other.age?0:-1;

}

}

class MyTreeSet {

private ArrayList  datas = new ArrayList();

public void add(Object obj){

for(int i=0;i<datas.size();i++){

if(obj.compareTo(datas.get(i) != 1){

datas.add(i,obj);

}

}

}

}

  1. hashCode方法的作用?  

【参考答案】

hashcode这个方法是用来鉴定2个对象是否相等的。hashcode方法一般用户不会去调用,比如在hashmap中,由于key是不可以重复的,他在判断key是不是重复的时候就判断了hashcode这个方法,而且也用到了equals方法。这里不可以重复是说equals和hashcode只要有一个不等就可以了!所以简单来讲,hashcode相当于是一个对象的编码。我们一般在覆盖equals的同时也要覆盖hashcode,让他们的逻辑一致。

  1. 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是什么。

  1. Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)?

【参考答案】

可以继承其他类或实现其他接口。不仅是可以,而是必须!

  1. JAVA语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出异常吗?

【参考答案】

Java使用面向对象的方式来处理异常,它把程序中发生的每个异常也都分别封装到一个对象来表示的,该对象中包含有异常的信息。而throws\throw\try、catch、finally就是Java中用来对异常进行处理的几个关键字,在Java编程中规容Java编译器强制普通异常必须try..catch处理或用throws声明继续抛给上层调用方法处理,一般异常必须要求被捕获和处理,而系统异常可以处理也可以不处理,所以编译器不强制用try..catch处理或用throws、throw声明异常。而finally一般与try或try\catch一起使用做为异常的最后处理出口。

  1. 同步和异步有何异同,在什么情况下分别使用他们?举例说明。

【参考答案】

如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。

当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。

  1. 当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?

【参考答案】

分几种情况:

1.其他方法前是否加了synchronized关键字,如果没加,则能。

2.如果这个方法内部调用了wait,则可以进入其他synchronized方法。

3.如果其他个方法都加了synchronized关键字,并且内部没有调用wait,则不能。

4.如果其他方法是static,它用的同步锁是当前类的字节码,与非静态的方法不能同步,因为非静态的方法用的是this。

  1. 线程的基本概念、线程的基本状态以及状态之间的关系

【参考答案】

一个程序中可以有多条执行线索同时执行,一个线程就是程序中的一条执行线索,每个线程上都关联有要执行的代码,即可以有多段程序代码同时运行,每个程序至少都有一个线程,即main方法执行的那个线程。如果只是一个cpu,它怎么能够同时执行多段程序呢?这是从宏观上来看的,cpu一会执行a线索,一会执行b线索,切换时间很快,给人的感觉是a,b在同时执行,好比大家在同一个办公室上网,只有一条链接到外部网线,其实,这条网线一会为a传数据,一会为b传数据,由于切换时间很短暂,所以,大家感觉都在同时上网。

状态:就绪,运行,synchronize阻塞,wait和sleep挂起,结束。wait必须在synchronized内部调用。

调用线程的start方法后线程进入就绪状态,线程调度系统将就绪状态的线程转为运行状态,遇到synchronized语句时,由运行状态转为阻塞,当synchronized获得锁后,由阻塞转为运行,在这种情况可以调用wait方法转为挂起状态,当线程关联的代码执行完后,线程变为结束状态。

  1. 简述synchronized和java.util.concurrent.locks.Lock的异同

【参考答案】

主要相同点:Lock能完成synchronized所实现的所有功能

主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。Lock还有更强大的功能,例如,它的tryLock方法可以非阻塞方式去拿锁。

  1. 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的方法是synchronized的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。

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

  1. List、Set、Map是否继承自Collection接口?

【参考答案】

List、Set是,Map不是; Map接口定义的是Key-Value存储的特性,与List和Set不同,Map在存储对象时,先要定义这个对象的key的值,再存入与这个key相对应的Object,Map集合的取值时根据存入的key(关键字)来获取与这个关键字对应的对象。

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

【参考答案】

首先,List与Set具有相似性,它们都是单列元素的集合,所以,它们有一个功共同的父接口Collection接口。Set里面不允许有重复的元素,即不能有两个相等的对象 。

List表示有先后顺序的集合, 当我们多次调用add(Obj e)方法时,每次加入的对象就像火车站买票有排队顺序一样,按先来后到的顺序排序。

Map与List和Set不同,它是双列的集合每次存储时,要存储一对key/value,不能存储重复的key,这个重复的规则也是按equals比较相等。取则可以根据key获得相应的value,即get(Object key)返回值为key 所对应的value。另外,也可以获得所有的key的结合。

【分析】

总结:List 以特定次序来持有元素,可有重复元素。Set 无法拥有重复元素,内部排序。Map 保存key-value值,value可多值。上面是大致不同,另外上述3个只是接口,而具体实现类中,用法大同小异,只是实现的数据结构不同,例如List接口下的LinkedList主要实现了双链表的存储特点,Vector是线程安全的集合类。

  1. 说出ArrayList,Vector, LinkedList的存储性能和特性。【大唐动力面试题

【参考答案】

ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。

LinkedList也是线程不安全的,LinkedList提供了一些方法,使得LinkedList可以被当作堆栈和队列来使用。

  1. 如何去掉一个Vector集合中重复的元素

【参考答案】

Vector newVector = new Vector();

for (int i=0;i<vector.size();i++)

{

Object obj = vector.get(i);

if(!newVector.contains(obj);

newVector.add(obj);

}

还有一种简单的方式,HashSet set = new HashSet(vector);

  1. Set里的元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?

【参考答案】

Set里的元素是不能重复的,元素重复与否是使用equals()方法进行判断的。

  1. 两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?

【参考答案】

对。

如果对象要保存在HashSet或HashMap中,它们的equals相等,那么,它们的hashcode值就必须相等。

如果不是要保存在HashSet或HashMap,则与hashcode没有什么关系了,这时候hashcode不等是可以的,例如arrayList存储的对象就不用实现hashcode方法。

  1. 字节流与字符流的区别

【参考答案】

要把一片二进制数据数据逐一输出到某个设备中,或者从某个设备中逐一读取一片二进制数据,不管输入输出设备是什么,我们要用统一的方式来完成这些操作,用一种抽象的方式进行描述,这个抽象描述方式起名为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);

}

}

  1. java里面的io跟nio有什么区别

【参考答案】

1、Java NIO和IO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。

2、Java IO的各种流是阻塞的。而Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。

3、选择器上,Java IO无选择器,而NIO有选择器,Java NIO的选择器允许一个单独的线程来监视多个输入通道,你可以注册多个通道使用一个选择器,然后使用一个单独的线程来“选择”通道:这些通道里已经有可以处理的输入,或者选择已准备写入的通道。

  1. Java中会存在内存泄漏吗,请简单描述。

【参考答案】

所谓内存泄露就是指一个不再被程序使用的对象或变量一直被占据在内存中。java中有垃圾回收机制,它可以保证一对象不再被引用的时候,即对象变成了孤儿的时候,对象将自动被垃圾回收器从内存中清除掉。由于Java 使用有向图的方式进行垃圾回收管理,可以消除引用循环的问题,例如有两个对象,相互引用,只要它们和根进程不可达的,那么GC也是可以回收它们的,例如下面的代码可以看到这种情况的内存回收:

package com.huawei.interview;

import java.io.IOException;

public class GarbageTest {

/**

* @param args

* @throws IOException

*/

public static void main(String[] args) throws IOException {

// TODO Auto-generated method stub

try {

gcTest();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

System.out.println("has exited gcTest!");

System.in.read();

System.in.read();

System.out.println("out begin gc!");

for(int i=0;i<100;i++)

{

System.gc();

System.in.read();

System.in.read();

}

}

private static void gcTest() throws IOException {

System.in.read();

System.in.read();

Person p1 = new Person();

System.in.read();

System.in.read();

Person p2 = new Person();

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!");

}

private static class Person

{

byte[] data = new byte[20000000];

Person mate = null;

public void setMate(Person other)

{

mate = other;

}

}

}

java中的内存泄露的情况:长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被回收,这就是java中内存泄露的发生场景,通俗地说,就是程序员可能创建了一个对象,以后一直不再使用这个对象,这个对象却一直被引用,即这个对象无用但是却无法被垃圾回收器回收的,这就是java中可能出现内存泄露的情况,例如,缓存系统,我们加载了一个对象放在缓存中(例如放在一个全局map对象中),然后一直不再使用它,这个对象一直被缓存引用,但却不再被使用。

检查java中的内存泄露,一定要让程序将各种分支情况都完整执行到程序结束,然后看某个对象是否被使用过,如果没有,则才能判定这个对象属于内存泄露。

如果一个外部类的实例对象的方法返回了一个内部类的实例对象,这个内部类对象被长期引用了,即使那个外部类实例对象不再被使用,但由于内部类持久外部类的实例对象,这个外部类对象将不会被垃圾回收,这也会造成内存泄露。

[] 是对象已不可到达,而内存又没有回收,真正的内存黑洞。
   而Java的泄漏,则是因为各种原因,对象对应用已经无用,但一直被持有,一直可到达。
   总结原因无外乎几方面:

  1. 被生命周期极长的集合类不当持有,号称是Java内存泄漏的首因。
    这些集合类的生命周期通常极长,而且是一个辅助管理性质的对象,在一个业务事务运行完后,如果没有将某个业务对象主动的从中清除的话,这个集合就会吃越来越多内存,可以用WeakReference,如WeakHashMap,使得它持有的对象不增加对象的引用数。
  2. Scope定义不对,这个很简单了,方法的局部变量定义成类的变量,类的静态变量等。
  3. 异常时没有加finally{}来释放某些资源,JDBC时代也是很普遍的事情。
  4. 另外一些我了解不深的原因,如:Swing里的Listener没有显式remove;内部类持有外部对象的隐式引用;Finalizers造成关联对象没有被及时清空等。

内存泄漏的检测

有不少工具辅助做这个事情的,如果手上一个工具也没有,可以用JDK自带的小工具:

  • 看看谁占满了Heap?
    用JDK6的jmap可以显示运行程序中对象的类型,个数与所占的大小
    先用jps 找到进程号,然后jmap -histo pid 显示或 jmap -dump:file=heap_file_name pid 导出heap文件
  • 为什么这些对象仍然可以到达?
    用jhat(Java Heap Analysis Tool) 分析刚才导出的heap文件。
    先jhat heap_file_name,然后打开浏览器http://localhost:7000/ 浏览。
  1. Hashcode和Equals的联系

【参考答案】

首先equals()和hashcode()这两个方法都是从object类中继承过来的,主要用来比较对象时进行调用。在object类中定义如下:

  1. 、如果两个对象相同,那么它们的hashCode值一定要相同;
  2. 、如果两个对象的hashCode相同,它们并不一定相同 上面说的对象相同指的是用eqauls方法比较。
  1. TreadThreadlocal的作用及区别?

【参考答案】

答:threadlocal是 线程局部变量(thread local variable),为每一个使用该线程的线程都提供一个变量值的副本,使每一个线程都可以独立地改变自己的副本,而不会和其他线程的副本产生冲突。

  1. TCP和UDP的区别?

【参考答案】

TCP/IP的运输层有两个不同的协议:①用户数据报协议UDP ②传输控制协议 TCP

二者最大区别:TCP是面向连接的,而UDP是无连接的.区别大致如下:

1)UDP传送的数据单位协议是 UDP 报文或用户数据报,TCP传送的数据单位协议是 TCP 报文段。

2)UDP发送数据之前不需要建立连接,因此减少了开销和发送之前的时延。TCP提供面向连接的服务,不提供广播或多播服务。

3)对方的运输层在收到 UDP 报文后,不需要给出任何确认。TCP则需要确认。

4)UDP没有拥塞控制,因此网络出现的拥塞不会使源主机的发送速率降低,也不保证可靠交付,因此主机不需要维持具有许多参数的、复杂的连接状态表。TCP 要提供可靠的、面向连接的运输服务,因此不可避免地增加了许多的开销,这不仅使协议数据单元的首部增大很多,还要占用许多的处理机资源。

5)UDP 用户数据报只有8个字节的首部开销,比TCP的20个字节的首部要短。

  1. 启动一个线程用什么方法?【北京永中软件面试题】

【参考】

使用Thread类的start()方法来启动一个线程,使线程进入就绪状态。如果自定义的类是Thread类的子类的话,可以直接使用Start()来启,如果是实现的Runnable接口的话,还要将该类的实例作为参数传入到Thread对象中来启动。

  1. 作用域public等写不写的区别?【北京永中软件面试题】

【参考】

作用域不写将采用默认的作用域,默认作用域的访问权限是包的权限,也就是除本包中的所有类能访问,不同包只有子类能访问。

  1. 同步和异步有何异同

【参考答案】

同步(synchronized)和异步(asynchronized)是对于多线程(multi-threading)而言的
    同步可防止并发 主要出于数据安全的考虑
如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。
    异步允许并发
    ajax技术通常都是异步实现的,异步主要使用在当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。

  1. Static方法和static字段有什么用处?可以被重载吗?

【参考答案】

用static 修饰的方法叫类方法,被所有实例共享;static修饰的字段为类变量,被所有实例共享,在使用类变量时,一般会结合final一起使用定义类常量,不允许被其它的类实例修改。

可以被重载,重载只是参数类型、顺序和个数不同。

  1. 请用Java写一个冒泡排序方法

【参考答案】

public static void Bubble(int a[]){

for(int i=0;i<a.length-1;i++){

for(int j=a.length-1;j>i;j--){

if(a[j]<a[j-1]){

a[j]=a[j]+a[j-1];

a[j-1]=a[j]-a[j-1];

a[j]=a[j]-a[j-1];

}

}

}

}

  1. 子线程循环10次,接着主线程循环100,接着又回到子线程循环10次,接着再回到主线程又循环100,如此循环50次,请写出程序。

【参考答案】

最终的程序代码如下:

public class ThreadTest {

/**

* @param args

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

new ThreadTest().init();

}

public void init()

{

final Business business = new Business();

new Thread(

new Runnable()

{

public void run() {

for(int i=0;i<50;i++)

{

business.SubThread(i);

}

}

}

).start();

for(int i=0;i<50;i++)

{

business.MainThread(i);

}

}

private class Business

{

boolean bShouldSub = true;//这里相当于定义了控制该谁执行的一个信号灯

public synchronized void MainThread(int i)

{

if(bShouldSub)

try {

this.wait();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

for(int j=0;j<5;j++)

{

System.out.println(Thread.currentThread().getName() + ":i=" + i +",j=" + j);

}

bShouldSub = true;

this.notify();

}

public synchronized void SubThread(int i)

{

if(!bShouldSub)

try {

this.wait();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

for(int j=0;j<10;j++)

{

System.out.println(Thread.currentThread().getName() + ":i=" + i +",j=" + j);

}

bShouldSub = false;

this.notify();

}

}

}

备注:不可能一上来就写出上面的完整代码,最初写出来的代码如下,问题在于两个线程的代码要参照同一个变量,即这两个线程的代码要共享数据,所以,把这两个线程的执行代码搬到同一个类中去:

package com.huawei.interview.lym;

public class ThreadTest {

private static boolean bShouldMain = false;

public static void main(String[] args) {

// TODO Auto-generated method stub

/*new Thread(){

public void run()

{

for(int i=0;i<50;i++)

{

for(int j=0;j<10;j++)

{

System.out.println("i=" + i + ",j=" + j);

}

}

}

}.start();*/

//final String str = new String("");

new Thread(

new Runnable()

{

public void run()

{

for(int i=0;i<50;i++)

{

synchronized (ThreadTest.class) {

if(bShouldMain)

{

try {

ThreadTest.class.wait();}

catch (InterruptedException e) {

e.printStackTrace();

}

}

for(int j=0;j<10;j++)

{

System.out.println(

Thread.currentThread().getName() +

"i=" + i + ",j=" + j);

}

bShouldMain = true;

ThreadTest.class.notify();

}

}

}

}

).start();

for(int i=0;i<50;i++)

{

synchronized (ThreadTest.class) {

if(!bShouldMain)

{

try {

ThreadTest.class.wait();}

catch (InterruptedException e) {

e.printStackTrace();

}

}

for(int j=0;j<5;j++)

{

System.out.println(

Thread.currentThread().getName() +

"i=" + i + ",j=" + j);

}

bShouldMain = false;

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 i=0;i<50;i++)

{

lock.lock();

try

{

if(!bBhouldSubThread)

subThreadCondition.await();

for(int j=0;j<10;j++)

{

System.out.println(Thread.currentThread().getName() + ",j=" + j);

}

bBhouldSubThread = false;

subThreadCondition.signal();

}catch(Exception e)

{

}

finally

{

lock.unlock();

}

}

}

});

threadPool.shutdown();

for(int i=0;i<50;i++)

{

lock.lock();

try

{

if(bBhouldSubThread)

subThreadCondition.await();

for(int j=0;j<10;j++)

{

System.out.println(Thread.currentThread().getName() + ",j=" + j);

}

bBhouldSubThread = true;

subThreadCondition.signal();

}catch(Exception e)

{

}

finally

{

lock.unlock();

}

}

}

  1. 写一个程序,把一个文件的数组按对角线做对称变换,并输出!

【参考答案】

一个正方形里面全数字,写一个程序,成对角线转变!     我做的这个是3行3列的对角互换,也许转换规则不一样

public class testMain {

public static void main(String[] args) {

int a[][]=new int[3][3];

int c=1;

//初始化数据

for(int i=0;i<3;i++){

for(int j=0;j<3;j++){

a[i][j]=c++;

}

}

System.out.println("转换之前:");

for(int i=0;i<3;i++){

for(int j=0;j<3;j++){

System.out.print("a["+i+"]["+j+"]="+a[i][j]+"   ");

}

System.out.println("\n");

}

for(int i=0;i<3;i++){

for(int j=0;j<3;j++){

if((i+1<3&&j+1<3)&&i==j&&i!=0&&i!=3-i){

int temp=a[i-1][j-1];

a[i-1][j-1]=a[i+1][j+1];

a[i+1][j+1]=temp;

temp=a[i-1][j+1];

a[i-1][j+1]=a[i+1][j-1];

a[i+1][j-1]=temp;

}

}

}

System.out.println("转换之后:");

for(int i=0;i<3;i++){

for(int j=0;j<3;j++){

System.out

print("a["+i+"]["+j+"]="+a[i][j]+"   ");

}

System.out.println("\n");

}

}

}

  1. 写一个方法,传入一个int 型的数字,把它的四个字节码取出来,并且把它按大小顺序通过控制台输出?

【参考答案】

public static void main(String[] args) {
        int num = -800000000;
        String str = Integer.toBinaryString(num); //获得num 的二进制
        if(num>=0) {    //如果输入的数为正数,位数可能不足32位,要补0;负数肯定是32位
            if(str.length()<32) { //二进制不足32位,就在前面补0
                int n0 = 32-str.length(); //看差几个0
                String temp = "";
                for(int i=0;i<n0;i++) {
                    temp = temp + "0"; //拼0
                }
                str = temp + str;
            }
        }
        String s1 = str.substring(0, 8);
        String s2 = str.substring(8, 16);
        String s3 = str.substring(16, 24);
        String s4 = str.substring(24, 32);
       
        System.out.println(str);
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);
        System.out.println(s4);      
       
        int n1=Integer.parseInt(s1,2);//以二进制把字符串解析为 10进制的数
        int n2=Integer.parseInt(s2,2);
        int n3=Integer.parseInt(s3,2);
        int n4=Integer.parseInt(s4,2);
        System.out.println(n1);
        System.out.println(n2);
        System.out.println(n3);
        System.out.println(n4);        //整数大小自己比较吧

    }

【分析】

  1. 设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。写出程序。

【参考答案】

以下程序使用内部类实现线程,对j增减的时候没有考虑顺序问题。

public class ThreadTest1

{

private int j;

public static void main(String args[]){

ThreadTest1 tt=new ThreadTest1();

Inc inc=tt.new Inc();

Dec dec=tt.new Dec();

for(int i=0;i<2;i++){

Thread t=new Thread(inc);

t.start();

t=new 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 i=0;i<100;i++){

inc();

}

}

}

class Dec implements Runnable{

public void run(){

for(int i=0;i<100;i++){

dec();

}

}

}

}

----------随手再写的一个-------------

class A

{

JManger j =new JManager();

main()

{

new A().call();

}

void call

{

for(int i=0;i<2;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++;

}

}

  1. 十六进制的216转换十进制是多少?

216是16进制,转10进制:
=2*16^2+1*16^1+6*16^0
=512+16+6
=536

以下函数htoi函数的功能是将一个十六进制数字的字符串,转换成它等价的十进制整数值。

Public int htoi(char s[])

{

Int i , n ;

N=0;

For(i=0 , s[i]<’\0’;i++)

{

If(s[i]>=0&&s[i]<=9) n=_______

If(s[i]>=’a’&&s[i]<=’f’) n=_________

If(s[i]>=’A’&&s[i]<=’F’) n=_________

}

Return (n);

}

  1. 如何把一段逗号分割的字符串转换成一个数组?

【参考答案】

可以说说我的思路:

  1. 用正则表达式,代码大概为:String [] result = orgStr.split(“,”);
  2. 用StingTokenizer ,代码为:

StringTokenizer  tokener = StringTokenizer(orgStr,”,”);

String [] result = new String[tokener .countTokens()];

Int i=0;

while(tokener.hasNext(){result[i++]=toker.nextToken();}

  1. 编写一个函数将一个十六进制数的字符串参数转换成整数返回。

【参考答案】

String str = “13abf”;

int len = str.length;

int sum = 0;

for(int i=0;i<len;i++){

char c = str.charAt(len-1-i);

int n = Character.digit(c,16);

sum += n * (1<<(4*i));

}

其实,也可以用Integer.parseInt(str,16),但面试官很可能是想考我们的编码基本功。

  1. 读取一个文件在控制台打印出来

【参考答案】

File file = new File("E:\\JRadioButtonDemo.java");

long file_length= file.length();

try {

//输入流

FileInputStream input = new FileInputStream(file);

byte b_data [] = new byte[(int)file_length];

input.read(b_data);

System.out.println(new String(b_data));

input.close();

} catch (FileNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

  1. 递归实现1,1,2,3,5,8,….第30个数是多少?【上海菲耐德】

【参考答案】

public static int Foo(int i)
    {
        if (i <= 0)
            return 0;
        else if(i > 0 && i <= 2)
            return 1;
        else return Foo(i -1) + Foo(i - 2);
    } 
int i=Foo(30);
System.out.println(i);

  1. 求一个字符串中第一个无重复的字符

public static void getUniqueString(String str){

boolean bool = true;

for(int i=0;i<str.length()&&bool;i++){

String s1 = str.substring(i, i+1);

if(str.indexOf(s1, i+1)==-1){

System.out.println(s1);

bool = false;

}

}

}

  1. 写一个递归函数,输入一个整数,反序输出这个整数

// 写一个递归函数,输入一个整数,反序输出这个整数

public static void printOut(int n) {

System.out.print(n % 10);

if (n >= 10){

printOut(n / 10);

}

}

  1. 有一个数据文件:123 34  17  651234  345....这些数据都是随机产生的,编写程序读出该文件.并将其以从大到小的顺序输出到另一个文件中.

public void readtext(){

File file = new File("D:\test.txt");

List list= new ArrayList();

try {

BufferedReader br=new BufferedReader(new FileReader(file));

String data = "";

String line = null;

while ( (line = br.readLine()) != null) {

data = data.concat(line);

}

StringTokenizer stoken = new StringTokenizer(data, " ");

while (stoken.hasMoreTokens()) {

int i = Integer.parseInt(stoken.nextToken());

list.add(i);

}

} catch(Exception ex) {}

String[] str = new String[list.size()];

for(int i=0;i<list.size();i++){

str[i]=list.get(i);

}

Object iTemp= null;

for(int i=1;i<list.size();i++) {

      for(int j=list.size()-1;j>=i;j--) {

          if(str[j]>str[j-1]) {

              iTemp = str[j-1];

              str[j-1] = str[j];

              str[j] = iTemp;

          }

}

String result = "";

for(int i=0;i<str.length;i++){

result +=str[i]+" ";

}

//将result写入另外一个文件即可。

}

  1. 从一到十九共十九个数,打印出利用这十九个整数任意多个相加等于20所以可能性,每个数字在同一个算式中只出现一次.

public void test(){

Integer[] a = new Integer[19];

for(int i=1;i<20;i++){

a[i-1]=i;

}

for(int i=0;i<18;i++){

for(int j=18-i;j<18;j++)

if(a[i]+a[j]==20)

System.out.println(a[i]+"+"+a[i+1]+"="+20);

}

}

  1. 一个字符串中可能存在A-Z的全角字符,写一个方法把里面的全角字符转变成半角字符?

答:采用建立字典表进行查找转换
public  static String translate(String s){
        String qj = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        String bj = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        StringBuffer sb = new StringBuffer();
        for(int i=0;i<s.length();i++){
            char c = s.charAt(i);
            int pos = qj.indexOf(c);
            if(pos>=0){
                System.out.println(c + "," + pos);
                sb.append(bj.charAt(pos));
            }else{
                sb.append(c);
            }
        }
        return sb.toString();
    }

  1. Stack堆栈,实现进栈、出栈。【云巢动脉面试题】

package t1;

public class mystack {

private Object[] data;

private int top=-1;

private int size;

public mystack()

{

data=new Object[5];

size=5;

}

public mystack(int size)

{

data=new Object[size];

this.size=size;

}

public void push(Object obj)

{

if(this.isfull())

{

return ;

}

top++;

data[top]=obj;

}

public Object pop() {

if(this.isempty())

{

return null;

}

Object obj=data[top];

top--;

return obj ;

}

public boolean isfull()

{

if(top==data.length)

{

return true;

}

else

{

return false;

}

}

public boolean isempty()

{

if(top==-1)

{

return true;

}

else

{

return false;

}

}

}

  1. 定义两个变量a和b,不使用第三个变量,使两个值交换

public class testMain {

public void test(int a,int b){

System.out.println("交换前a = "+a);

System.out.println("交换前b = "+b);

a=a+b;

b=a-b;

a=a-b;

System.out.println("交换后a = " +a);

System.out.print("交换后b = "+b);

}

public static void main(String args[]){

new testMain().test(10,13);

}

}

  1. 针对一个分期付款,总期为1年,给定分期金额,期数和开始还款时间,计算出各期还款日期。

package demo;
import java.util.Calendar;
import java.util.Date;
public class TestDemo {   
    // 分期付款,总期为1年,给定分期金额,期数和开始还款时间
    // 计算出各期还款日期
    public void huankuan(double amount,int  num,Date start){
        int period = 365/num; // 一年中分期间隔天数
       
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, start.getYear()+1900);
        cal.set(Calendar.MONTH, start.getMonth());
        cal.set(Calendar.DATE, start.getDate());
       
        for(int i=1;i<=num;i++){           
            System.out.println(" 第" + i + "期还款日期: " + cal.getTime().toLocaleString());
            cal.add(Calendar.DATE, period);
        }           
    }
        public static void main(String[] args) {
        TestDemo demo = new TestDemo();
        demo.huankuan(20000.00, 1, new Date());

    }
}

  1. 用一个方法查出宜个数值类型数组的最大值,用递归方式实现。【高达软件】

方法1

public class Test1 {

public static int a(int[] i,int j){

if(i.length-1>j){

if(i[j]>i[j+1]){

i[j+1]=i[j];

}

return a(i,j+1);

}else{

return i[i.length-1];

}

}

}

方法2  -- 非递归

public  static int  test(int  []num) {

int x=0;

int log   =  num.Length;

for(intt=0;t<log;t++){

if(num[t]>x){

x=num[t];

}

}return  x;

}

方法3 --- 递归 不改变原数组中的元素

public static int getMax(int[]a, int index,int max){

       int len = a.length;

       if(len==1){

           return a[len-1];

       }

       if(index==0){

           max = a[index];

       }

       if(index==len){

           return max;

       }

       if(max<a[index]){

           max = a[index];

       }

       index++;

       return getMax(a,index,max);          

}

// 测试

int max = getMax(new int[]{2,5,18,3,38,10,2},0,0);

System.out.println(max);

  1. 用C编写将一个100以内的自然数分解质因数

/*  100以内素数  */

#include<stdio.h>

main()

{

int i,j;

for(i=2;i<100;i++)

{

for(j=2;j<i;j++)

{

if(i%j==0)

break;

}

if(i==j)

{

printf("%d ",i);

}

}

}

/* 分解质因数*/

main()

{

int   n,i;

printf( "please   input   a   number:\n ");

scanf( "%d ",&n);

printf( "%d= ",n);

for(i=2;i <=n;i++)

while(n!=i)

{

if(n%i==0)

{

printf( "%d* ",i);

n=n/i;

} else{       break; }

}

printf( "%d ",n);

getch();

}

  1. 在main方法中将字符串中的数字排序并输出  STRING A="56.89.5.3.75.98.98.26.15.44"

String s=” 56.89.5.3.75.98.98.26.15.44”;

String s1[]=s. split (“.”);

Integer ii[]=new Integer[s1.length];

For(int i=0;i<s1.length;i++){

ii[i]=Integer.parseInt(s1[i]);

}

Arrays.sort(ii);

for(Integer o: ii){

System.out.println(o+” s”);

}

  1. 用4 个0,用你所知道的数学方法计算出24

0的阶乘等于1  即 0!=1那么4个0就是4了

又4的阶乘为24  4!=24

  1. 判断身份证:要么是15位,要么是18位,最后一位可以为字母,并写程序提出其中的年月日。

答:我们可以用正则表达式来定义复杂的字符串格式,(\d{17}[0-9a-zA-Z]|\d{14}[0-9a-zA-Z])可以用来判断是否为合法的15位或18位身份证号码。

因为15位和18位的身份证号码都是从7位到第12位为身份证为日期类型。这样我们可以设计出更精确的正则模式,使身份证号的日期合法,这样我们的正则模式可以进一步将日期部分的正则修改为[12][0-9]{3}[01][0-9][123][0-9],当然可以更精确的设置日期。

在jdk的java.util.Regex包中有实现正则的类,Pattern和Matcher。以下是实现代码:

import java.util.regex.Matcher;

import java.util.regex.Pattern;

public class RegexTest {

/**

* @param args

*/

public static void main(String[] args) {

// 测试是否为合法的身份证号码

String[] strs = { "130681198712092019", "13068119871209201x",

"13068119871209201", "123456789012345", "12345678901234x",

"1234567890123" };

Pattern p1 = Pattern.compile("(\\d{17}[0-9a-zA-Z]|\\d{14}[0-9a-zA-Z])");

for (int i = 0; i < strs.length; i++) {

Matcher matcher = p1.matcher(strs[i]);

System.out.println(strs[i] + ":" + matcher.matches());

}

Pattern p2 = Pattern.compile("\\d{6}(\\d{8}).*"); // 用于提取出生日字符串

Pattern p3 = Pattern.compile("(\\d{4})(\\d{2})(\\d{2})");// 用于将生日字符串进行分解为年月日

for (int i = 0; i < strs.length; i++) {

Matcher matcher = p2.matcher(strs[i]);

boolean b = matcher.find();

if (b) {

String s = matcher.group(1);

Matcher matcher2 = p3.matcher(s);

if (matcher2.find()) {

System.out

.println("生日为" + matcher2.group(1) + "年"

+ matcher2.group(2) + "月"

+ matcher2.group(3) + "日");

}

}

}

}

}

  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++];

}

}

  1. 编写一个程序,将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();

}

  1. 编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串,但要保证汉字不被截取半个,如“我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 i=0;i<n;i++)

{

if(buf[i]<0 && !bChineseFirstHalf){

bChineseFirstHalf = true;

}else{

num++;

bChineseFirstHalf = false;

}

}

return num;

}

  1. 有一个字符串,其中包含中文字符、英文字符和数字字符,请统计和打印出各个字符的个数。

答:String content = “中国aadf的111萨bbb菲的zz萨菲”;

HashMap map = new HashMap();

for(int i=0;i<content.length;i++)

{

char c = content.charAt(i);

Integer num = map.get(c);

if(num == null)

num = 1;

else

num = 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 i=0;i<str.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(……………);

  1. 从类似如下的文本文件中读取出所有的姓名,并打印出重复的姓名和重复的次数,并按重复次数排序:

1,张三,28

2,李四,35

3,张三,28

4,王五,35

5,张三,28

6,李四,35

7,赵六,28

8,田七,35

package com.huawei.interview;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.util.Comparator;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;

import java.util.TreeSet;

public class GetNameTest {

/**

* @param args

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

//InputStream ips = GetNameTest.class.getResourceAsStream("/com/huawei/interview/info.txt");

//用上一行注释的代码和下一行的代码都可以,因为info.txt与GetNameTest类在同一包下面,所以,可以用下面的相对路径形式

Map results = new HashMap();

InputStream ips = GetNameTest.class.getResourceAsStream("info.txt");

BufferedReader in = new BufferedReader(new InputStreamReader(ips));

String line = null;

try {

while((line=in.readLine())!=null)

{

dealLine(line,results);

}

sortResults(results);

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

static class User

{

public  String name;

public Integer value;

public User(String name,Integer value)

{

this.name = name;

this.value = value;

}

@Override

public boolean equals(Object obj) {

// TODO Auto-generated method stub

//下面的代码没有执行,说明往treeset中增加数据时,不会使用到equals方法。

boolean result = super.equals(obj);

System.out.println(result);

return result;

}

}

private static void sortResults(Map results) {

// TODO Auto-generated method stub

TreeSet sortedResults = new TreeSet(

new Comparator(){

public int compare(Object o1, Object o2) {

// TODO Auto-generated method stub

User user1 = (User)o1;

User user2 = (User)o2;

/*如果compareTo返回结果0,则认为两个对象相等,新的对象不会增加到集合中去

* 所以,不能直接用下面的代码,否则,那些个数相同的其他姓名就打印不出来。

* */

//return user1.value-user2.value;

//return user1.value<user2.value?-1:user1.value==user2.value?0:1;

if(user1.value<user2.value)

{

return -1;

}else if(user1.value>user2.value)

{

return 1;

}else

{

return user1.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(new User(name,value));

}

}

printResults(sortedResults);

}

private static void printResults(TreeSet sortedResults)

{

Iterator iterator  = sortedResults.iterator();

while(iterator.hasNext())

{

User user = (User)iterator.next();

System.out.println(user.name + ":" + user.value);

}

}

public static void dealLine(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);

}

}

}

}

  1. 写一个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 (instance==null)

    instance=new Singleton();

return instance;   

}

}

其他形式:

定义一个类,它的构造函数为private的,所有方法为static的。

一般认为第一种形式要更加安全些

  1. 一个整数,大于0,不用循环和本地变量,按照n,2n,4n,8n的顺序递增,当值大于5000时,把值按照指定顺序输出来。

例:n=1237
则输出为:
1237,
2474,
4948,
9896,
9896,
4948,
2474,
1237,

提示:写程序时,先致谢按递增方式的代码,写好递增的以后,再增加考虑递减部分。

public static void doubleNum(int n)

{

System.out.println(n);

if(n<=5000)

doubleNum(n*2);

System.out.println(n);

}

Gaibaota(N) = Gaibaota(N-1) + n

  1. 第1个人10,第2个比第1个人大2岁,依次递推,请用递归方式计算出第8个人多大?

package cn.demo;

import java.util.Date;

public class A1 {

public static void main(String [] args)

{

System.out.println(computeAge(8));

}

public static int computeAge(int n)

{

if(n==1) return 10;

return computeAge(n-1) + 2;

}

}

public static void toBinary(int n,StringBuffer result)

{

if(n/2 != 0)

toBinary(n/2,result);

result.append(n%2);

}

  1. 排序都有哪几种方法?请列举。用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;
i=left;
j=right;
middle=strDate[(i+j)/2];
do{
    while(strDate[i].compareTo(middle)<0&& i<right)
    i++; //找出左边比中间值大的数
    while(strDate[j].compareTo(middle)>0&& j>left)
    j--; //找出右边比中间值小的数
if(i<=j){ //将左边大的数和右边小的数进行替换
    tempDate=strDate[i];
    strDate[i]=strDate[j];
    strDate[j]=tempDate;
    i++;
    j--;
}
}while(i<=j); //当两者交错时停止

if(i<right){
quickSort(strDate,i,right);//从
}
if(j>left){
quickSort(strDate,left,j);
}
}
/**
  * @param args
  */
public static void main(String[] args){
String[] strVoid=new String[]{"11","66","22","0","55","22","0","32"};
QuickSort sort=new QuickSort();
sort.quickSort(strVoid,0,strVoid.length-1);
for(int i=0;i<strVoid.length;i++){
System.out.println(strVoid[i]+" ");
}
}
}

  1. 有数组a[n],用java代码将数组元素顺序颠倒

//用下面的也可以

//for(int i=0,int j=a.length-1;i<j;i++,j--) 是否等效于 for(int i=0;i<a.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 i=0;i<len/2;i++){

int tmp = a[i];

a[i] = a[len-1-i];

a[len-1-i] = tmp;

}

}

}

  1. 写一个方法,用一个for循环打印九九乘法表      /** *//**
         * 打印九九乘法口诀表
         */
        public void nineNineMulitTable(){
            for (int i = 1,j = 1; j <= 9; i++) {
                  System.out.print(i+"*"+j+"="+i*j+" ");
                  if(i==j){
                      i=0;
                      j++;
                   System.out.println();
                  }
              }
        }
  2. 给定一个java.util.Date对象,如何转化为”2007-3-22 20:23:22”格式的字符串。【高达软件】

/** *//**
     * 将某个日期以固定格式转化成字符串
     * @param date
    * @return str
    */
    public String date2FormatStr(Date date)
    {
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      String str = sdf.format(date);
      return str;
    }

  1. 金额转换,阿拉伯数字的金额转换成中国传统的形式如:(¥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 stub

System.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();

}

}

  1. 写一个方法,能够判断任意一个整数是否素数

/** *//**

* 判断任意一个整数是否素数

* @param num

* @return boolean

*/

public boolean isPrimeNumber(int num)

{

for (int i = 2; i <= Math.sqrt(num); i++) {

if(num%i==0)

{

return false;

}

}

return true;

}

  1. 用1、2、3、4、5这5个数字,用Java写一个Main函数,打印所有不同的排序 

static int[] bits = new int[] { 1, 2, 3, 4, 5 };

/**

* @param args

*/

public static void main(String[] args) {

sort("", bits);

}

private static void sort(String prefix, int[] a) {

if (a.length == 1) {

System.out.println(prefix + a[0]);

}

for (int i = 0; i < a.length; i++) {

sort(prefix + a[i], copy(a, i));

}

}

private static int[] copy(int[] a,int index){

int[] b = new int[a.length-1];

System.arraycopy(a, 0, b, 0, index);

System.arraycopy(a, index+1, b, index, a.length-index-1);

return b;

}

  1. 写一个方法,输入任意一个整数,返回它的阶乘     /** *//**      *获得任意一个整数的阶乘
          n
          !
          */
          public int factorial(int num)
          {
            //递归
            if(num == 1)
            {
                return 1;
            }
            return num*factorial(num-1);
          }
  2. 写一个方法,用二分查找法判断任意整数在任意整数数组里面是否存在,若存在就返回它在数组中的索引位置,不存在返回-1

/** *//**
       *二分查找特定整数在整型数组中的位置(递归)
       dataset
       data
       beginIndex
       endIndex
       index
       */
       public int binarySearch(int[] dataset,int data,int beginIndex,int endIndex){
         int midIndex = (beginIndex+endIndex)/2;
         //如果查找的数要比开始索引的数据要小或者是比结束索引的书要大,或者开始查找的索引值大于结束的索引值返回-1没有查到
         if(data <dataset[beginIndex]||data>dataset[endIndex]||beginIndex>endIndex){
             return -1;
         }
         if(data <dataset[midIndex]){
             return binarySearch(dataset,data,beginIndex,midIndex-1);
         }else if(data>dataset[midIndex])
         {
             return binarySearch(dataset,data,midIndex+1,endIndex);
         }else {
             return midIndex;
         }
       }
     
       /** *//**
        *二分查找特定整数在整型数组中的位置(非递归)
        dataset
        data
        index
        */
        public int binarySearch(int[] dataset ,int data)
        {
          int beginIndex = 0;
          int endIndex = dataset.length - 1;
          int midIndex = -1;
          if(data <dataset[beginIndex]||data>dataset[endIndex]||beginIndex>endIndex){
              return -1;
          }
          while(beginIndex <= endIndex) {
              midIndex = (beginIndex+endIndex)/2;
              if(data <dataset[midIndex]) {
                 endIndex = midIndex-1;
              } else if(data>dataset[midIndex]) {
                beginIndex = midIndex+1;
              }else {
                return midIndex;
              }
          }
          return -1;
        }

  1. 如果一个序列的前四个数字分别是2,9,28,65请问第五个数字是?

1³+1=2

2³+1=9

3²+1=28

4³+1=65

所以继续的话应是

5³+1=126

  1. 编写函数找出1到1000之内能被3整除且不是偶数的整数,并按个位数的大小从大到小排序

public List find() {

List list=new ArrayList();

for (int i = 1; i <=1000; i++) {

if (i%3==0 && i%2!=0) {

list.add(i);

}

}

return list;

}

  1. 用java方法编写计算指定目录下所有文件占空间大小

//返回文件大小private void getFileSize()throws RuntimeException,IOException

{//初始化文件大小为0;

this.longSize=0;

//如果文件存在而且是文件,直接返回文件大小

if(file.exists()&&file.isFile()){

this.longSize= file.length();

}

//文件存在而且是目录,递归遍历文件目录计算文件大小  else if(file.exists()&&file.isDirectory()){

getFileSize(file);//递归遍历

}else{

throw new RuntimeException("指定文件不存在");

}

}

  1. 一个list中,有b.a.b.c.b.b.写个方法去掉所有b

public List qub(List list) {

List alist=new ArrayList();

for (int i = 0; i < list.size(); i++) {

String a=(String)list.get(i);

if (!a.equals("b")) {

alist.add(a);

}

}

return alist;

}

  1. 设计线程的生产者和消费者模式

package com;

import java.io.*;

import java.util.*;

public class Test1 {

Vector v = new Vector();

int index = -1;

boolean isput = false;

public synchronized void put(String name) throws InterruptedException{

if(isput){

wait();

}

v.add(name);

index++;

isput = true;

notify();

System.out.println(Thread.currentThread().getName());

}

public synchronized  void get() throws InterruptedException{

if(!isput){

wait();

}

System.out.println(Thread.currentThread().getName()+"取:"+v.get(index));

isput = false;

notify();

}

public static void main(String[] args) throws CloneNotSupportedException, FileNotFoundException, IOException, InterruptedException {

Test1 t = new Test1();

A a = new A(t);

B b = new B(t);

new Thread(a).start();

new Thread(b).start();

}

}

class A implements Runnable{

Test1 t;

public A(Test1 t){

this.t = t;

}

@Override

public void run() {

int i  =0 ;

while(true){

if(i==0){

try {

t.put("男");

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}else{

try {

t.put("女");

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

i = (i+1)%2;

}

}

}

class B implements Runnable{

Test1 t;

public B(Test1 t){

this.t = t;

}

@Override

public void run() {

// TODO Auto-generated method stub

while(true){

try {

t.get();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

  1. 写一个方法求两个数的公约数

import java.util.ArrayList;

import java.util.List;

public class MaxNum {

int num=0;

public List Maxs(int a){//先找出能被第一个数整除的数

List list=new ArrayList();

for (int i = 1; i <= a; i++) {

if(a%i==0){

list.add(i);

}

}

return list;

}

public void Test(int a,int b){

List list=new MaxNum().Maxs(a);

for (int i = 0; i < list.size(); i++) {

int bb=(Integer) list.get(i);

if(b%bb==0){//找出能被第二个数整出并且也能被第二个数整除的数

num=bb;

}

}

System.out.println("最大公约数为:"+num);

}

public static void main(String[] args) {

new MaxNum().Test(100,1000);

}

}

  1. 实现字符串的反转。如:abcd 输出dcba

答:

StringBuffer stringBuffer =

new StringBuffer().append("abc").reverse();

System.out.println(stringBuffer.toString());

  1. 编写程序将由数字及字符组成的字符串中的数字截取出来并按顺序输出,例如:“ABC137GMNQQ2049PN5FFF”输出结果应该为01234579

package com.tarena;

import java.util.Arrays;

public class NumberSplitChar {

public static void main(String[] args) {

String str=”ABC137GMNQQ2049PN5FFF”;

char[] beforechars=str.toCharArray();

char[] afterchars=new char[beforechars.length];

int j=0;

for(int i=0;i<beforechars.length;i++){

if(beforechars[i]>=’0′ && beforechars[i]<=’9′){

afterchars[j++]=beforechars[i];

}

}

Arrays.sort(afterchars);

for(int i=(afterchars.length-j);i<afterchars.length;i++){

System.out.print(afterchars[i]);

}

}

}

二、JQuery,JS面试题

  1. JavaScript有哪几种数据类型

简单:Number,Boolean,String,Null,Undefined

复合:Object,Array,Function

  1. 在js编码中innerHTML,outhtml,innertext区别
    • innerHTML 设置或获取位于对象起始和结束标签内的 HTML
    • outerHTML 设置或获取对象及其内容的 HTML 形式
    • innerText 设置或获取位于对象起始和结束标签内的文本
    • outerText 设置(包括标签)或获取(不包括标签)对象的文本
  1. 什么是json ,jquery?

JSON: (javaScript Object Notation)是一种轻量级的数据交换格式。

JSON两种结构:

名称/值对的集合,不同的语言中,它被理解为对象,记录,结构,字典,哈希表,有   键列表,关联数组。

值的有序列表,数组

jQuery:

jQuery由美国人John Resig创建  是一个优秀的javascript框架  使用户能够方便的处理HTML documents   events  实现动画效果,并且方便地为网站提供AJAX交互。

  1. jQuery中有id为foo的对象有att属性,如何获取att属性的值?

$(‘foo’).att(‘attr’).val()

  1. jQuery中添加文本怎么写在div

【参考】

可以通过jQuery提供的元素选择器或ID选择器为实现,如:

$(‘div’).append(‘Hello ’);要求只能有一个div否则$(‘div’)返回的是数组

$(‘#ID名称’).append(“hello”);

  1. 你在公司是怎么用jquery的?        

【参考】

在项目中是怎么用的是看看你有没有项目经验(根据自己的实际情况来回答)你用过的选择器啊,复选框啊,表单啊,ajax啊,事件等。配置Jquery环境 下载jquery类库 在jsp页面引用jquery类库即可

<script type="text/javascript" src="jquery/jquery-1.7.2.min.js"/>

接下来通过在<script>

$(function(){

);

</script>

  1. 你为什么要使用jquery        

【参考】

答:因为jQuery是轻量级的框架,大小不到30kb,它有强大的选择器,出色的DOM操作的封装,有可靠的事件处理机制(jQuery在处理事件绑定的时候相当的可靠),完善的ajax(它的ajax封装的非常的好,不需要考虑复杂浏览器的兼容性和XMLHttpRequest对象的创建和使用的问题。) 出色的浏览器的兼容性。 而且支持链式操作,隐式迭代。行为层和结构层的分离,还支持丰富的插件,jquery的文档也非常的丰富。

  1. 你使用jquery遇到过哪些问题,你是怎么解决的?           

【参考】

答:这个答案是开发的,看你是否有相关的项目经验。例 前台拿不到值,JSON 可是出现的错误(多了一个空格等)这编译是不会报错的       jquery库与其他库冲突:

1>如果其他库在jquery库之前导入的话

  • 我们可以通过jquery.noconflict()将变量的$的控制权过度给其他库
  • 自定义快捷键,用一个变量接住jquery.noconflict()
  • 通过函数传参

2>如果jquery库在其他库之前导入就直接使用jquery    今天在处理一个数据问题时,发现jQuery.ajax()方法返回的值一直有问题,清除缓存后数据无误,多次测试后发现返回的值都是之前的值,并且一直未执行url(后台为JAVA,设置断点一直未进入)。在网上查找下,发现是未设置type的原因。如果没设置jQuery.ajax的type="Post",那么ajax就会默认type="Get",这就会导致之前数据被缓存起来。加上type="Post",问题解决!

  1. 你知道jquery中的选择器吗,请讲一下有哪些选择器?           

【参考】

jQuery中的选择器大致分为:基本选择器,层次选择器,过滤选择器,表单选择器

  1. jquery中的选择器 和 css中的选择器有区别吗?

【参考】

jQuery选择器支持CSS里的选择器,jQuery选择器可用来添加样式和添加相应的行为CSS 中的选择器是只能添加相应的样式

  1. 你觉得jquery中的选择器有什么优势?       

【参考】

简单的写法  $('ID') 来代替 document.getElementById()函数支持CSS1 到CSS3 选择器完善的处理机制(就算写错了id也不会报错)

  1. 你在使用选择器的时候有有没有什么觉得要注意的地方? 

【参考】

  1. 选择器中含有".","#","[" 等特殊字符的时候需要进行转译
  2. 属性选择器的引号问题
  3. 选择器中含有空格的注意事项
  1. jquery对象和dom对象是怎样转换的?       

【参考】

答 :jquery转DOM对象:jQuery 对象是一个数组对象,可以通过[index]的丰富得到相应的DOM对象还可以通过get[index]去得到相应的DOM对象。DOM对象转jQuery对象:$(DOM对象)

  1. 你是如何使用jquery中的ajax的?      

【参考】

如果是一些常规的ajax程序的话,使用load(),$.get(),$.post(),就可以搞定了,         一般我会使用的是$.post() 方法。如果需要设定beforeSend(提交前回调函数),error(失败后处理),success(成功后处理)及complete(请求完成后处理)回调函数等,这个时候我会使用$.ajax()

  1. 你觉得jquery中的ajax好用吗,为什么?          

【参考】

答: 好用的。因为jQuery提供了一些日常开发中夙瑶的快捷操作,例 load,ajax,get,post等等,所以使用jQuery开发ajax将变得极其简单,我们就可以集中精力在业务和用户的体验上,不需要去理会那些繁琐的XMLHttpRequest对象了。

  1. jquery中$.get()提交和$.post()提交有区别吗?            
  1. $.get() 方法使用GET方法来进行异步请求的。 $.post() 方法使用POST方法来进行异步请求的。
  2. get请求会将参数跟在URL后进行传递,而POST请求则是作为HTTP消息的实体内容发送给Web服务器的,这种传递是对用户不可见的。
  3. get方式传输的数据大小不能超过2KB 而POST要大的多
  4. GET 方式请求的数据会被浏览器缓存起来,因此有安全问题。
  1. jquery中的load方法一般怎么用的?    

【参考】

答:load方法一般在 载入远程HTML 代码并插入到DOM中的时候用通常用来从Web服务器上获取静态的数据文件。

如果要传递参数的话,可以使用$.get() 或 $.post()

  1. 在jquery中你是如何去操作样式的?           

【参考】

addClass() 来追加样式

removeClass() 来删除样式

toggle() 来切换样式

  1. 简单的讲叙一下jquery是怎么处理事件的,你用过哪些事件?       

【参考】

答: 首先去装载文档,在页面家在完毕后,浏览器会通过javascript 为DOM元素添加事件。

  1. 你使用过jquery中的动画吗,是怎样用的?       

【参考】

答:使用过。hide() 和 show() 同时修改多个样式属性。像高度,宽度,不透明度。 fadeIn() 和fadeOut() fadeTo() 只改变不透明度slideUp() 和 slideDown() slideToggle() 只改变高度animate() 属于自定义动画的方法。

  1. 你一般用什么去提交数据,为什么?            

【参考】

答:一般我会使用的是$.post() 方法。 如果需要设定beforeSend(提交前回调函数),error(失败后处理),success(成功后处理)及complete(请求完成后处理)回调函数等,这个时候我会使用$.ajax()

  1. 在jquery中引入css有几种方式?         

【参考】

答:四种 行内式,内嵌式,导入式,链接式

  1. 你在jquery中使用过哪些插入节点的方法,它们的区别是什么?    

【参考】

答:append(),appendTo(),prepend(),prependTo(),after(),insertAfter()             before(),insertBefore() 大致可以分为 内部追加和外部追加

append() 表式向每个元素内部追加内容。

appendTo() 表示 讲所有的元素追加到指定的元素中。例$(A)appendTo(B) 是将A追加到B中 下面的方法解释类似

  1. jquery中如何来获取或和设置属性?            

【参考】

jQuery中可以用attr()方法来获取和设置元素属性

removeAttr() 方法来删除元素属性

  1. 如何来设置和获取HTML和文本的值?

【参考】

html()方法 类似于innerHTML属性 可以用来读取或者设置某个元素中的HTML内容   注意:html() 可以用于xhtml文档 不能用于xml文档

text() 类似于innerText属性 可以用来读取或设置某个元素中文本内容。

val() 可以用来设置和获取元素的值

  1. 子元素选择器和后代选择器元素有什么区别?          

【参考】

答:子代元素是找子节点下的所有元素,后代元素是找子节点或子节点的子节点中的元素

  1. 你在ajax中使用过JSON吗,你是如何用的?           

【参考】

答:使用过,在$.getJSON() 方法的时候就是。因为 $.getJSON() 就是用于加载JSON文件的

  1. jQuery中有几种方法可以来设置和获取 样式      

答 :addClass() 方法,attr() 方法

  1. $(document).ready()方法和window.onload有什么区别?        

【参考】

答: 两个方法有相似的功能,但是在实行时机方面是有区别的。

  1. window.onload方法是在网页中所有的元素(包括元素的所有关联文件)完全加载到浏览器后才执行的。
  2. $(document).ready() 方法可以在DOM载入就绪时就对其进行操纵,并调用执行绑定的函数。
  1. jQuery是如何处理缓存的?         

【参考】

答 :要处理缓存就是禁用缓存.

  1. 通过$.post() 方法来获取数据,那么默认就是禁用缓存的。
  2. 通过$.get()方法 来获取数据,可以通过设置时间戳来避免缓存。可以在URL后面加上+(+new Date)例 $.get('ajax.xml?'+(+new Date),function () {  //内容                          });
  3. 通过$.ajax 方法来获取数据,只要设置cache:false即可。
  1. $("#msg").text();和 $("#msg").text("<b>new content</b>");有什么区别?   

【参考】

1 $("#msg").text() 是 返回id为msg的元素节点的文本内容

2 $("#msg").text("<b>new content</b>"); 是 将“<b>new content</b>” 作为普通文本串写入id为msg的元素节点内容中,                      页面显示粗体的<b>new content</b>

  1. radio单选组的第二个元素为当前选中值,该怎么去取?   

【参考】

答 : $('input[name=items]').get(1).checked = true;

  1. 选择器中 id,class有什么区别?          

【参考】

答:在网页中 每个id名称只能用一次,class可以允许重复使用

  1. 你使用过哪些数据格式,它们各有什么特点?            

【参考】

答: HTML格式,JSON格式,javascript格式,XML格式

  1. HTML片段提供外部数据一般来说是最简单的。
  2. 如果数据需要重用,而且其他应用程序也可能一次受到影响,那么在性能和文件大小方面具有优势的JSON通常是不错的选择。
  3. 而当远程应用程序未知时,XML则能够为良好的互操作性提供最可靠的保证。
  1. jQuery能做什么?   

【参考】

  1. 获取页面的元素
  2. 修改页面的外观
  3. 改变页面大的内容
  4. 响应用户的页面操作
  5. 为页面添加动态效果
  6. 无需刷新页面,即可以从服务器获取信息
  7. 简化常见的javascript任务
  1. 在ajax中data主要有几种方式?   

【参考】

三种,html拼接的,json数组,form表单经serialize()序列化的。

  1. jQuery中的hover()和toggle()有什么区别?        

【参考】

hover()和toggle()都是jQuery中两个合成事件。hover()方法用于模拟光标悬停事件。toggle()方法是连续点击事件。

  1. css+div的优势

Div+CSS标准的优点:
1.大大缩减页面代码,提高页面浏览速度,缩减带宽成本;
2.结构清晰,容易被搜索引擎搜索到,天生优化了seo
3.缩短改版时间。只要简单的修改几个CSS文件就可以重新设计一个有成百上千页面的站点。
4.强大的字体控制和排版能力。CSS控制字体的能力比糟糕的FONT标签好多了,有了CSS,我们不再需要用FONT标签或者透明的1 px GIF图片来控制标题,改变字体颜色,字体样式等等。
5.CSS非常容易编写。你可以象写html代码一样轻松地编写CSS。
6.提高易用性。使用CSS可以结构化HTML

  1. 可以一次设计,随处发布。

更好的控制页面布局

  1. DIV和Span的区别?

DIV(division)是一个块级元素,可以包含段落、标题、表格,乃至诸如章节、摘要和备注等。而SPAN 是行内元素,SPAN 的前后是不会换行的,它没有结构的意义,纯粹是应用样式,当其他行内元素都不合适时,可以使用SPAN
在 HTML 视图中工作时,可以在 <DIV> 内编辑文本,将某些字包含在 <SPAN> 元素内,以强调那些字。与 <DIV> 不同,<SPAN> 和它周围的文本一起移动

  1. css是什么

层叠样式表,用来进行页面样式设计,美化页面显示。

  1. ajax的工作原理?
     Ajax 基本上就是把 JavaScript 技术和 XMLHttpRequest 对象放在 Web 表单和服务器之间。当用户填写表单时,数据发送给一些 JavaScript 代码而不是 直接发送给服务器。相反,JavaScript 代码捕获表单数据并向服务器发送请求。同时用户屏幕上的表单也不会闪烁、消失或延迟。换句话说,JavaScript 代码在幕后发送请求,用户甚至不知道请求的发出。更好的是,请求是异步发送的,就是说 JavaScript 代码(和用户)不用等待服务器的响应。因此用户可以继续输入数据、滚动屏幕和使用应用程序。 

 然后,服务器将数据返回 JavaScript 代码(仍然在 Web 表单中),后者决定如何处理这些数据。它可以迅速更新表单数据,让人感觉应用程序是立即完成的,表单没有提交或刷新而用户得到了新数据。JavaScript 代码甚至可以对收到的数据执行某种计算,再发送另一个请求,完全不需要用户干预!这就是 XMLHttpRequest 的强大之处。它可以根据需要自行与服务器进行交互,用户甚至可以完全不知道幕后发生的一切。结果就是类似于桌面应用程序的动态、快速响应、高交互性的体验。

  1. 在javascript中设置定时调用myfun()函数(周期为1秒)的代码是?

setInterval(myfun(),1000)

  1. HTTP请求返回的状态码有哪些?分别有什么含义?

3XX:重定向,这类状态码代表需要客户端采取进一步的操作才能完成请求。通常,这些状态码用来重定向,后续的请求地址(重定向目标)在本次响应的 Location 域中指明。

302:请求的资源现在临时从不同的 URI 响应请求

303:对应当前请求的响应可以在另一个 URI 上被找到,而且客户端应当采用 GET 的方式访问那个资源。

4XX:请求错误,这类的状态码代表了客户端看起来可能发生了错误,妨碍了服务器的处理。

像,403、404、405错误

5XX:服务器错误,这类状态码代表了服务器在处理请求的过程中有错误或者异常状态发生,也有可能是服务器意识到以当前的软硬件资源无法完成对请求的处理。

像,500、501、502等错误

  1. JSON和XML的优缺点

【参考答案】

  1. 在可读性方面,JSON和XML的数据可读性基本相同。JSON和XML的可读性可谓不相上下,一边是建议的语法,一边是规范的标签形式,很难分出胜负。
  2. 在可扩展性方面,XML天生有很好的扩展性,JSON当然也有,没有什么是XML能扩展,JSON不能的。
  3. 在编码难度方面,XML有丰富的编码工具,比如Dom4j、JDom等,JSON也有json.org提供的工具,但是JSON的编码明显比XML容易许多,即使不借助工具也能写出JSON的代码,可是要写好XML就不太容易了。
  4. 在解码难度方面,XML的解析得考虑子节点父节点,让人头昏眼花,而JSON的解析难度几乎为0。这一点XML输的真是没话说。
  5. 在流行度方面,XML已经被业界广泛的使用,而JSON才刚刚开始,但是在Ajax这个特定的领域,未来的发展一定是XML让位于JSON。到时Ajax应该变成Ajaj(Asynchronous Javascript and JSON)了。
  6. JSON和XML同样拥有丰富的解析手段。
  7. JSON相对于XML来讲,数据的体积小。
  8. JSON与JavaScript的交互更加方便。
  9. JSON对数据的描述性比XML较差。
  10. JSON的速度要远远快于XML。

三、Web面试题

Java web部分

  1. JSP有哪些内置对象?作用分别是什么?

答:JSP有9个内置对象:

- request:封装客户端的请求,其中包含来自GET或POST请求的参数;

- response:封装服务器对客户端的响应;

- pageContext:通过该对象可以获取其他对象;

- session:封装用户会话的对象;

- application:封装服务器运行环境的对象;

- out:输出服务器响应的输出流对象;

- config:Web应用的配置对象;

- page:JSP页面本身(相当于Java程序中的this);

- exception:封装页面抛出异常的对象。

  1. 通过部署描述文件(web.xml)可以配置哪些功能?

【参考答案】

  1. 配置项目的欢迎页面。
  2. 配置Servlet访问URL
  3. 配置Web 容器、Servlet的初始化参数
  4. 配置错误页面,可以通过异常编号进行错误页面跳转。
  5. Servlet加载优先级。
  6. Web容器监听器。
  7. Web请求过滤器。
  8. 设置会话的过期时间。
  1. JSP与SERVLET区别

【参考答案】

JSP在本质上就是SERVLET,但是两者的创建方式不一样.Servlet完全是JAVA程序代码构成,擅长于流程控制;而.JSP由HTML代码和JSP标签构成,可以方便地编写动态网页.因此在实际应用中采用Servlet来控制业务流程,而采用JSP来生成动态网页,同时在MVC设计模式中JSP充当视图层,而Servlet位于控制层。另外JSP也是Servlet技术的扩展,本质上就是Servlet,就是JSP的另一种简易体现形式,因为JSP编译后就是一个“类servlet”,再经由JVM编译生成Java类文件来执行。

  1. Tomcat的class加载的优先顺序一览

【参考答案】

加载顺序图示如下:

震撼,java面试题整合(良心制作)11万多字拿去。持续更新【可以收藏】

第一步:加载JVM类库。一般是加载由虚拟机提供的基本的运行时类和系统扩展目录($JAVA_HOME/jre/lib/ext)下的JAR包。

第二步:加载系统环境变量的类库。这个加载器用来加载CLASSPATH环境变量中指定的类。

第三步:加载Tomcat下面common文件夹下面的公共类库。

第四步:加载自己需要的catalina类库。

第五步:webapps下面自己应用的类库,包括webapp1、webapp1......等。

  1. Servlet中的init()方法什么时候被调用?

【参考答案】

当客户端第一次请求该Servlet时,由容器调用该Servlet类的init()方法对该Servlet进行初始化,该初始始化方法只被调用一次。

  1. 用什么方法使服务器关闭之后,session所保存的信息不会丢失?

【参考答案】

使用cookie实现,服务器端将需要保存的信息,通过Cookie并写入客户端磁盘中,下次访问时,客户端浏览器携带写入的信息提交至服务器,这样可以使信息不会因服务器关闭而丢失。

【分析】

主要考查Cookie的相关知识,比如还有一道题问:如果登录某个网站后,想在本周内都不用重新登录,也是通过Cookie实现的

  1. Forward与Redirect 的区别?有哪些方式实现

【参考答案】

forward是服务器资源转发,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器,客户机并不知道发送的内容是从哪儿来的,所以地址栏中还是原来的地址;redirect则是服务器收到请求后发送一个状态头给客户,客户将再请求一次,这里多了两次网络通信的来往。forward 会将请求状态和信息发至下一个jsp或Servlet。redirect 是送到 client 端后再一次请求,信息不被保留,就是我们说的无法获取request中的参数。

实现方式:

HttpServletResponse接口sendRedirect()方法进行重定向转发

RequestDispatcher.接口forward()方法进行请求转发

  1. Servlet的生命周期分为3个阶段? 

【参考答案】

Servlet的生命周期主要由3个过程组成。

(1)init()方法:服务器初始化servlet。

(2)service()方法:初始化完毕,servlet对象调用该方法响应客户的请求。

(3)destroy()方法:调用该方法消灭servlet对象。

其中,init()方法只在servlet第一次被请求加载的时候被调用一次,当有客户再请求servlet服务时,web服务器将启动一个新的线程,在该线程中,调用service方法响应客户的请求。

  1. 描述Cookie和Session的作用?区别和各自的应用范围?Session工作原理。【北京科瑞明】

【参考答案】

Cookie和Session都是用来服务器端和客户端进行会话跟踪的一种技术。

区别:Cookie只能传输字符数据,字符是通过加密后写到客户端,下次请求时协带至服务器端,Cookie协带的数据大小为4KB,对数据量超出4KB的数据,无法处理,Cookie数据一般是通过加密后存储在客户端,而Session在服务器端和浏览器缓存中都保存在ID的值,通过此ID来识别唯一的客户端。Session对数据存储的大小没有限制,但存储的信息加重服务器的负载,另外Session在分布式服务器的使用上也有限制,Session无法跨域,也就是多台服务器无法共享会话。

Session原理:当客户端用户访问时,服务器都为每个用户分配一个唯一的会话ID(Session ID) 保存在服务器内存中,服务器响应客户端时,将Session ID写入浏览器缓存中,当下次客户端请求时,就会将该Session ID携带至服务器,服务器再根据ID比对,识别不同客户端请求,以此方式来不断维持服务器和客户端状态跟踪。

  1. HTTP请求的GET与POST方式的区别

【参考答案】

GET 和 POST.是HTTP定义的与服务器交互的不同方法,是使用HTTP的标准协议动词,用于编码和传送变量名/变量值对参数,并且使用相关的请求语义。

1、Get方式在通过URL提交数据,数据在URL中可以看到;POST方式,数据放置在HTML HEADER内提交,无法在地址栏看到。

2、GET方式提交的数据最多只能有1024字节,而POST则没有此限制。

3、GET一般用作小数据量的请求,POST一般用作大数据量的请求,如:附件。

  1. 什么情况下调用doGet()和doPost()?

【参考答案】

根据客户端的请求的方式来决定调用哪个方法处理请求,如果客户端采用GET方式

发送请求,服务器端则采用doGET()来处理,如果采用post方式,服务器端则采用doPOST()

  1. request.getAttribute()和 request.getParameter() 有何区别?

【参考答案】

request.getAttribute()获取在请求对象中设置的属性,该方法返回对象为Object类型,而getParameter()方法是获取指定的请求参数值,返回值为String类型的字符串。

  1. JSP的常用指令

【参考答案】

共三种,分别是:

  1. <%@include >用来在JSP页面包含静态资源
  2. <%@taglib >用来指定JSP页面标签类型
  3. <%@page >用来指定页面相关属性
  1. 页面间对象传递的方法

【参考答案】

request、session、application、Cookie等,其中比较常用的像request、Session。request主要是应用在同一请求周期内,可能进行对象或参数的共享传递。而Session主要可以应用于同一客户端会话周期内进行参数属性的共享。

  1. web运用程序的稳定、安全需要考虑哪些?

【参考答案】

Web服务器的性能考虑主要有:并发用户数、事务安全、负载均衡、时段流量、网络带宽

网格安全等。

网络安全方面:

  • 关键数据的保护,例如用户数据等
  • 功能服务的正常提供。
  • 网站的防攻击能力。
  • 对异常灾害的恢复能力。

程序性能:

  • 响应请求并运行得出结果的时间。
  • 错误的检测和拦截。
  • 扩展性。
  1. 将ISO8859-1字符串转成GB2312编码,语句为?

【参考答案】

String s=new String(text.getBytes(“iso8859-1”),”gb2312”)

  1. 哪些方法可以提高JDBC性能?

【参考答案】

1. 使用数据连接池(Connection Pool), 避免使用DriverManager.getConnection()。

  1. 合理的配置数据连接池参数,合理如何设置数据连接池的初始大小
  2. 选择合适的事务等级,按照不同的数据库操作类型选择不同的事务等级。
  3. 及时关闭Connection,不关闭的话会严重影响系统的性能,甚至造成系统罢工
    5. 优化Statement
           1) 选择合适的Statement, 根据不同的数据库操作选择Statement, PreparedStatement 或者 CallableStatement

2) 尽可能的使用batch, 这样可以减少调用JDBC的次数。

3) Statement执行完毕后关闭Statement
6. 优化你的SQL, 尽量减少你的结果集,不要每次都"select * from XXX"

7. 使用一些缓存工具进行缓存,特别是大数据查询。

  1. Web容器里面的对象存活周期? 

【参考答案】

当然由web容器进行创建管理的对象主要有application,session,request,page这四个级别的对象,而这4种级别的对象,根据它们自身的特点来管理所持的对象,如:request中的对象的生命周期就是在请求范围内,Session在是会话周期内,page是在当前JSP Page内,Application是在服务器启、停的周期内。

【分析】

总的来说这道题有点没明白,提问者想问的是东西是什么。看到题第一反应以为是问Servlet的生存周期,因为说到Web容器对象,一般指的是Servlet,Servlet组件是由容器进行创建、调用和管理的,所以首先想到了Servlet的存活周期。

  1. 浏览器页面与Tomcat的交互过程?

【参考答案】

当一个JSP页面第一次被访问的时候,JSP引擎将执行以下步骤:

(1)将JSP页面翻译成一个Servlet,这个Servlet是一个java文件,同时也是一个完整的java程序

(2)再由java编译器对这个Servlet进行编译,得到可执行class文件

(3)再由JVM解释器来解释执行class文件,生成向客户端发送的应答,然后发送给客户端

以上三个步骤仅仅在JSP页面第一次被访问时才会执行,以后的访问速度会因为class文件已经生成而大大提高。

  1. 常用的Web服务器有哪些?

答:Unix和Linux平台下使用最广泛的免费HTTP服务器是Apache服务器,而Windows平台的服务器通常使用IIS作为Web服务器。选择Web服务器应考虑的因素有:性能、安全性、日志和统计、虚拟主机、代理服务器、缓冲服务和集成应用程序等。下面是对常见服务器的简介:

- IIS:Microsoft的Web服务器产品,全称是Internet Information Services。IIS是允许在公共Intranet或Internet上发布信息的Web服务器。IIS是目前最流行的Web服务器产品之一,很多著名的网站都是建立在IIS的平台上。IIS提供了一个图形界面的管理工具,称为Internet服务管理器,可用于监视配置和控制Internet服务。IIS是一种Web服务组件,其中包括Web服务器、FTP服务器、NNTP服务器和SMTP服务器,分别用于网页浏览、文件传输、新闻服务和邮件发送等方面,它使得在网络(包括互联网和局域网)上发布信息成了一件很容易的事。它提供ISAPI(Intranet Server API)作为扩展Web服务器功能的编程接口;同时,它还提供一个Internet数据库连接器,可以实现对数据库的查询和更新。

- Kangle:Kangle Web服务器是一款跨平台、功能强大、安全稳定、易操作的高性能Web服务器和反向代理服务器软件。此外,Kangle也是一款专为做虚拟主机研发的Web服务器。实现虚拟主机独立进程、独立身份运行。用户之间安全隔离,一个用户出问题不影响其他用户。支持PHP、ASP、ASP.NET、Java、Ruby等多种动态开发语言。

- WebSphere:WebSphere Application Server是功能完善、开放的Web应用程序服务器,是IBM电子商务计划的核心部分,它是基于Java的应用环境,用于建立、部署和管理Internet和Intranet Web应用程序,适应各种Web应用程序服务器的需要。

- WebLogic:WebLogic Server是一款多功能、基于标准的Web应用服务器,为企业构建企业应用提供了坚实的基础。针对各种应用开发、关键性任务的部署,各种系统和数据库的集成、跨Internet协作等Weblogic都提供了相应的支持。由于它具有全面的功能、对开放标准的遵从性、多层架构、支持基于组件的开发等优势,很多公司的企业级应用都选择它来作为开发和部署的环境。WebLogic Server在使应用服务器成为企业应用架构的基础方面一直处于领先地位,为构建集成化的企业级应用提供了稳固的基础。

- Apache:目前Apache仍然是世界上用得最多的Web服务器,其市场占有率很长时间都保持在60%以上(目前的市场份额约40%左右)。世界上很多著名的网站都是Apache的产物,它的成功之处主要在于它的源代码开放、有一支强大的开发团队、支持跨平台的应用(可以运行在几乎所有的Unix、Windows、Linux系统平台上)以及它的可移植性等方面。

- Tomcat:Tomcat是一个开放源代码、运行Servlet和JSP的容器。Tomcat实现了Servlet和JSP规范。此外,Tomcat还实现了Apache-Jakarta规范而且比绝大多数商业应用软件服务器要好,因此目前也有不少的Web服务器都选择了Tomcat。

- Nginx:读作"engine x",是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP代理服务器。 Nginx是由Igor Sysoev为俄罗斯访问量第二的Rambler站点开发的,第一个公开版本0.1.0发布于2004年10月4日。其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。在2014年下半年,Nginx的市场份额达到了14%。

  1. 过滤器有哪些作用和用法?

答: Java Web开发中的过滤器(filter)是从Servlet 2.3规范开始增加的功能,并在Servlet 2.4规范中得到增强。对Web应用来说,过滤器是一个驻留在服务器端的Web组件,它可以截取客户端和服务器之间的请求与响应信息,并对这些信息进行过滤。当Web容器接受到一个对资源的请求时,它将判断是否有过滤器与这个资源相关联。如果有,那么容器将把请求交给过滤器进行处理。在过滤器中,你可以改变请求的内容,或者重新设置请求的报头信息,然后再将请求发送给目标资源。当目标资源对请求作出响应时候,容器同样会将响应先转发给过滤器,在过滤器中你可以对响应的内容进行转换,然后再将响应发送到客户端。

常见的过滤器用途主要包括:对用户请求进行统一认证、对用户的访问请求进行记录和审核、对用户发送的数据进行过滤或替换、转换图象格式、对响应内容进行压缩以减少传输量、对请求或响应进行加解密处理、触发资源访问事件、对XML的输出应用XSLT等。

和过滤器相关的接口主要有:Filter、FilterConfig和FilterChain。

  1. 监听器有哪些作用和用法? 
    答:Java Web开发中的监听器(listener)就是application、session、request三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件,如下所示: 
    ①ServletContextListener:对Servlet上下文的创建和销毁进行监听。 
    ②ServletContextAttributeListener:监听Servlet上下文属性的添加、删除和替换。 
    ③HttpSessionListener:对Session的创建和销毁进行监听。

④HttpSessionAttributeListener:对Session对象中属性的添加、删除和替换进行监听。 
⑤ServletRequestListener:对请求对象的初始化和销毁进行监听。 
⑥ServletRequestAttributeListener:对请求对象属性的添加、删除和替换进行监听。

  1. 你的项目中使用过哪些JSTL标签? 
    答:项目中主要使用了JSTL的核心标签库,包括<c:if>、<c:choose>、<c: when>、<c: otherwise>、<c:forEach>等,主要用于构造循环和分支结构以控制显示逻辑。
  1. 使用标签库有什么好处? 
    答:使用标签库的好处包括以下几个方面: 
    - 分离JSP页面的内容和逻辑,简化了Web开发; 
    - 开发者可以创建自定义标签来封装业务逻辑和显示逻辑; 
    - 标签具有很好的可移植性、可维护性和可重用性; 
    - 避免了对Scriptlet(小脚本)的使用(很多公司的项目开发都不允许在JSP中书写小脚本)
  1. 表达式语言(EL)支持哪些运算符?

答:除了.和[]运算符,EL还提供了:

- 算术运算符:+、-、*、/或div、%或mod

- 关系运算符:==或eq、!=或ne、>或gt、>=或ge、<或lt、<=或le

- 逻辑运算符:&&或and、||或or、!或not

- 条件运算符:${statement? A : B}(跟Java的条件运算符类似)

- empty运算符:检查一个值是否为null或者空(数组长度为0或集合中没有元素也返回true)

  1. Java Web开发的Model 1Model 2分别指的是什么? 
    答:Model 1是以页面为中心的Java Web开发,使用JSP+JavaBean技术将页面显示逻辑和业务逻辑处理分开,JSP实现页面显示,JavaBean对象用来保存数据和实现业务逻辑。Model 2是基于MVC(模型-视图-控制器,Model-View-Controller)架构模式的开发模型,实现了模型和视图的彻底分离,利于团队开发和代码复用。
  1. 实现会话跟踪的技术有哪些?

答:由于HTTP协议本身是无状态的,服务器为了区分不同的用户,就需要对用户会话进行跟踪,简单的说就是为用户进行登记,为用户分配唯一的ID,下一次用户在请求中包含此ID,服务器据此判断到底是哪一个用户。

①URL 重写:在URL中添加用户会话的信息作为请求的参数,或者将唯一的会话ID添加到URL结尾以标识一个会话。

②设置表单隐藏域:将和会话跟踪相关的字段添加到隐式表单域中,这些信息不会在浏览器中显示但是提交表单时会提交给服务器。

这两种方式很难处理跨越多个页面的信息传递,因为如果每次都要修改URL或在页面中添加隐式表单域来存储用户会话相关信息,事情将变得非常麻烦。

③cookie:cookie有两种,一种是基于窗口的,浏览器窗口关闭后,cookie就没有了;另一种是将信息存储在一个临时文件中,并设置存在的时间。当用户通过浏览器和服务器建立一次会话后,会话ID就会随响应信息返回存储在基于窗口的cookie中,那就意味着只要浏览器没有关闭,会话没有超时,下一次请求时这个会话ID又会提交给服务器让服务器识别用户身份。会话中可以为用户保存信息。会话对象是在服务器内存中的,而基于窗口的cookie是在客户端内存中的。如果浏览器禁用了cookie,那么就需要通过下面两种方式进行会话跟踪。当然,在使用cookie时要注意几点:首先不要在cookie中存放敏感信息;其次cookie存储的数据量有限(4k),不能将过多的内容存储cookie中;再者浏览器通常只允许一个站点最多存放20个cookie。当然,和用户会话相关的其他信息(除了会话ID)也可以存在cookie方便进行会话跟踪。

④HttpSession:在所有会话跟踪技术中,HttpSession对象是最强大也是功能最多的。当一个用户第一次访问某个网站时会自动创建HttpSession,每个用户可以访问他自己的HttpSession。可以通过HttpServletRequest对象的getSession方法获得HttpSession,通过HttpSession的setAttribute方法可以将一个值放在HttpSession中,通过调用HttpSession对象的getAttribute方法,同时传入属性名就可以获取保存在HttpSession中的对象。与上面三种方式不同的是,HttpSession放在服务器的内存中,因此不要将过大的对象放在里面,即使目前的Servlet容器可以在内存将满时将HttpSession中的对象移到其他存储设备中,但是这样势必影响性能。添加到HttpSession中的值可以是任意Java对象,这个对象最好实现了Serializable接口,这样Servlet容器在必要的时候可以将其序列化到文件中,否则在序列化时就会出现异常。

  1. 如何在基于Java的Web项目中实现文件上传和下载?

答:在Sevlet 3 以前,Servlet API中没有支持上传功能的API,因此要实现上传功能需要引入第三方工具从POST请求中获得上传的附件或者通过自行处理输入流来获得上传的文件,我们推荐使用Apache的commons-fileupload。

  1. 如何设置请求的编码以及响应内容的类型? 
    答:通过请求对象(ServletRequest)的setCharacterEncoding(String)方法可以设置请求的编码,其实要彻底解决乱码问题就应该让页面、服务器、请求和响应、Java程序都使用统一的编码,最好的选择当然是UTF-8;通过响应对象(ServletResponse)的setContentType(String)方法可以设置响应内容的类型,当然也可以通过HttpServletResponsed对象的setHeader(String, String)方法来设置。
  1. 解释一下网络应用的模式及其特点。 
    答:典型的网络应用模式大致有三类:B/S、C/S、P2P。其中B代表浏览器(Browser)、C代表客户端(Client)、S代表服务器(Server),P2P是对等模式,不区分客户端和服务器。B/S应用模式中可以视为特殊的C/S应用模式,只是将C/S应用模式中的特殊的客户端换成了浏览器,因为几乎所有的系统上都有浏览器,那么只要打开浏览器就可以使用应用,没有安装、配置、升级客户端所带来的各种开销。P2P应用模式中,成千上万台彼此连接的计算机都处于对等的地位,整个网络一般来说不依赖专用的集中服务器。网络中的每一台计算机既能充当网络服务的请求者,又对其它计算机的请求作出响应,提供资源和服务。通常这些资源和服务包括:信息的共享和交换、计算资源(如CPU的共享)、存储共享(如缓存和磁盘空间的使用)等,这种应用模式最大的阻力安全性、版本等问题,目前有很多应用都混合使用了多种应用模型,最常见的网络视频应用,它几乎把三种模式都用上了。四、

四、框架面试题

Spring  Boot总结
1、什么是SpringBoot
    描述:Spring  Boot是Spring社区发布的一个开源项目,旨在帮助开发者快速并且更简单的构建项目。大多数SpringBoot项目只需要很少的配置文件。
2、SpringBoot核心功能
2.1、独立运行Spring项目
Spring  boot  可以以jar包形式独立运行,运行一个Spring  Boot项目只需要通过java  -jar  xx.jar来运行。
2.2、内嵌servlet容器
Spring  Boot可以选择内嵌Tomcat、jetty或者Undertow,这样我们无须以war包形式部署项目。
2.3、提供starter简化Maven配置
spring提供了一系列的start  pom来简化Maven的依赖加载,例如,当你使用了spring-boot-starter-web,会自动加入如图5-1所示的依赖包。
2.4、自动装配Spring  
SpringBoot会根据在类路径中的jar包,类、为jar包里面的类自动配置Bean,这样会极大地减少我们要使用的配置。当然,SpringBoot只考虑大多数的开发场景,并不是所有的场景,若在实际开发中我们需要配置Bean,而SpringBoot灭有提供支持,则可以自定义自动配置。
2.5、准生产的应用监控
SpringBoot提供基于http  ssh  telnet对运行时的项目进行监控。
2.6、无代码生产和xml配置    
SpringBoot不是借助与代码生成来实现的,而是通过条件注解来实现的,这是Spring4.x提供的新特性。
3、SpringBoot优缺点
优点:
3.1、快速构建项目。
3.2、对主流开发框架的无配置集成。
3.3、项目可独立运行,无须外部依赖Servlet容器。
3.4、提供运行时的应用监控。
3.5、极大的提高了开发、部署效率。
3.6、与云计算的天然集成。
缺点:
3.1、如果你不认同spring框架,也许这就是缺点。
4、SpringBoot特性
4.1、创建独立的Spring项目
4.2、内置Tomcat和Jetty容器
4.3、提供一个starter  POMs来简化Maven配置
4.4、提供了一系列大型项目中常见的非功能性特性,如安全、指标,健康检测、外部配置等
4.5、完全没有代码生成和xml配置文件
6、SpringBoot  CLI
SpringBoot  CLI  是SpringBoot提供的控制台命令工具。
7、SpringBoot  maven  构建项目
spring-boot-starter-parent:是一个特殊Start,它用来提供相关的Maven依赖项,使用它之后,常用的包依赖可以省去version标签。
8、SpringBoot几个常用的注解
(1)@RestController和@Controller指定一个类,作为控制器的注解  
(2)@RequestMapping方法级别的映射注解,这一个用过Spring  MVC的小伙伴相信都很熟悉  
(3)@EnableAutoConfiguration和@SpringBootApplication是类级别的注解,根据maven依赖的jar来自动猜测完成正确的spring的对应配置,只要引入了spring-boot-starter-web的依赖,默认会自动配置Spring  MVC和tomcat容器
(4)@Configuration类级别的注解,一般这个注解,我们用来标识main方法所在的类,完成元数据bean的初始化。
(5)@ComponentScan类级别的注解,自动扫描加载所有的Spring组件包括Bean注入,一般用在main方法所在的类上  
(6)@ImportResource类级别注解,当我们必须使用一个xml的配置时,使用@ImportResource和@Configuration来标识这个文件资源的类。  
(7)@Autowired注解,一般结合@ComponentScan注解,来自动注入一个Service或Dao级别的Bean
(8)@Component类级别注解,用来标识一个组件,比如我自定了一个filter,则需要此注解标识之后,Spring  Boot才会正确识别。
Spring  Boot、Spring  MVC  和  Spring  有什么区别?
SpringFrame
SpringFramework  最重要的特征是依赖注入。所有  SpringModules  不是依赖注入就是  IOC  控制反转。
当我们恰当的使用  DI  或者是  IOC  的时候,我们可以开发松耦合应用。松耦合应用的单元测试可以很容易的进行。
SpringMVC
Spring  MVC  提供了一种分离式的方法来开发  Web  应用。通过运用像  DispatcherServelet,MoudlAndView  和  ViewResolver  等一些简单的概念,开发  Web  应用将会变的非常简单。
SpringBoot
Spring  和  SpringMVC  的问题在于需要配置大量的参数。
<bean
  class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property  name="prefix">
                <value>/WEB-INF/views/</value>
        </property>
        <property  name="suffix">
                <value>.jsp</value>
        </property>
    </bean>

<mvc:resources  mapping="/webjars/**"  location="/webjars/"/>
Spring  Boot  通过一个自动配置和启动的项来目解决这个问题。为了更快的构建产品就绪应用程序,Spring  Boot  提供了一些非功能性特征。

Spring  Boot  还提供了其它的哪些  Starter  Project  Options?
Spring  Boot  也提供了其它的启动器项目包括,包括用于开发特定类型应用程序的典型依赖项。
spring-boot-starter-web-services  -  SOAP  Web  Services
spring-boot-starter-web  -  Web  和  RESTful  应用程序
spring-boot-starter-test  -  单元测试和集成测试
spring-boot-starter-jdbc  -  传统的  JDBC
spring-boot-starter-hateoas  -  为服务添加  HATEOAS  功能
spring-boot-starter-security  -  使用  SpringSecurity  进行身份验证和授权
spring-boot-starter-data-jpa  -  带有  Hibeernate  的  Spring  Data  JPA
spring-boot-starter-data-rest  -  使用  Spring  Data  REST  公布简单的  REST  服务

(1) Spring在SSM起什么作用
Spring是一个轻量级框架,也是一个容器,Spring实质上讲就是一个Bean工厂,主要用来管理Bean的生命周期和框架集成。有IOC控制反转,DI依赖注入,控制反转是把dao依赖注入到servic层,然后service层反转给action层,Spring的顶层容器为BeanFactory,常用的ApplicationContext为它的子接口,实现了工厂模式,Spring还提供了AOP的支持,方便在切面级开发,
(2) 怎么样理解IOC和DI
在使用Spring框架的过程中、一定会用到控制反转、但是往往所需要的资源还需要其他资源的支持、个过程就需要依赖注入的支持
(3)Spring的事务,事务的作用。
• 编程式事务管理:这意味你通过编程的方式管理事务,给你带来极大的灵活性,但是难维护。
• 声明式事务管理:这意味着你可以将业务代码和事务管理分离,你只需用注解和XML配置来管理事务。
(3) Spring的IOC你在项目中是怎么使用的?
• IOC主要来解决对象之间的依赖问题,把所有的bean的依赖关系通过配置文件或者注解关联起来,降低了耦合度

高内聚、低耦合
(5)Spring的配置文件有哪些内容?
• 开启事务注解驱动
• 事务管理器
• 开启注解功能,并配置扫描包
• 配置数据源
• 配置SQL会话工厂、别名、映射文件
• 不用编写DAO层的实现类(代理模式)
(6)说下Spring的注解
• @Controller
• @Service
• @Component
• @RequestMapping
• @Resource、@Autowired
• @ResponseBody
• @Transactional

(7)为什么要用Spring
• 降低对象耦合度,让代码更加清晰,提供一些常见的模版
(8)Spring DI的几种方式
• (1)构造器注入:通过构造方法初始化
• <constructor-arg name="dao"</constructor-arg>
• (2)setter注入:通过setter方法初始化注入
• <property name="dao" ref="dao2"></property>
• 注意:在实际开发中常用setter注入。
(1)SpringMvc的控制器是不是单例模式,如果是,有什么问题,怎么解决
是单例模式,所以在多线程访问的时候有线程安全问题,不要用同步,会影响性能的,解决方案是在控制器里面不能写字段
(2)SpingMvc中的控制器的注解
@Controller 注解:该注解表明该类扮演控制器的角色,Spring不需要你继承任何其他控制器基类或引用Servlet API。
(3)@RequestMapping注解用在类上面有什么作用
该注解是用来映射一个URL到一个类或一个特定的方处理法上。
(4) 我想在拦截的方法里面得到从前台传入的参数,怎么得到
直接在形参里面声明这个参数就可以,但必须名字和传过来的参数一样
(5)如果前台有很多个参数传入,并且这些参数都是一个对象的,那么怎么样快速得到这个对象
直接在方法中声明这个对象,SpringMvc就自动会把属性赋值到这个对象里面
(6)SpringMvc中函数的返回值是什么
返回值可以有很多类型,有String, ModelAndView,List,Set等,一般用String比较好,如果是AJAX请求,返回的可以是一个集合
(7)SpringMvc怎么处理返回值的
SpringMvc根据配置文件中InternalResourceViewResolver(内部资源视图解析器)的前缀和后缀,用前缀+返回值+后缀组成完整的返回值
(8)SpringMVC怎么样设定重定向和转发的
在返回值前面加"forward:"就可以让结果转发,譬如"forward:user.do?name=method4" 在返回值前面加"redirect:"就可以让返回值重定向,譬如"redirect:http://www.uu456.com"
(9)SpringMvc中有个类把视图和数据都合并的一起的,叫什么
ModelAndView
(10)怎么样把数据放入Session里面
可以声明一个request,或者session先拿到session,然后就可以放入数据,或者可以在类上面加上@SessionAttributes注解,里面包含的字符串就是要放入session里面的key
(11)SpringMvc怎么和AJAX相互调用的
通过Jackson框架就可以把Java里面的对象直接转化成js可以识别的Json对象 具体步骤如下 :
1.加入Jackson.jar
2.在配置文件中配置json的映射
3.在接受Ajax方法里面可以直接返回Object,List等,但方法前面要加上@ResponseBody注解
(12)当一个方法向AJAX返回对象,譬如Object,List等,需要做什么处理
要加上@ResponseBody注解
(13)讲下SpringMvc的执行流程
系统启动的时候根据配置文件创建spring的容器, 首先是发送http请求到核心控制器DispatcherServlet,spring容器通过映射器去寻找业务控制器,
使用适配器找到相应的业务类,在进业务类时进行数据封装,在封装前可能会涉及到类型转换,执行完业务类后使用ModelAndView进行视图转发,
数据放在model中,用map传递数据进行页面显示。
(1)什么是MyBatis的接口绑定,有什么好处
接口映射就是在IBatis中任意定义接口,然后把接口里面的方法和SQL语句绑定,我们直接调用接口方法就可以,这样比起原来了SqlSession提供的方法我们可以有更加灵活的选择和设置.
(2)什么情况下用注解绑定,什么情况下用xml绑定
当Sql语句比较简单时候,用注解绑定,当SQL语句比较复杂时候,用xml绑定,一般用xml绑定的比较多
(3)如果要查询的表名和返回的实体Bean对象不一致,那你是怎么处理的?
在MyBatis里面最主要最灵活的的一个映射对象的ResultMap,在它里面可以映射键值对, 默认里面有id节点,result节点,它可以映射表里面的列名和对象里面的字段名. 并且在一对一,一对多的情况下结果集也一定要用ResultMap
(4)MyBatis在核心处理类叫什么
MyBatis里面的核心处理类叫做SqlSession
(5)讲下MyBatis的缓存
MyBatis的缓存分为一级缓存和二级缓存,一级缓存放在session里面,默认就有,二级缓存放在它的命名空间里,
默认是打开的,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置<cache/>
(6)MyBatis(IBatis)的好处是什么
ibatis把sql语句从Java源程序中独立出来,放在单独的XML文件中编写,给程序的
维护带来了很大便利。
ibatis封装了底层JDBC API的调用细节,并能自动将结果集转换成JavaBean对象,大大简化了Java数据库编程的重复工作。
因为Ibatis需要程序员自己去编写sql语句,程序员可以结合数据库自身的特点灵活控制sql语句,
因此能够实现比hibernate等全自动orm框架更高的查询效率,能够完成复杂查询。
(7)MyBatis怎么配置一对多?
一对多的关系 :property: 指的是集合属性的值, ofType:指的是集合中元素的类型
(8)MyBatis怎样配置多对一?
多对一的关系:property: 指的是属性的值, javaType:指的是属性的类型

五、数据库面试题

Student(SId,Sname,Sage,Ssex) 学生表

Course(CId,Cname,TId) 课程表

SC(SId,CId,score) 成绩表

Teacher(TId,Tname) 教师表

问题:

1、查询“001”课程比“002”课程成绩高的所有学生的学号;

select a.SId from (select sId,score from SC where CId='001') a,(select sId,score

from SC where CId='002') b

where a.score>b.score and a.sId=b.sId;

2、查询平均成绩大于60分的同学的学号和平均成绩;

select SId,avg(score)

from sc

group by SId having avg(score) >60;

3、查询所有同学的学号、姓名、选课数、总成绩;

select Student.SId,Student.Sname,count(SC.CId),sum(score)

from Student left Outer join SC on Student.SId=SC.SId

group by Student.SId,Sname

4、查询姓“李”的老师的个数;

select count(distinct(Tname))

from Teacher

where Tname like '李%';

5、查询没学过“叶平”老师课的同学的学号、姓名;

select Student.SId,Student.Sname

from Student

where SId not in (select distinct( SC.SId) from SC,Course,Teacher where  SC.CId=Course.CId and Teacher.TId=Course.TId and Teacher.Tname='叶平');

6、查询学过“001”并且也学过编号“002”课程的同学的学号、姓名;

select Student.SId,Student.Sname from Student,SC where Student.SId=SC.SId and SC.CId='001'and exists( Select * from SC as SC_2 where SC_2.SId=SC.SId and SC_2.CId='002');

7、查询学过“叶平”老师所教的所有课的同学的学号、姓名;

select SId,Sname

from Student

where SId in (select SId from SC ,Course ,Teacher where SC.CId=Course.CId and Teacher.TId=Course.TId and Teacher.Tname='叶平' group by SId having count(SC.CId)=(select count(CId) from Course,Teacher  where Teacher.TId=Course.TId and Tname='叶平'));

8、查询课程编号“002”的成绩比课程编号“001”课程低的所有同学的学号、姓名;

Select SId,Sname from (select Student.SId,Student.Sname,score ,(select score from SC SC_2 where SC_2.SId=Student.SId and SC_2.CId='002') score2

from Student,SC where Student.SId=SC.SId and CId='001') S_2 where score2 <score;

9、查询所有课程成绩小于60分的同学的学号、姓名;

select SId,Sname

from Student

where SId not in (select Student.SId from Student,SC where S.SId=SC.SId and score>60);

10、查询没有学全所有课的同学的学号、姓名;

select Student.SId,Student.Sname

from Student,SC

where Student.SId=SC.SId group by  Student.SId,Student.Sname having count(CId) <(select count(CId) from Course);

11、查询至少有一门课与学号为“1001”的同学所学相同的同学的学号和姓名;

select SId,Sname from Student,SC where Student.SId=SC.SId and CId in select CId from SC where SId='1001';

12、查询至少学过学号为“001”同学所有一门课的其他同学学号和姓名;

select distinct SC.SId,Sname

from Student,SC

where Student.SId=SC.SId and CId in (select CId from SC where SId='001');

13、把“SC”表中“叶平”老师教的课的成绩都更改为此课程的平均成绩;

update SC set score=(select avg(SC_2.score)

from SC SC_2

where SC_2.CId=SC.CId ) from Course,Teacher where Course.CId=SC.CId and Course.TId=Teacher.TId and Teacher.Tname='叶平');

14、查询和“1002”号的同学学习的课程完全相同的其他同学学号和姓名;

select SId from SC where CId in (select CId from SC where SId='1002')

group by SId having count(*)=(select count(*) from SC where SId='1002');

15、删除学习“叶平”老师课的SC表记录;

Delect SC

from course ,Teacher

where Course.CId=SC.CId and Course.TId= Teacher.TId and Tname='叶平';

16、向SC表中插入一些记录,这些记录要求符合以下条件:没有上过编号“003”课程的同学学号、2

号课的平均成绩;

Insert SC select SId,'002',(Select avg(score)

from SC where CId='002') from Student where SId not in (Select SId from SC where CId='002');

17、按平均成绩从高到低显示所有学生的“数据库”、“企业管理”、“英语”三门的课程成绩,按如下形式显示: 学生ID,,数据库,企业管理,英语,有效课程数,有效平均分

SELECT SId as 学生ID

,(SELECT score FROM SC WHERE SC.SId=t.SId AND CId='004') AS 数据库

,(SELECT score FROM SC WHERE SC.SId=t.SId AND CId='001') AS 企业管理

,(SELECT score FROM SC WHERE SC.SId=t.SId AND CId='006') AS 英语

,COUNT(*) AS 有效课程数, AVG(t.score) AS 平均成绩

FROM SC AS t

GROUP BY SId

ORDER BY avg(t.score)

18、查询各科成绩最高和最低的分:以如下形式显示:课程ID,最高分,最低分

SELECT L.CId As 课程ID,L.score AS 最高分,R.score AS 最低分

FROM SC L ,SC AS R

WHERE L.CId = R.CId and

L.score = (SELECT MAX(IL.score)

FROM SC AS IL,Student AS IM

WHERE L.CId = IL.CId and IM.SId=IL.SId

GROUP BY IL.CId)

AND

R.Score = (SELECT MIN(IR.score)

FROM SC AS IR

WHERE R.CId = IR.CId

GROUP BY IR.CId

);

19、按各科平均成绩从低到高和及格率的百分数从高到低顺序

SELECT t.CId AS 课程号,max(course.Cname)AS 课程名,isnull(AVG(score),0) AS 平均成绩

,100 * SUM(CASE WHEN  isnull(score,0)>=60 THEN 1 ELSE 0 END)/COUNT(*) AS 及格百分数

FROM SC T,Course

where t.CId=course.CId

GROUP BY t.CId

ORDER BY 100 * SUM(CASE WHEN  isnull(score,0)>=60 THEN 1 ELSE 0 END)/COUNT(*) DESC

20、查询如下课程平均成绩和及格率的百分数(用"1行"显示): 企业管理(001),马克思(002),OO&UML (003),数据库(004

SELECT SUM(CASE WHEN CId ='001' THEN score ELSE 0 END)/SUM(CASE CId WHEN '001' THEN 1 ELSE 0 END) AS 企业管理平均分

,100 * SUM(CASE WHEN CId = '001' AND score >= 60 THEN 1 ELSE 0 END)/SUM(CASE WHEN CId = '001' THEN 1 ELSE 0 END) AS 企业管理及格百分数

,SUM(CASE WHEN CId = '002' THEN score ELSE 0 END)/SUM(CASE CId WHEN '002' THEN 1 ELSE 0 END) AS 马克思平均分

,100 * SUM(CASE WHEN CId = '002' AND score >= 60 THEN 1 ELSE 0 END)/SUM(CASE WHEN CId = '002' THEN 1 ELSE 0 END) AS 马克思及格百分数

,SUM(CASE WHEN CId = '003' THEN score ELSE 0 END)/SUM(CASE CId WHEN '003' THEN 1 ELSE 0 END) AS UML平均分

,100 * SUM(CASE WHEN CId = '003' AND score >= 60 THEN 1 ELSE 0 END)/SUM(CASE WHEN CId = '003' THEN 1 ELSE 0 END) AS UML及格百分数

,SUM(CASE WHEN CId = '004' THEN score ELSE 0 END)/SUM(CASE CId WHEN '004' THEN 1 ELSE 0 END) AS 数据库平均分

,100 * SUM(CASE WHEN CId = '004' AND score >= 60 THEN 1 ELSE 0 END)/SUM(CASE WHEN CId = '004' THEN 1 ELSE 0 END) AS 数据库及格百分数

FROM SC

21、查询不同老师所教不同课程平均分从高到低显示

SELECT max(Z.TId) AS 教师ID,MAX(Z.Tname) AS 教师姓名,C.CId AS 课程ID,MAX(C.Cname) AS 课程名称,AVG(Score) AS 平均成绩

FROM SC AS T,Course AS C ,Teacher AS Z

where T.CId=C.CId and C.TId=Z.TId

GROUP BY C.CId

ORDER BY AVG(Score) DESC

22、查询如下课程成绩第 3 名到第 6 名的学生成绩单:企业管理(001),马克思(002),UML (003),数据库(004

[学生ID],[学生姓名],企业管理,马克思,UML,数据库,平均成绩

SELECT  DISTINCT top 3

SC.SId As 学生学号,

Student.Sname AS 学生姓名 ,

T1.score AS 企业管理,

T2.score AS 马克思,

T3.score AS UML,

T4.score AS 数据库,

ISNULL(T1.score,0) + ISNULL(T2.score,0) + ISNULL(T3.score,0) + ISNULL(T4.score,0) as 总分

FROM Student,SC  LEFT JOIN SC AS T1

ON SC.SId = T1.SId AND T1.CId = '001'

LEFT JOIN SC AS T2

ON SC.SId = T2.SId AND T2.CId = '002'

LEFT JOIN SC AS T3

ON SC.SId = T3.SId AND T3.CId = '003'

LEFT JOIN SC AS T4

ON SC.SId = T4.SId AND T4.CId = '004'

WHERE student.SId=SC.SId and

ISNULL(T1.score,0) + ISNULL(T2.score,0) + ISNULL(T3.score,0) + ISNULL(T4.score,0)

NOT IN

(SELECT

DISTINCT

TOP 15 WITH TIES

ISNULL(T1.score,0) + ISNULL(T2.score,0) + ISNULL(T3.score,0) + ISNULL(T4.score,0)

FROM sc

LEFT JOIN sc AS T1

ON sc.SId = T1.SId AND T1.CId = 'k1'

LEFT JOIN sc AS T2

ON sc.SId = T2.SId AND T2.CId = 'k2'

LEFT JOIN sc AS T3

ON sc.SId = T3.SId AND T3.CId = 'k3'

LEFT JOIN sc AS T4

ON sc.SId = T4.SId AND T4.CId = 'k4'

ORDER BY ISNULL(T1.score,0) + ISNULL(T2.score,0) + ISNULL(T3.score,0) + ISNULL(T4.score,0) DESC);

23、统计列印各科成绩,各分数段人数:课程ID,课程名称,[100-85],[85-70],[70-60],[ <60]

SELECT SC.CId as 课程ID, Cname as 课程名称

,SUM(CASE WHEN score BETWEEN 85 AND 100 THEN 1 ELSE 0 END) AS [100 - 85]

,SUM(CASE WHEN score BETWEEN 70 AND 85 THEN 1 ELSE 0 END) AS [85 - 70]

,SUM(CASE WHEN score BETWEEN 60 AND 70 THEN 1 ELSE 0 END) AS [70 - 60]

,SUM(CASE WHEN score < 60 THEN 1 ELSE 0 END) AS [60 -]

FROM SC,Course

where SC.CId=Course.CId

GROUP BY SC.CId,Cname;

24、查询学生平均成绩及其名次

SELECT 1+(SELECT COUNT( distinct 平均成绩)

FROM (SELECT SId,AVG(score) AS 平均成绩

FROM SC

GROUP BY SId

) AS T1

WHERE 平均成绩 > T2.平均成绩) as 名次,

SId as 学生学号,平均成绩

FROM (SELECT SId,AVG(score) 平均成绩

FROM SC

GROUP BY SId

) AS T2

ORDER BY 平均成绩 desc;

25、查询各科成绩前三名的记录:(不考虑成绩并列情况)

SELECT t1.SId as 学生ID,t1.CId as 课程ID,Score as 分数

FROM SC t1

WHERE score IN (SELECT TOP 3 score

FROM SC

WHERE t1.CId= CId

ORDER BY score DESC

)

ORDER BY t1.CId;

26、查询每门课程被选修的学生数

select cId,count(SId) from sc group by CId;

27、查询出只选修了一门课程的全部学生的学号和姓名

select SC.SId,Student.Sname,count(CId) AS 选课数

from SC ,Student

where SC.SId=Student.SId group by SC.SId ,Student.Sname having count(CId)=1;

28、查询男生、女生人数

Select count(Ssex) as 男生人数 from Student group by Ssex having Ssex='男';

Select count(Ssex) as 女生人数 from Student group by Ssex having Ssex='女';

29、查询姓“张”的学生名单

SELECT Sname FROM Student WHERE Sname like '张%';

30、查询同名同性学生名单,并统计同名人数

select Sname,count(*) from Student group by Sname having  count(*)>1;;

31、1981年出生的学生名单(注:Student表中Sage列的类型是datetime)

select Sname,  CONVERT(char (11),DATEPART(year,Sage)) as age

from student

where  CONVERT(char(11),DATEPART(year,Sage))='1981';

32、查询每门课程的平均成绩,结果按平均成绩升序排列,平均成绩相同时,按课程号降序排列

Select CId,Avg(score) from SC group by CId order by Avg(score),CId DESC ;

33、查询平均成绩大于85的所有学生的学号、姓名和平均成绩

select Sname,SC.SId ,avg(score)

from Student,SC

where Student.SId=SC.SId group by SC.SId,Sname having    avg(score)>85;

34、查询课程名称为“数据库”,且分数低于60的学生姓名和分数

Select Sname,isnull(score,0)

from Student,SC,Course

where SC.SId=Student.SId and SC.CId=Course.CId and  Course.Cname='数据库'and score <60;

35、查询所有学生的选课情况;

SELECT SC.SId,SC.CId,Sname,Cname

FROM SC,Student,Course

where SC.SId=Student.SId and SC.CId=Course.CId ;

36、查询任何一门课程成绩在70分以上的姓名、课程名称和分数;

SELECT  distinct student.SId,student.Sname,SC.CId,SC.score

FROM student,Sc

WHERE SC.score>=70 AND SC.SId=student.SId;

37、查询不及格的课程,并按课程号从大到小排列

select cId from sc where scor e <60 order by CId ;

38、查询课程编号为003且课程成绩在80分以上的学生的学号和姓名;

select SC.SId,Student.Sname from SC,Student where SC.SId=Student.SId and Score>80 and CId='003';

39、求选了课程的学生人数

select count(*) from sc;

40、查询选修“叶平”老师所授课程的学生中,成绩最高的学生姓名及其成绩

select Student.Sname,score

from Student,SC,Course C,Teacher

where Student.SId=SC.SId and SC.CId=C.CId and C.TId=Teacher.TId and Teacher.Tname='叶平' and SC.score=(select max(score)from SC where CId=C.CId );

41、查询各个课程及相应的选修人数

select count(*) from sc group by CId;

42、查询不同课程成绩相同的学生的学号、课程号、学生成绩

select distinct  A.SId,B.score from SC A  ,SC B where A.Score=B.Score and A.CId <>B.CId ;

43、查询每门功成绩最好的前两名

SELECT t1.SId as 学生ID,t1.CId as 课程ID,Score as 分数

FROM SC t1

WHERE score IN (SELECT TOP 2 score

FROM SC

WHERE t1.CId= CId

ORDER BY score DESC

)

ORDER BY t1.CId;

44、统计每门课程的学生选修人数(超过10人的课程才统计)。要求输出课程号和选修人数,查询结果按人数降序排列,查询结果按人数降序排列,若人数相同,按课程号升序排列

select  CId as 课程号,count(*) as 人数

from  sc

group  by  CId

order  by  count(*) desc,cId

45、检索至少选修两门课程的学生学号

select  SId

from  sc

group  by  sId

having  count(*)  >  =  2

46、查询全部学生都选修的课程的课程号和课程名

select  CId,Cname

from  Course

where  CId  in  (select  cId  from  sc group  by  cId)

47、查询没学过“叶平”老师讲授的任一门课程的学生姓名

select Sname from Student where SId not in (select SId from Course,Teacher,SC where Course.TId=Teacher.TId and SC.CId=course.CId and Tname='叶平');

48、查询两门以上不及格课程的同学的学号及其平均成绩

select SId,avg(isnull(score,0)) from SC where SId in (select SId from SC where score <60 group by SId having count(*)>2)group by SId;

49、检索“004”课程分数小于60,按分数降序排列的同学学号

select SId from SC where CId='004'and score <60 order by score desc;

50、删除“002”同学的“001”课程的成绩

delete from Sc where SId='001'and CId='001';

问题描述:

本题用到下面三个关系表:

CARD     借书卡。   CNO 卡号,NAME  姓名,CLASS 班级

BOOKS    图书。     BNO 书号,BNAME 书名,AUTHOR 作者,PRICE 单价,QUANTITY 库存册数

BORROW   借书记录。 CNO 借书卡号,BNO 书号,RDATE 还书日期

备注:限定每人每种书只能借一本;库存册数随借书、还书而改变。

要求实现如下15个处理:

1. 写出建立BORROW表的SQL语句,要求定义主码完整性约束和引用完整性约束。

2. 找出借书超过5本的读者,输出借书卡号及所借图书册数。

3. 查询借阅了"水浒"一书的读者,输出姓名及班级。

4. 查询过期未还图书,输出借阅者(卡号)、书号及还书日期。

5. 查询书名包括"网络"关键词的图书,输出书号、书名、作者。

6. 查询现有图书中价格最高的图书,输出书名及作者。

7. 查询当前借了"计算方法"但没有借"计算方法习题集"的读者,输出其借书卡号,并按卡号降序排序输出。

8. 将"C01"班同学所借图书的还期都延长一周。

9. 从BOOKS表中删除当前无人借阅的图书记录。

10.如果经常按书名查询图书信息,请建立合适的索引。

11.在BORROW表上建立一个触发器,完成如下功能:如果读者借阅的书名是"数据库技术及应用",就将该读者的借阅记录保存在BORROW_SAVE表中(注ORROW_SAVE表结构同BORROW表)。

12.建立一个视图,显示"力01"班学生的借书信息(只要求显示姓名和书名)。

13.查询当前同时借有"计算方法"和"组合数学"两本书的读者,输出其借书卡号,并按卡号升序排序输出。

14.假定在建BOOKS表时没有定义主码,写出为BOOKS表追加定义主码的语句。

15.对CARD表做如下修改:

a. 将NAME最大列宽增加到10个字符(假定原为6个字符)。

b. 为该表增加1列NAME(系名),可变长,最大20个字符。

1. 写出建立BORROW表的SQL语句,要求定义主码完整性约束和引用完整性约束

--实现代码:

CREATE TABLE BORROW(

CNO int FOREIGN KEY REFERENCES CARD(CNO),

BNO int FOREIGN KEY REFERENCES BOOKS(BNO),

RDATE datetime,

PRIMARY KEY(CNO,BNO))

2. 找出借书超过5本的读者,输出借书卡号及所借图书册数

--实现代码:

SELECT CNO,借图书册数=COUNT(*)

FROM BORROW

GROUP BY CNO

HAVING COUNT(*)>5

3. 查询借阅了"水浒"一书的读者,输出姓名及班级

--实现代码:

SELECT * FROM CARD c

WHERE EXISTS(

SELECT * FROM BORROW a,BOOKS b

WHERE a.BNO=b.BNO

AND b.BNAME=N'水浒'

AND a.CNO=c.CNO)

4. 查询过期未还图书,输出借阅者(卡号)、书号及还书日期

--实现代码:

SELECT * FROM BORROW

WHERE RDATE<GETDATE()

5. 查询书名包括"网络"关键词的图书,输出书号、书名、作者

--实现代码:

SELECT BNO,BNAME,AUTHOR FROM BOOKS

WHERE BNAME LIKE N'%网络%'

6. 查询现有图书中价格最高的图书,输出书名及作者

--实现代码:

SELECT BNO,BNAME,AUTHOR FROM BOOKS

WHERE PRICE=(

SELECT MAX(PRICE) FROM BOOKS)

7. 查询当前借了"计算方法"但没有借"计算方法习题集"的读者,输出其借书卡号,并按卡号降序排序输出

--实现代码:

SELECT a.CNO

FROM BORROW a,BOOKS b

WHERE a.BNO=b.BNO AND b.BNAME=N'计算方法'

AND NOT EXISTS(

SELECT * FROM BORROW aa,BOOKS bb

WHERE aa.BNO=bb.BNO

AND bb.BNAME=N'计算方法习题集'

AND aa.CNO=a.CNO)

ORDER BY a.CNO DESC

8. 将"C01"班同学所借图书的还期都延长一周

--实现代码:

UPDATE b SET RDATE=DATEADD(Day,7,b.RDATE)

FROM CARD a,BORROW b

WHERE a.CNO=b.CNO

AND a.CLASS=N'C01'

9. 从BOOKS表中删除当前无人借阅的图书记录

--实现代码:

DELETE A FROM BOOKS a

WHERE NOT EXISTS(

SELECT * FROM BORROW

WHERE BNO=a.BNO)

10. 如果经常按书名查询图书信息,请建立合适的索引

--实现代码:

CREATE CLUSTERED INDEX IDX_BOOKS_BNAME ON BOOKS(BNAME)

11. 在BORROW表上建立一个触发器,完成如下功能:如果读者借阅的书名是"数据库技术及应用",就将该读者的借阅记录保存在BORROW_SAVE表中(注ORROW_SAVE表结构同BORROW表)

--实现代码:

CREATE TRIGGER TR_SAVE ON BORROW

FOR INSERT,UPDATE

AS

IF @@ROWCOUNT>0

INSERT BORROW_SAVE SELECT i.*

FROM INSERTED i,BOOKS b

WHERE i.BNO=b.BNO

AND b.BNAME=N'数据库技术及应用'

12. 建立一个视图,显示"力01"班学生的借书信息(只要求显示姓名和书名)

--实现代码:

CREATE VIEW V_VIEW

AS

SELECT a.NAME,b.BNAME

FROM BORROW ab,CARD a,BOOKS b

WHERE ab.CNO=a.CNO

AND ab.BNO=b.BNO

AND a.CLASS=N'力01'

13. 查询当前同时借有"计算方法"和"组合数学"两本书的读者,输出其借书卡号,并按卡号升序排序输出

--实现代码:

SELECT a.CNO

FROM BORROW a,BOOKS b

WHERE a.BNO=b.BNO

AND b.BNAME IN(N'计算方法',N'组合数学')

GROUP BY a.CNO

HAVING COUNT(*)=2

ORDER BY a.CNO DESC

14. 假定在建BOOKS表时没有定义主码,写出为BOOKS表追加定义主码的语句

--实现代码:

ALTER TABLE BOOKS ADD PRIMARY KEY(BNO)

15.1 将NAME最大列宽增加到10个字符(假定原为6个字符)

--实现代码:

ALTER TABLE CARD ALTER COLUMN NAME varchar(10)

15.2 为该表增加1列NAME(系名),可变长,最大20个字符

--实现代码:

ALTER TABLE CARD ADD 系名 varchar(20)

问题描述:

为管理岗位业务培训信息,建立3个表:

S (SId,SN,SD,SA)   SId,SN,SD,SA 分别代表学号、学员姓名、所属单位、学员年龄

C (CId,CN )        CId,CN       分别代表课程编号、课程名称

SC ( SId,CId,G )    SId,CId,G     分别代表学号、所选修的课程编号、学习成绩

要求实现如下5个处理:

1. 使用标准SQL嵌套语句查询选修课程名称为’税收基础’的学员学号和姓名

2. 使用标准SQL嵌套语句查询选修课程编号为’C2’的学员姓名和所属单位

3. 使用标准SQL嵌套语句查询不选修课程编号为’C5’的学员姓名和所属单位

4. 使用标准SQL嵌套语句查询选修全部课程的学员姓名和所属单位

5. 查询选修了课程的学员人数

6. 查询选修课程超过5门的学员学号和所属单位

1. 使用标准SQL嵌套语句查询选修课程名称为’税收基础’的学员学号和姓名

--实现代码:

SELECT SN,SD FROM S

WHERE [SId] IN(

SELECT [SId] FROM C,SC

WHERE C.[CId]=SC.[CId]

AND CN=N'税收基础')

2. 使用标准SQL嵌套语句查询选修课程编号为’C2’的学员姓名和所属单位

--实现代码:

SELECT S.SN,S.SD FROM S,SC

WHERE S.[SId]=SC.[SId]

AND SC.[CId]='C2'

3. 使用标准SQL嵌套语句查询不选修课程编号为’C5’的学员姓名和所属单位

--实现代码:

SELECT SN,SD FROM S

WHERE [SId] NOT IN(

SELECT [SId] FROM SC

WHERE [CId]='C5')

4. 使用标准SQL嵌套语句查询选修全部课程的学员姓名和所属单位

--实现代码:

SELECT SN,SD FROM S

WHERE [SId] IN(

SELECT [SId] FROM SC

RIGHT JOIN C ON SC.[CId]=C.[CId]

GROUP BY [SId]

HAVING COUNT(*)=COUNT(DISTINCT [SId]))

5. 查询选修了课程的学员人数

--实现代码:

SELECT 学员人数=COUNT(DISTINCT [SId]) FROM SC

6. 查询选修课程超过5门的学员学号和所属单位

--实现代码:

SELECT SN,SD FROM S

WHERE [SId] IN(

SELECT [SId] FROM SC

GROUP BY [SId]

HAVING COUNT(DISTINCT [CId])>5)