JavaSE面试题(转)
1.是否可以从一个static方法内部发出对非static方法的调用?
不可以。当一个static方法被调用时,可能还没有创建任何实例对象,如果从一个static方法中发出对非static方法的调用,那个非static方法是关联到哪个对象上的呢?这个逻辑无法成立.
2.Integer与int的区别?
int是 java提供的8种原始数据类型之一,Integer是java为int提供的封装类。int的默认值为0,而Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况。在JSP开发中,Integer的默认为null,所以用el表达式在文本框中显示时,值为空白字符串,而int默认的默认值为0,所以用el表达式在文本框中显示时,结果为0,所以,int不适合作为web层的表单数据的类型。
在Hibernate中,如果将OID定义为Integer类型,那么Hibernate就可以根据其值是否为null而判断一个对象是否是临时的,如果将OID定义为了int类型,还需要在hbm映射文件中设置其unsaved-value属性为0。
3.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.round(11.5)的结果为12,Math.round(-11.5)的结果为-11。
4.Overload和Override的区别?Overloaded的方法是否可以改变返回值的类型?
Overload是重载的意思,Override是覆盖的意思,也就是重写。重载Overload表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不同)。
重写Override表示子类中的方法可以与父类中的某个方法的名称和参数完全相同,通过子类创建的实例对象调用这个方法时,将调用子类中的定义方法,这相当于把父类中定义的那个完全相同的方法给覆盖了,这也是面向对象编程的多态性的一种表现。子类覆盖父类的方法时,只能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常,因为子类可以解决父类的一些问题,不能比父类有更多的问题。子类方法的访问权限只能比父类的更大,不能更小。如果父类的方法是private类型,那么,子类则不存在覆盖的限制,相当于子类中增加了一个全新的方法。
5.接口是否可继承接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concreteclass)?抽象类中是否可以有静态的main方法?
接口可以继承接口。抽象类可以实现(implements)接口,抽象类可以继承具体类。抽象类中可以有静态的main方法。抽象类与普通类的唯一区别就是不能创建实例对象和允许有abstract方法。
6.Java中实现多态的机制是什么?
- 抽象的来讲,多态的意思就是同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
- 实现的原理是动态绑定,程序调用的方法在运行期才动态绑定,追溯源码可以发现,JVM 通过参数的自动转型来找到合适的办法。
7.abstractclass和interface语法上有什么区别?
抽象类可以有构造方法,接口中不能有构造方法。
抽象类中可以有普通成员变量,接口中没有普通成员变量
抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。
抽象类中可以包含静态方法,接口中不能包含静态方法
抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是publicstatic final类型,并且默认即为publicstatic final类型。
一个类可以实现多个接口,但只能继承一个抽象类。
8.abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized?
- abstract的method不可以是static的,因为抽象的方法是要被子类实现的,而static与子类扯不上关系!
- native方法表示该方法要用另外一种依赖平台的编程语言实现的,不存在着被子类实现的问题,所以,它也不能是抽象的,不能与abstract混用。
- synchronized与abstract不可同时修饰一个方法,synchronized应该是作用在一个具体的方法上才有意义.
9.内部类可以引用它的包含类的成员吗?有没有什么限制?
完全可以。如果不是静态内部类,那没有什么限制!如果你把静态嵌套类当作内部类的一种特例,那在这种情况下不可以访问外部类的普通成员变量,而只能访问外部类中的静态成员.
10.String s = "Hello";s = s + "world!";这两行代码执行后,原始的String对象中的内容到底变了没有?
-
没有。因为String被设计成不可变(immutable)类,所以它的所有对象都是不可变对象。在这段代码中,s原先指向一个String对象,内容是 "Hello",然后我们对s进行了+操作,那么s所指向的那个对象是否发生了改变呢?答案是没有。这时,s不指向原来那个对象了,而指向了另一个 String对象,内容为"Hello world!",原来那个对象还存在于内存之中,只是s这个引用变量不再指向它了。
-
通过上面的说明,我们很容易导出另一个结论,如果经常对字符串进行各种各样的修改,或者说,不可预见的修改,那么使用String来代表字符串的话会引起很大的内存开销。因为String对象建立之后不能再改变,所以对于每一个不同的字符串,都需要一个String对象来表示。这时,应该考虑使用StringBuffer类,它允许修改,而不是每个不同的字符串都要生成一个新的对象。
11.String s = new String("xyz");创建了几个StringObject?是否可以继承String类?
两个或一个都有可能,”xyz”对应一个对象,这个对象放在字符串常量缓冲区,常量”xyz”不管出现多少遍,都是缓冲区中的那一个。new String每写一遍,就创建一个新的对象 ,它使用常量”xyz”对象的内容来创建出一个新String对象。如果以前就用过’xyz’,那么这里就不会创建”xyz”了,直接从缓冲区拿,这时创建了一个StringObject;但如果以前没有用过"xyz",那么此时就会创建一个对象并放入缓冲区,这种情况它创建两个对象。至于String类是否继承,答案是否定的,因为 String默认final修饰,是不可继承的 。
12.String、StringBuffer与StringBuilder的区别?
-
String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象
-
StringBuffer和StringBuilder底层是 char[]数组实现的
-
StringBuffer是线程安全的,而StringBuilder是线程不安全的
13.对于如下代码:
String s1 = "a";
String s2 = s1 + "b";
String s3 = "a" + "b";
System.out.println(s2 == "ab");
System.out.println(s3 == "ab");
第一条语句打印的结果为false,s2=a1+"b",相当于构建了一个新的string对象,并将对象引用赋予s2变量,s2的变量值此时就和常量池中“ab”不一致了,只是他们对象值是相等的。
第二条语句打印的结果为true.javac编译可以对字符串常量直接相加的表达式进行优化,不必要等到运行期再去进行加法运算处理,而是在编译时去掉其中的加号,直接将其编译成一个这些常量相连的结果.
14.下面这条语句一共创建了多少个对象:String s="a"+"b"+"c"+"d";
第一行代码被编译器在编译时优化后,相当于直接定义了一个”abcd”的字符串,所以,上面的代码应该只创建了一个String对象。
15.try {}里有一个return语句,那么紧跟在这个try后的finally{}里的code会不会被执行,什么时候被执行,在return前还是后?
首先finally{}中的语句是一定会执行的,那么这个可能正常脱口而出就是return之前.
16.final, finally, finalize的区别?
- final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。内部类要访问局部变量,局部变量必须定义成final类型。
- finally是异常处理语句结构的一部分,表示总是执行。
- finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。但是JVM不保证此方法总被调用.
17.error和exception有什么区别?
error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。exception表示一种设计或实现问题。也就是说,它表示如果程序运行正常,从不会发生的情况。
18.简单说说Java中的异常处理机制的简单原理和应用。
异常是指java程序运行时(非编译)所发生的非正常情况或错误,与现实生活中的事件很相似,现实生活中的事件可以包含事件发生的时间、地点、人物、情节等信息,可以用一个对象来表示,Java使用面向对象的方式来处理异常,它把程序中发生的每个异常也都分别封装到一个对象来表示的,该对象中包含有异常的信息。
Java对异常进行了分类,不同类型的异常分别用不同的Java类表示,所有异常的根类为java.lang.Throwable,Throwable下面又派生了两个子类: Error和Exception,Error表示应用程序本身无法克服和恢复的一种严重问题,程序只有奔溃了,例如,说内存溢出和线程死锁等系统问题。
19.Java中堆和栈有什么区别?
- JVM 中堆和栈属于不同的内存区域,使用目的也不同。栈常用于保存方法帧和局部变量,而对象总是在堆上分配。栈通常都比堆小,也不会在多个线程之间共享,而堆被整个 JVM 的所有线程共享。
-
栈:在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。
-
栈内存是指程序进入一个方法时,会为这个方法单独分配一块私属存储空间,用于存储这个方法内部的局部变量,当这个方法结束时,分配给这个方法的栈会释放,这个栈中的变量也将随之释放。
-
堆:堆内存用来存放由 new 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。
20.能将 int 强制转换为 byte 类型的变量吗?如果该值大于 byte 类型的范围,将会出现什么现象?
可以做强制转换,但是 Java 中 int 是 32 位的,而 byte 是 8 位的,所以,如果强制转化,int 类型的高 24 位将会被丢弃,因为byte 类型的范围是从 -128 到 127。
21.a.hashCode() 有什么用?与 a.equals(b) 有什么关系?
hashCode() 方法对应对象整型的 hash 值。它常用于基于 hash 的集合类,如 Hashtable、HashMap、LinkedHashMap等等。它与 equals() 方法关系特别紧密。根据 Java 规范,两个使用 equal() 方法来判断相等的对象,必须具有相同的 hashcode。
java集合中有 list 和 set 两类,其中 set不允许元素重复实现,那个这个不允许重复实现的方法,如果用 equal 去比较的话,如果存在1000个元素,你 new 一个新的元素出来,需要去调用1000次 equal 去逐个和他们比较是否是同一个对象,这样会大大降低效率。hashcode实际上是返回对象的存储地址,如果这个位置上没有元素,就把元素直接存储在上面,如果这个位置上已经存在元素,这个时候才去调用equal方法与新元素进行比较,相同的话就不存了,散列到其他地址上
22.字节流与字符流的区别?
要把一段二进制数据数据逐一输出到某个设备中,或者从某个设备中逐一读取一段二进制数据,不管输入输出设备是什么,我们要用统一的方式来完成这些操作,用一种抽象的方式进行描述,这个抽象描述方式起名为IO流,对应的抽象类为OutputStream和InputStream,不同的实现类就代表不同的输入和输出设备,它们都是针对字节进行操作的。
底层设备永远只接受字节数据,有时候要写字符串到底层设备,需要将字符串转成字节再进行写入。字符流是字节流的包装,字符流则是直接接受字符串,它内部将串转成字节,再写入底层设备,这为我们向IO设备写入或读取字符串提供了一点点方便。
23.什么是java序列化,如何实现java序列化?Serializable接口的作用?
将一个java对象变成字节流的形式传出去称为序列化,从字节流中恢复一个对象称为反序列化。 实现serializable接口,这样,javac编译时就会进行特殊处理,编译的类才可以被writeObject方法操作,这就是所谓的序列化。需要被序列化的类必须实现Serializable接口,该接口是一个mini接口,其中没有需要实现方法,implements Serializable只是为了标注该对象是可被序列化的。
24.Java 中,throw 和 throws 有什么区别
- throw代表的是动作,throws是状态
- throw用在方法中,而throws用在方法声明中
- throw只能抛出一种异常,而throws可以抛出多个
25.volatile关键字是否能保证线程安全?
否,volatile变量自身具有下列特性: 1. 可见性:对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入。 2. 禁止进行指令重排序 3. 不保证原子性:对任意单个volatile变量的读/写具有原子性,但类似于volatile++这种符合操作不具有原子性。 多线程共享变量的读写是通过主内存进行复制到线程本地内存中和把本地内存中值写入主内存中来实现的。
当写一个volatile变量时,JMM(Java内存模型)会把该线程对应的本地内存中的共享变量值刷新到主内存。
当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效。线程接下来将从住内存中读取共享变量。
只能在有限的一些情形下使用 volatile 变量替代锁。要使 volatile 变量提供理想的线程安全,必须同时满足下面两个条件:
- 对变量的写操作不依赖于当前值。
- 该变量没有包含在具有其他变量的不变式中。
正确使用 volatile 的模式
- 模式 #1:状态标志 >这种类型的状态标记的一个公共特性是:通常只有一种状态转换;volatile 变量仅仅是使用一个布尔状态标志,用于指示发生了一个重要的一次性事件,例如完成初始化或请求停机。
- 模式 #2:一次性安全发布(one-time safe publication) >实现安全发布对象的一种技术就是将对象引用定义为 volatile 类型。该模式的一个必要条件是:被发布的对象必须是线程安全的,或者是有效的不可变对象(有效不可变意味着对象的状态在发布之后永远不会被修改)。volatile 类型的引用可以确保对象的发布形式的可见性,但是如果对象的状态在发布后将发生更改,那么就需要额外的同步。
- 模式 #3:独立观察(independent observation) >安全使用 volatile 的另一种简单模式是:定期 “发布” 观察结果供程序内部使用。该模式是前面模式的扩展;将某个值发布以在程序内的其他地方使用,但是与一次性事件的发布不同,这是一系列独立事件。这个模式要求被发布的值是有效不可变的 —— 即值的状态在发布后不会更改。使用该值的代码需要清楚该值可能随时发生变化。
- 模式 #4:“volatile bean” 模式 >volatile bean 模式适用于将 JavaBeans 作为“荣誉结构”使用的框架。在 volatile bean 模式中,JavaBean 被用作一组具有 getter 和/或 setter 方法 的独立属性的容器。volatile bean 模式的基本原理是:很多框架为易变数据的持有者(例如 HttpSession)提供了容器,但是放入这些容器中的对象必须是线程安全的。在 volatile bean 模式中,JavaBean 的所有数据成员都是 volatile 类型的,并且 getter 和 setter 方法必须非常普通 —— 除了获取或设置相应的属性外,不能包含任何逻辑。此外,对于对象引用的数据成员,引用的对象必须是有效不可变的。(这将禁止具有数组值的属性,因为当数组引用被声明为 volatile 时,只有引用而不是数组本身具有 volatile 语义)。对于任何 volatile 变量,不变式或约束都不能包含 JavaBean 属性。
-
模式 #5:开销较低的读-写锁策略 >如果读操作远远超过写操作,您可以结合使用内部锁和 volatile 变量来减少公共代码路径的开销。
>结合使用 volatile 和 synchronized 实现 “开销较低的读-写锁”
@ThreadSafe public class CheesyCounter { // Employs the cheap read-write lock trick // All mutative operations MUST be done with the 'this' lock held @GuardedBy("this") private volatile int value;
public int getValue() { return value; }
public synchronized int increment() {
return value++;
}
}
之所以将这种技术称之为 “开销较低的读-写锁” 是因为您使用了不同的同步机制进行读写操作。因为本例中的写操作违反了使用 volatile 的第一个条件,因此不能使用 volatile 安全地实现计数器 —— 您必须使用锁。然而,您可以在读操作中使用 volatile 确保当前值的可见性,因此可以使用锁进行所有变化的操作,使用 volatile 进行只读操作。其中,锁一次只允许一个线程访问值,volatile 允许多个线程执行读操作,因此当使用 volatile 保证读代码路径时,要比使用锁执行全部代码路径获得更高的共享度 —— 就像读-写操作一样。
26.Java能不能不通过构造函数创建对象()
*能
Java创建对象的几种方式: 1. 用new语句创建对象,这是最常见的创建对象的方法。 2. 运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。 3. 调用对象的clone()方法。 4. 运用反序列化手段,调用java.io.ObjectInputStream对象的 readObject()方法。 (1)和(2)都会明确的显式的调用构造函数 ;(3)是在内存上对已有对象的影印,所以不会调用构造函数 ;(4)是从文件中还原类的对象,也不会调用构造函数。
27.下列哪个叙述是正确的()
- A.子类继承父类的构造方法。
- B.abstract类的子类必须是非abstract类。
- C.子类继承的方法只能操作子类继承和隐藏的成员变量。
- D.子类重写或新增的方法也能直接操作被子类隐藏的成员变量。
答案:C
28.下列哪个叙述是正确的()
- A.final类可以有子类。
- B.abstract类中只可以有abstract方法。
- C.abstract类中可以有非abstract方法,但该方法不可以用final修饰。
- D.不可以同时用final和abstract修饰同一个方法。
- E.允许使用static修饰abstract方法。
答案:D
29.当检索一个压缩文件时,首先要建立压缩文件输入流对象,该对象()
- A、以选中的压缩文件为参数
- B、以FileInputStream对象为参数
- C、以InputStreamReader对象为参数
- D、以BufferedReader对象为参数 答案:B 在java.io包中提供了对压缩文件进行操作的能力。它是通过压缩文件输入流与压缩文件输出流来实现的,其分别继承自InflaterInputStream与DeflaterOutputStream。
在创建压缩文件输入流时,其初始化参数是一个FileInputStream类的实例。
30.下列选项中,不属于模块间耦合的是( )
- A.数据耦合
- B.标记耦合
- C.异构耦合
- D.公共耦合 答案:C 模块之间的耦合程度反映了模块的独立性,也反映了系统分解后的复杂程度。 按照耦合程度从弱到强,可以将其分成7级。
分别是非直接耦合、数据耦合、标记耦合、控制耦合、外部耦合、公共耦合和内容耦合。其中没有异构耦合这种方式。
31.什么是LinkedHashSet()
- A、是一个HashSet,保留了对象插入的顺序
- B、是一个HashSet,拥有一个链表的性能
- C、是一个HashSet,能很容易地转换为一个链表
- D、HashSet对象的超类 正确答案:A
扩展:
LinkedHashSet是HashSet的一个“扩展版本”,HashSet并不管什么顺序,不同的是LinkedHashSet会维护“插入顺序”。HashSet内部使用HashMap对象来存储它的元素,而LinkedHashSet内部使用LinkedHashMap对象来存储和处理它的元素。
32.以下两个片段执行结果差异的原因是什么?
片段一: short s=1; s=s+1;
片段二: short s=1; s+=1;
片段一是编译不通过的 ,提示损失精度 。 s=s+1这句先执行s+1然后把结果赋给s,由于1为int类型,所以s+1的返回值是int,编译器自动进行了隐式类型转换,所以将一个int类型赋给short就会出错。 而s+=1不同,由于他是使用+=操作符,在解析的时候s+=1就等价于s = (short)(s+1),也就是s+=1 <=> s = (s的类型)(s+1)。
33.基本数据类型之间的转换规则
- 在一个双操作数以及位运算等算术运算式中,会根据操作数的类型将低级的数据类型自动转换为高级的数据类型,分为以下几种情况:
1)只要两个操作数中有一个是double类型的,另一个将会被转换成double类型,并且结果也是double类型;
2)只要两个操作数中有一个是float类型的,另一个将会被转换成float类型,并且结果也是float类>型;
3)只要两个操作数中有一个是long类型的,另一个将会被转换成long类型,并且结果也是long类型;
4)两个操作数(包括byte、short、int、char)都将会被转换成int类型,并且结果也是int类型。
- 如果低级类型为char型,向高级类型(整型)转换时,会转换为对应ASCII码值,再做其它类型的自动转换。
-
对于byte,short,char三种类型而言,他们是平级的,因此不能相互自动转换,可以使用下述的强制类型转换。 如: >short i=99 ; char c=(char)i; System.out.println("output:"+c);
-
不能在布尔值和任何数字类型间强制类型转换;
-
不同级别数据类型间的强制转换,可能会导致溢出或精度的下降。
-
当字节类型变量参与运算,java作自动数据运算类型的提升,将其转换为int类型。
34.float f=3.4;是否正确?
答:不正确。3.4是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失,因此需要强制类型转换float f =(float)3.4; 或者写成float f =3.4F;。
35.面向对象的特征有哪些方面?
-
抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。
-
继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的重要手段。
-
封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口(可以想想普通洗衣机和全自动洗衣机的差别,明显全自动洗衣机封装更好因此操作起来更简单;我们现在使用的智能手机也是封装得足够好的,因为几个按键就搞定了所有的事情)。
-
多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。如果将对象的方法视为对象向外界提供的服务,那么运行时的多态性可以解释为:当A系统访问B系统提供的服务时,B系统有多种提供服务的方式,但一切对A系统来说都是透明的。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。运行时的多态是面向对象最精髓的东西,要实现多态需要做两件事:1). 方法重写(子类继承父类并重写父类中已有的或抽象的方法);2). 对象造型(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。
36.ava有没有goto?
答:goto 是Java中的保留字,在目前版本的Java中没有使用。
37.&和&&的区别?
- &运算符有两种用法:(1)按位与;(2)逻辑与。
- &&运算符是短路与运算。 >如果&&左边的表达式的值是false,右边的表达式会被直接短路掉,不会进行运算。
38.在JAVA与JSP中要调用一个LINUX上的脚本程序,或WINDOWS上的脚本程序,该怎么写?
答:System.getRuntime().exec("bash < aaa.sh");
39.jsp如何获得客户端的IP地址?
答: request.getRemoteAddr()
40.提交表单后验证没有通过,返回提交页面,如何使原提交页面中的数据保留?
答:javascript的go(-1)可以把上页的表单内容重新显示出来,但password域没有。 疑问,现在不都是异步提交吗?还有同步表单提交的方式?
41.表单成功提交了,点后退显示网页过期
答: 在\<head>\</head>里面加以下代码 : <br> \<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
\<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">
\<META HTTP-EQUIV="Expires" CONTENT="0">
或者在表单页中加上 <br> \<%
response.setHeader("Pragma","no-cache");
response.setHeader("Cache-Control","no-cache");
response.setDateHeader("Expires",0);
\%>
42.WEB上面怎么样连接上一个EXCEL表格?
答: 定义页面得contentType="application/vnd.ms-excel",让页面以excel得形式打开。同样也可以以word得形式打开:application/msword。
43.indexOf()的使用需要注意什么?
答:参数是指从第几位(1,2,3,...)开始搜索,而返回值是指搜索到的位置(0,1,2,3.......)注意是从零算起的。
44.Switch能否用string做参数?
在 Java 7 之前, switch 只能支持byte,short,char,int 或者其对应的封装类,以及 Enum 类型。在JAVA 7中,String 支持被加上了。
45.什么是OOM?
> OOM,全称“Out Of Memory”,翻译成中文就是“内存用完了”,来源于java.lang.OutOfMemoryError。看下关于的官方说明: Thrown when the Java Virtual Machine cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector. 意思就是说,当JVM因为没有足够的内存来为对象分配空间并且垃圾回收器也已经没有空间可回收时,就会抛出这个error(注:非exception,因为这个问题已经严重到不足以被应用处理)
### 46.4. Java的四种引用,强弱软虚,用到的场景 1. 强引用:如果一个对象具有强引用,它就不会被垃圾回收器回收。即使当前内存空间不足,JVM也不会回收它,而是抛出 OutOfMemoryError 错误,使程序异常终止。如果想中断强引用和某个对象之间的关联,可以显式地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象 2. 软引用:在使用软引用时,如果内存的空间足够,软引用就能继续被使用,而不会被垃圾回收器回收,只有在内存不足时,软引用才会被垃圾回收器回收。 3. 弱引用:具有弱引用的对象拥有的生命周期更短暂。因为当 JVM 进行垃圾回收,一旦发现弱引用对象,无论当前内存空间是否充足,都会将弱引用回收。不过由于垃圾回收器是一个优先级较低的线程,所以并不一定能迅速发现弱引用对象. 4. 虚引用:顾名思义,就是形同虚设,如果一个对象仅持有虚引用,那么它相当于没有引用,在任何时候都可能被垃圾回收器回收。
. 利用软引用和弱引用解决OOM问题:用一个HashMap来保存图片的路径和相应图片对象关联的软引用之间的映射关系,在内存不足时,JVM会自动回收这些缓存图片对象所占用的空间,从而有效地避免了OOM的问题 . 通过软可及对象重获方法实现Java对象的高速缓存:比如我们创建了一Employee的类,如果每次需要查询一个雇员的信息。哪怕是几秒中之前刚刚查询过的,都要重新构建一个实例,这是需要消耗很多时间的。我们可以通过软引用和 HashMap 的结合,先是保存引用方面:以软引用的方式对一个Employee对象的实例进行引用并保存该引用到HashMap 上,key 为此雇员的 id,value为这个对象的软引用,另一方面是取出引用,缓存中是否有该Employee实例的软引用,如果有,从软引用中取得。如果没有软引用,或者从软引用中得到的实例是null,重新构建一个实例,并保存对这个新建实例的软引用.
47.解析XML的几种方式的原理与特点:DOM、SAX、PULL
-
DOM:DOM的全称是Document Object Model,也即文档对象模型。在应用程序中,基于DOM的XML分析器将一个XML文档转换成一个对象模型的集合(通常称DOM树),应用程序正是通过对这个对象模型的操作,来实现对XML文档数据的操作。通过DOM接口,应用程序可以在任何时候访问XML文档中的任何一部分数据,因此,这种利用DOM接口的机制也被称作随机访问机制。 > 优点: >1. 形成了树结构,有助于更好的理解、掌握,且代码容易编写。 >2. 解析过程中,树结构保存在内存中,方便修改。 > 缺点: >1. 由于文件是一次性读取,所以对内存的耗费比较大。 >2. 如果XML文件比较大,容易影响解析性能且可能会造成内存溢出。
-
SAX:SAX的全称是Simple APIs for XML,也即XML简单应用程序接口。与DOM不同,SAX提供的访问模式是一种顺序模式,这是一种快速读写XML数据的方式。当使用SAX分析器对XML文档进行分析时,会触发一系列事件,并激活相应的事件处理函数,应用程序通过这些事件处理函数实现对XML文档的访问,因而SAX接口也被称作事件驱动接口。 > 优点: >1. 采用事件驱动模式,对内存耗费比较小。 >2. 适用于只处理XML文件中的数据时。 > 缺点: >1. 编码比较麻烦。 >2. 很难同时访问XML文件中的多处不同数据。
- PULL: 与 SAX 类似,也是基于事件驱动,我们可以调用它的next()方法,来获取下一个解析事件(就是开始文档,结束文档,开始标签,结束标签),当处于某个元素时可以调用XmlPullParser的getAttributte()方法来获取属性的值,也可调用它的nextText()获取本节点的值。
48.java中 sleep 和 wait 的区别
- 来自不同的类 : sleep来自Thread类,是Thread类的静态方法。而wait来自于object类。sleep是Thread的静态方法,那个线程调用的了sleep,那个线程就会休眠.
- 持有锁:这一点很重要,sleep是没有释放锁的,使得该线程仍然占用这系统资源,wait方法则会释放锁,使得其他线程可以使用同步控制块或者方法。sleep 不释放系统资源并且有时间限制,需要调用sleep(milliseconds)来指定休眠时间 wait会释放资源,并且进入线程等待池等待,这个时候其他线程可以占用CPU,直到其他线程调用notify/notifyAll唤醒等待池中的线程,然后进入就绪队列等待系统分配资源
- 使用范围: wait,notify,notifyAll只能在synchronized块中或者synchronied控制的方法中调用。而sleep可以在任何地方调用
49.JAVA 垃圾回收算法?
- 标记回收法:遍历对象图并且记录可到达的对象,以便删除不可到达的对象,一般使用单线程工作并且可能产生内存碎片
- 标记-压缩回收法:前期与第一种方法相同,只是多了一步,将所有的存活对象压缩到内存的一端,这样内存碎片就可以合成一大块可再利用的内存区域,提高了内存利用率
- 复制回收法:把现有内存空间分成两部分,gc运行时,它把可到达对象复制到另一半空间,再清空正在使用的空间的全部对象。这种方法适用于短生存期的对象,持续复制长生存期的对象则导致效率降低。
- 分代回收发:把内存空间分为两个或者多个域,如年轻代和老年代,年轻代的特点是对象会很快被回收,因此在年轻代使用效率比较高的算法。当一个对象经过几次回收后依然存活,对象就会被放入称为老年的内存空间,老年代则采取标记-压缩算法
- 引用计数(最简单古老的方法):指将资源(可以是对象、内存或磁盘空间等等)的被引用次数保存起来,当被引用次数变为零时就将其释放的过程
- 对象引用遍历(现在大多数 jvm 使用的方法):对象引用遍历从一组对象开始,沿着整个对象图上的每条链接,递归确定可到达(reachable)的对象。如果某对象不能从这些根对象的一个(至少一个)到达,则将它作为垃圾收集
50.内存溢出和内存泄露
- 内存溢出(out of memory),是指程序在申请内存时,没有足够的内存空间供其使用
- 内存泄露(menory leak):是指程序在申请内存后,无法释放已申请的内存空间。简单点说及就是,内存中存在可到达(即在有向图中,存在通路可以与其相连)且不再使用的对象。
51.JVM的组成部分
- Class Loader 类加载器
- Execution Engine 执行引擎,执行引擎也叫做解释器(Interpreter) ,负责解释命令,提交操作系统执行。
- Native Interface 本地接口
- Runtime data area 运行数据区
52.synchronized和lock的区别?
- 主要相同点:Lock能完成Synchronized所实现的所有功能。
- > 主要不同点:Lock有比Synchronized更精确的线程予以和更好的性能。 > 1. Synchronized会自动释放锁,但是Lock一定要求程序员手工释放,并且必须在finally从句中释放。 > 2. synchronized修饰方法时 表示同一个对象在不同的线程中 表现为同步队列 如果实例化不同的对象 那么synchronized就不会出现同步效果了。
53.什么是值传递和引用传递?java中是值传递还是引用传递,还是都有?
- 对象被值传递,意味着传递了对象的一个副本。因此,就算是改变了对象副本,也不会影响源对象的值。
- 对象被引用传递,意味着传递的并不是实际的对象,而是对象的引用。因此,外部对引用对象所做的改变会反映到所有的对象上。 >>java中方法参数传递方式是按值传递。 如果参数是基本类型,传递的是基本类型的字面量值的拷贝。 如果参数是引用类型,传递的是该参量所引用的对象在堆中地址值的拷贝。
54..构造器(constructor)是否可被重写(override)?
构造方法是不能被子类重写的,但是构造方法可以重载,也就是说一个类可以有多个构造方法。
55.happens-before规则:
- 程序顺序规则: 一个线程中的每个操作,happens-before于该线程中的任意后续操作。 >在一个线程里,所有的操作都是按顺序的,但是在JMM里其实只要执行结果一样,是允许重排序的,这边的happens-before强调的重点也是单线程执行结果的正确性,但是无法保证多线程也是如此。
- 监视器锁规则:对一个线程的解锁,happens-before于随后对这个线程的加锁.
- volatile变量规则: 对一个volatile域的写,happens-before于后续对这个volatile域的读 > 如果一个线程去写一个变量,同时另外一个线程再去读,那么写入操作一定在读操作之前。
- 传递性:如果A happens-before B ,且 B happens-before C, 那么 A happens-before C
- start()规则: 如果线程A执行操作ThreadBstart()(启动线程B) , 那么A线程的ThreadBstart()happens-before 于B中的任意操作
- join()原则: 如果A执行ThreadB.join()并且成功返回,那么线程B中的任意操作happens-before于线程A从ThreadB.join()操作成功返回。
- interrupt()原则: 对线程interrupt()方法的调用先行发生于被中断线程代码检测到中断事件的发生,可以通过Thread.interrupted()方法检测是否有中断发生
- finalize()原则:一个对象的初始化完成先行发生于它的finalize()方法的开始
56.创建线程有几种不同的方式?你喜欢哪一种?为什么?
有三种方式可以用来创建线程: 1. 继承Thread类 2. 实现Runnable接口 3. 应用程序可以使用Executor框架来创建线程池
57.Comparable和Comparator接口是干什么的?列出它们的区别。
-
Java提供了只包含一个compareTo()方法的Comparable接口。这个方法可以个给两个对象排序。具体来说,它返回负数,0,正数来表明输入对象小于,等于,大于已经存在的对象。
-
Java提供了包含compare()和equals()两个方法的Comparator接口。compare()方法用来给两个输入参数排序,返回负数,0,正数表明第一个参数是小于,等于,大于第二个参数。equals()方法需要一个对象作为参数,它用来决定输入参数是否和comparator相等。只有当输入参数也是一个comparator并且输入参数和当前comparator的排序结果是相同的时候,这个方法才返回true。
58.finalize()方法什么时候被调用?
在释放对象占用的内存之前,且对象的finalize()还没被垃圾收集器调用过,则垃圾收集器会调用对象的finalize()方法。
59.如果对象的引用被置为null,垃圾收集器是否会立即释放对象占用的内存?
不会,在下一个垃圾回收周期中,这个对象将是可被回收的。
60.什么是JDBC?
JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。
61.面向对象的五大基本原则
- 单一职责原则SRP(Single Responsibility Principle) >>一个类应该仅有一个引起它变化的原因,例如:比如在职员类里,将工程师、销售人员、销售经理这些情况都放在职员类里考虑,其结果将会非常混乱,在这个假设下,职员类里的每个方法都要if else判断是哪种情况,从类结构上来说将会十分臃肿,并且上述三种的职员类型,不论哪一种发生需求变化,都会改变职员类!这个是大家所不愿意看到的!
- 开放封闭原则OCP(Open-Close Principle)
- 既开放又封闭,对扩展是开放的,对更改是封闭的!
-
扩展即扩展现行的模块,当我们软件的实际应用发生改变时,出现新的需求,就需要我们对模块进行扩展,使其能够满足新的需求!
-
替换原则(the Liskov Substitution Principle LSP) >* 子类可以替换父类并且出现在父类能够出现的任何地方 >>在这个原则中父类应尽可能使用接口或者抽象类来实现!,子类通过实现了父类接口,能够替父类的使用地方! 通过这个原则,我们客户端在使用父类接口的时候,通过子类实现! 意思就是说我们依赖父类接口,在客户端声明一个父类接口,通过其子类来实现 这个时候就要求子类必须能够替换父类所出现的任何地方,这样做的好处就是,在根据新要求扩展父类接口的新子类的时候而不影响当前客户端的使用!
-
依赖倒置原则(the Dependency Inversion Principle DIP) 具体依赖抽象,上层依赖下层。 > 传统的结构化编程中,最上层的模块通常都要依赖下面的子模块来实现,也称为高层依赖低层! 所以DIP原则就是要逆转这种依赖关系,让高层模块不要依赖低层模块,所以称之为依赖倒置原则!
-
接口分离原则(the Interface Segregation Principle ISP) 模块间要通过抽象接口隔离开,而不是通过具体的类强耦合起来
62.用最有效率的方法计算2乘以8?
答: 2 << 3(左移3位相当于乘以2的3次方,右移3位相当于除以2的3次方)。
63.在Java中,如何跳出当前的多重嵌套循环?
在最外层循环前加一个标记如A,然后用break A;可以跳出多重循环。
64.两个对象值相同(x.equals(y) == true),但却可有不同的hash code,这句话对不对?
答:不对,如果两个对象x和y满足x.equals(y) == true,它们的哈希码(hash code)应当相同。Java对于eqauls方法和hashCode方法是这样规定的: 1. 如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同; 2. 如果两个对象的hashCode相同,它们并不一定相同。
如果违背了上述原则就会发现在使用容器时,相同的对象可以出现在Set集合中,同时增加新元素的效率会大大下降(对于使用哈希存储的系统,如果哈希码频繁的冲突将会造成存取性能急剧下降)。
65.是否可以继承String类?
答:String 类是final类,不可以被继承。
66.char 型变量中能不能存贮一个中文汉字,为什么?
答:char类型可以存储一个中文汉字,因为Java中使用的编码是Unicode(不选择任何特定的编码,直接使用字符在字符集中的编号,这是统一的唯一方法),一个char类型占2个字节(16比特),所以放一个中文是没问题的。
补充:使用Unicode意味着字符在JVM内部和外部有不同的表现形式,在JVM内部都是Unicode,当这个字符被从JVM内部转移到外部时(例如存入文件系统中),需要进行编码转换。所以Java中有字节流和字符流,以及在字符流和字节流之间进行转换的转换流,如InputStreamReader和OutputStreamReader,这两个类是字节流和字符流之间的适配器类,承担了编码转换的任务;对于C程序员来说,要完成这样的编码转换恐怕要依赖于union(联合体/共用体)共享内存的特征来实现了。
67.如何实现对象克隆?
答:有两种方式: 1. 实现Cloneable接口并重写Object类中的clone()方法; 2. 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆,代码如下。 注意:基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常,这种是方案明显优于使用Object类的clone方法克隆对象。让问题在编译的时候暴露出来总是优于把问题留到运行时。
68.Collection和Collections的区别?
答:Collection是一个接口,它是Set、List等容器的父接口;Collections是个一个工具类,提供了一系列的静态方法来辅助容器操作,这些方法包括对容器的搜索、排序、线程安全化等等。
69.事务的ACID是指什么?
- 原子性(Atomic):事务中各项操作,要么全做要么全不做,任何一项操作的失败都会导致整个事务的失败;
- 一致性(Consistent):事务结束后系统状态是一致的;
- 隔离性(Isolated):并发执行的事务彼此无法看到对方的中间状态;
-
持久性(Durable):事务完成后所做的改动都会被持久化,即使发生灾难性的失败。通过日志和同步备份可以在故障发生后重建数据。
-
脏读(Dirty Read):A事务读取B事务尚未提交的数据并在此基础上操作,而B事务执行回滚,那么A读取到的数据就是脏数据。
- 不可重复读(Unrepeatable Read):事务A重新读取前面读取过的数据,发现该数据已经被另一个已提交的事务B修改过了。
- 幻读(Phantom Read):事务A重新执行一个查询,返回一系列符合查询条件的行,发现其中插入了被事务B提交的行。
70.设计模式
共23种设计模式,包括:Abstract Factory(抽象工厂模式),Builder(建造者模式),Factory Method(工厂方法模式),Prototype(原始模型模式),Singleton(单例模式);Facade(门面模式),Adapter(适配器模式),Bridge(桥梁模式),Composite(合成模式),Decorator(装饰模式),Flyweight(享元模式),Proxy(代理模式);Command(命令模式),Interpreter(解释器模式),Visitor(访问者模式),Iterator(迭代子模式),Mediator(调停者模式),Memento(备忘录模式),Observer(观察者模式),State(状态模式),Strategy(策略模式),Template Method(模板方法模式), Chain Of Responsibility(责任链模式)。 1. 工厂模式:工厂类可以根据条件生成不同的子类实例,这些子类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作(多态方法)。当得到子类的实例后,开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例。 2. 代理模式:给一个对象提供一个代理对象,并由代理对象控制原对象的引用。实际开发中,按照使用目的的不同,代理可以分为:远程代理、虚拟代理、保护代理、Cache代理、防火墙代理、同步化代理、智能引用代理。 3. 适配器模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起使用的类能够一起工作。 4. 模板方法模式:提供一个抽象类,将部分逻辑以具体方法或构造器的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法(多态实现),从而实现不同的业务逻辑。 除此之外,还可以讲讲上面提到的门面模式、桥梁模式、单例模式、装潢模式(Collections工具类和I/O系统中都使用装潢模式)等,反正基本原则就是拣自己最熟悉的、用得最多的作答,以免言多必失。
71.什么是线程?
线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速。
72.线程和进程有什么区别?
线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。别把它和栈内存搞混,每个线程都拥有单独的栈内存用来存储本地数据。
73.Thread 类中的start() 和 run() 方法有什么区别?
这个问题经常被问到,但还是能从此区分出面试者对Java线程模型的理解程度。start()方法被用来启动新创建的线程,而且start()内部调用了run()方法,这和直接调用run()方法的效果不一样。当你调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程。
74.Java中Runnable和Callable有什么不同?
Runnable和Callable都代表那些要在不同的线程中执行的任务。Runnable从JDK1.0开始就有了,Callable是在JDK1.5增加的。它们的主要区别是Callable的 call() 方法可以返回值和抛出异常,而Runnable的run()方法没有这些功能。Callable可以返回装载有计算结果的Future对象.
75.Java中CyclicBarrier 和 CountDownLatch有什么不同?
CyclicBarrier 和 CountDownLatch 都可以用来让一组线程等待其它线程。与 CyclicBarrier 不同的是,CountdownLatch 不能重新使用。 CountDownLatch :允许一个或多个线程等待其他线程完成操作。 CyclicBarrier :同步屏障,它可以让一组线程到达一个屏障(也可以叫做同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行。
76.什么是FutureTask?
在Java并发程序中FutureTask表示一个可以取消的异步运算。它有启动和取消运算、查询运算是否完成和取回运算结果等方法。只有当运算完成的时候结果才能取回,如果运算尚未完成get方法将会阻塞。一个FutureTask对象可以对调用了Callable和Runnable的对象进行包装,由于FutureTask也是调用了Runnable接口所以它可以提交给Executor来执行。
77.Java中interrupted 和 isInterrupted方法的区别?
interrupted() 和 isInterrupted()的主要区别是前者会将中断状态清除而后者不会。Java多线程的中断机制是用内部标识来实现的,调用Thread.interrupt()来中断一个线程就会设置中断标识为true。当中断线程调用静态方法Thread.interrupted()来检查中断状态时,中断状态会被清零。而非静态方法isInterrupted()用来查询其它线程的中断状态且不会改变中断状态标识。简单的说就是任何抛出InterruptedException异常的方法都会将中断状态清零。无论如何,一个线程的中断状态有有可能被其它线程调用中断来改变。
78.为什么wait和notify方法要在同步块中调用?
主要是因为Java API强制要求这样做,如果你不这么做,你的代码会抛出IllegalMonitorStateException异常。还有一个原因是为了避免wait和notify之间产生竞态条件。
79.Java中Semaphore是什么?
Java中的Semaphore是一种新的同步类,它是一个计数信号。从概念上讲,信号量维护了一个许可集合。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release()添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore只对可用许可的号码进行计数,并采取相应的行动。信号量常常用于多线程的代码中,比如数据库连接池
80.Java线程池中submit() 和 execute()方法有什么区别?
两个方法都可以向线程池提交任务,execute()方法的返回类型是void,它定义在Executor接口中, 而submit()方法可以返回持有计算结果的Future对象,它定义在ExecutorService接口中,它扩展了Executor接口,其它线程池类像ThreadPoolExecutor和ScheduledThreadPoolExecutor都有这些方法。
81.JDBC的DriverManager是用来做什么的?
- JDBC的DriverManager是一个工厂类,我们通过它来创建数据库连接。
- 当JDBC的Driver类被加载进来时,它会自己注册到DriverManager类里面然后我们会把数据库配置信息传成DriverManager.getConnection()方法,DriverManager会使用注册到它里面的驱动来获取数据库连接,并返回给调用的程序。
82.JDBC的ResultSet是什么?
- 在查询数据库后会返回一个ResultSet,它就像是查询结果集的一张数据表。
- ResultSet对象维护了一个游标,指向当前的数据行。开始的时候这个游标指向的是第一行。如果调用了ResultSet的next()方法游标会下移一行,如果没有更多的数据了,next()方法会返回false。可以在for循环中用它来遍历数据集。
- 默认的ResultSet是不能更新的,游标也只能往下移。也就是说你只能从第一行到最后一行遍历一遍。不过也可以创建可以回滚或者可更新的ResultSet
- 当生成ResultSet的Statement对象要关闭或者重新执行或是获取下一个ResultSet的时候,ResultSet对象也会自动关闭。
- 可以通过ResultSet的getter方法,传入列名或者从1开始的序号来获取列数据。
83.JDBC的DataSource是什么,有什么好处?
DataSource即数据源,它是定义在javax.sql中的一个接口,跟DriverManager相比,它的功能要更强大。我们可以用它来创建数据库连接,当然驱动的实现类会实际去完成这个工作。除了能创建连接外,它还提供了如下的特性: 缓存PreparedStatement以便更快的执行 可以设置连接超时时间 提供日志记录的功能 ResultSet大小的最大阈值设置 * 通过JNDI的支持,可以为servlet容器提供连接池的功能
84.JDBC中存在哪些不同类型的锁?
- 乐观锁——只有当更新数据的时候才会锁定记录。
- 悲观锁——从查询到更新和提交整个过程都会对数据记录进行加锁。
85.JDBC的RowSet是什么,有哪些不同的RowSet?
RowSet用于存储查询的数据结果,和ResultSet相比,它更具灵活性。RowSet继承自ResultSet,因此ResultSet能干的,它们也能,而ResultSet做不到的,它们还是可以。RowSet接口定义在javax.sql包里。 RowSet提供的额外的特性有: 1. 提供了Java Bean的功能,可以通过settter和getter方法来设置和获取属性。RowSet使用了JavaBean的事件驱动模型,它可以给注册的组件发送事件通知,比如游标的移动,行的增删改,以及RowSet内容的修改等。 2. RowSet对象默认是可滚动,可更新的,因此如果数据库系统不支持ResultSet实现类似的功能,可以使用RowSet来实现。 RowSet分为两大类: 1. 连接型RowSet——这类对象与数据库进行连接,和ResultSet很类似。JDBC接口只提供了一种连接型RowSet,javax.sql.rowset.JdbcRowSet,它的标准实现是com.sun.rowset.JdbcRowSetImpl。 2. 离线型RowSet——这类对象不需要和数据库进行连接,因此它们更轻量级,更容易序列化。它们适用于在网络间传递数据。
有四种不同的离线型RowSet的实现:
- CachedRowSet——可以通过他们获取连接,执行查询并读取ResultSet的数据到RowSet里。我们可以在离线时对数据进行维护和更新,然后重新连接到数据库里,并回写改动的数据。
- WebRowSet继承自CachedRowSet——他可以读写XML文档。
- JoinRowSet继承自WebRowSet——它不用连接数据库就可以执行SQL的join操作。
- FilteredRowSet继承自WebRowSet——我们可以用它来设置过滤规则,这样只有选中的数据才可见。
86.在Java中定义一个不做事且没有参数的构造方法的作用
Java程序在执行子类的构造方法之前,如果没有用super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用super()来调用父类中特定的构造方法,则编译时将发生错误,因为Java程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。
87.实现一个线程有哪几种方式,各有什么优缺点,比较常用的是那种?
- 通过继承Thread类,优点:可以直接调用start方法启动。缺点:继承一个类后,不能再继承别的类。需要重写run方法。无返回值。
- 实现Runnable接口,优点:可以实现多个接口或继承一个类;缺点:不能直接启动,要通过构造一个Thread把自己传进去。需要重写run方法,无返回值。
- 实现Callable接口,优点:可以抛出异常,有返回值;缺点:只有jkd1.5以后才支持。需要重写call方法。结合FutureTask和Thread类一起使用,最后调用start启动。
- 一般最常用的是第二种,实现Runnable接口。比较方便,可扩展性高。
88.一般的线程优先级是什么回事,线程优先级高的线程一定会先执行吗?如果不设置优先级的话,那么线程优先级是多少,设置线程优先级用那个函数
线程的优先级就是设置哪个线程优先执行,但也不是绝对的,只是让优先级高的线程优先运行的几率高一些。线程默认是NORM_PRIORITY = 5; 设置优先级使用的是setPriority()函数。
89.Java中的内存划分
- 程序计数器:(线程私有) > 每个线程拥有一个程序计数器,在线程创建时创建, > 指向下一条指令的地址 > * 执行本地方法时,其值为undefined
- 虚拟机栈:(线程私有) > 每个方法被调用的时候都会创建一个栈帧,用于存储局部变量表、操作栈、动态链接、方法出口等信息。局部变量表存放的是:编译期可知的基本数据类型、对象引用类型。<br/> >每个方法被调用直到执行完成的过程,就对应着一个栈帧在虚拟机中从入栈到出栈的过程。
- 在Java虚拟机规范中,对这个区域规定了两种异常情况: > 1. 如果线程请求的栈深度太深,超出了虚拟机所允许的深度,就会出现StackOverFlowError(比如无限递归。因为每一层栈帧都占用一定空间,而 Xss 规定了栈的最大空间,超出这个值就会报错) > 2. 虚拟机栈可以动态扩展,如果扩展到无法申请足够的内存空间,会出现OOM
- 本地方法栈: >本地方法栈与java虚拟机栈作用非常类似,其区别是:java虚拟机栈是为虚拟机执行java方法服务的,而本地方法栈则为虚拟机执使用到的Native方法服务。<br/> >本地方法栈也会抛出StackOverFlowError和OutOfMemoryError。
- 堆:即堆内存(线程共享) > 1. 堆是java虚拟机所管理的内存区域中最大的一块,java堆是被所有线程共享的内存区域,在java虚拟机启动时创建,堆内存的唯一目的就是存放对象实例几乎所有的对象实例都在堆内存分配。 > 2. 堆是GC管理的主要区域,从垃圾回收的角度看,由于现在的垃圾收集器都是采用的分代收集算法,因此java堆还可以初步细分为新生代和老年代。 > 3. Java虚拟机规定,堆可以处于物理上不连续的内存空间中,只要逻辑上连续的即可。在实现上既可以是固定的,也可以是可动态扩展的。如果在堆内存没有完成实例分配,并且堆大小也无法扩展,就会抛出OutOfMemoryError异常。
- 方法区:(线程共享) > 1. 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。 > 2. Sun HotSpot虚拟机把方法区叫做永久代(Permanent Generation),方法区中最重要的部分是运行时常量池。
90.垃圾收集器
- Serial收集器:(串行收集器) >> 这个收集器是一个单线程的收集器,但它的单线程的意义并不仅仅说明它只会使用一个CPU或一条收集线程去完成垃圾收集工作,更重要的是在它进行垃圾收集时,必须暂停其他所有的工作线程(Stop-The-World:将用户正常工作的线程全部暂停掉),直到它收集结束。
- ParNew收集器:Serial收集器的多线程版本(使用多条线程进行GC) >>ParNew收集器是Serial收集器的多线程版本。<br /> 它是运行在server模式下的首选新生代收集器,除了Serial收集器外,目前只有它能与CMS收集器配合工作。CMS收集器是一个被认为具有划时代意义的并发收集器,因此如果有一个垃圾收集器能和它一起搭配使用让其更加完美,那这个收集器必然也是一个不可或缺的部分了。
- ParNew Scanvenge收集器 >> 类似ParNew,但更加关注吞吐量。目标是:达到一个可控制吞吐量的收集器。 停顿时间和吞吐量不可能同时调优。我们一方买希望停顿时间少,另外一方面希望吞吐量高,其实这是矛盾的。因为:在GC的时候,垃圾回收的工作总量是不变的,如果将停顿时间减少,那频率就会提高;既然频率提高了,说明就会频繁的进行GC,那吞吐量就会减少,性能就会降低。<br /> 吞吐量:CPU用于用户代码的时间/CPU总消耗时间的比值,即=运行用户代码的时间/(运行用户代码时间+垃圾收集时间)。比如,虚拟机总共运行了100分钟,其中垃圾收集花掉1分钟,那吞吐量就是99%。
- G1收集器: >>是当今收集器发展的最前言成果之一,直到jdk1.7,sun公司才认为它达到了足够成熟的商用程度。
- CMS收集器:(老年代收集器) >> CMS收集器(Concurrent Mark Sweep:并发标记清除)是一种以获取最短回收停顿时间为目标的收集器。适合应用在互联网站或者B/S系统的服务器上,这类应用尤其重视服务器的响应速度,希望系统停顿时间最短。
posted on 2019-11-05 17:59 qq575654643 阅读(156) 评论(0) 编辑 收藏 举报