Java基础

1、一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?

一个Java源文件中可以定义多个类,但最多只能定义一个public的类,并且public

类的类名必须与源文件名一致。一个文件中可以只有非public类,而且这些类的类名可以跟Java源文件名不同。例如一个Java源文件名中只定义了一个非public类MyClass,而源文件名为Other.java,编译后只会生成一个MyClass.class文件,不会生成Other.class文件。

2、Java有没有goto?

java中的保留字,现在没有在java中使用。

3、说说&和&&的区别。

&和&&都可以用作逻辑与的运算符,&&为短路与运算,&不是短路与运算。另外&可以做为整数的位运算符的与运算。例1:对于if(str != null && !str.equals(“”))表达式,当str为null时,后面的表达式不会执行,所以不会出现NullPointerException。如果将&&改为&,则会抛出NullPointerException异常。当然不建议这样的写法,应该写为if(str != null && ! “”.equals(str)),例2:If(x==33 &++y>0) y会增长,if(x==33 && ++y>0)不会增长

4、在JAVA中如何跳出当前的多重嵌套循环?

1. Break + 标签

2. 直接使用Break

3. 使用方法的return

在Java中,要想跳出多重循环,可以在外面的循环语句前定义一个标号,然后在里

层循环体的代码中使用带有标号的break语句,即可跳出外层循环。例如,

ok: for (int i = 0; i < 10; i++) {

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

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

if (j == 5)

break ok;

}

}

另外,可以让外层的循环条件表达式的结果可以受到里层循环体代码的控制,例如,要在二维数组中查找到某个数字。

int arr[][] ={{1,2,3},{4,5,6,7},{9}};

boolean found = false;

for(int i=0;i<arr.length&& !found;i++) {

for(int j=0;j<arr[i].length;j++){

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

if(arr[i][j]  ==5) {

found = true;

break;

}

}

}

第三种,使用方法的return

public static int test() {

int count = 0;

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

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

count++;

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

if (j == 5) {

return count;

}

}

}

return 0;

}

5、switch语句能否作用在byte上,能否作用在long上,能否作用在String上?

作用在byte、short、char、int,这四种基本类型的封装类对象和枚举,其它基本数据类型及引用数据类型都不能做为case的条件。基本数据类型可以这样简单记忆,能自动加宽到int类型的简单类型和封装类,再加一个enum类型。在JDK 7以后,String类型也可以做为switch的case条件。

6、short s1 = 1; s1 = s1 + 1; 有什么错? short s1 = 1; s1 += 1; 有什么错?

对于short s1 = 1; s1 = s1 + 1; 由于s1+1运算时会自动提升表达式的类型,因为s1是short类型,1是int类型,所以结果自动提升为int型,再赋值给short类型s1时,编译器将报告需要强制转换类型的错误。对于short s1 = 1; s1 += 1; 因为 += 是java语言的内置的运算符,是一种特殊的运算,不会有编译错误,不会出错。

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

char型变量是用来存储Unicode编码的字符的,Unicode编码字符集中包含了汉字。

补充说明:Unicode编码占用两个字节,因此Java的char类型的变量也是占用两个字节。

其它补充:

基本类型 长度(字节) 范围

Byte 1 -128 ~ 127

Short 2 -32768 ~ 32767

Int 4 -2147483648 ~ 2147483647

Long 8 -9223372036854775808 ~ 9223372036854775807

Float 4 -3.4E38 ~ 3.4E38

Double 8 -1.7E308~1.7E308

Char 2 0~65535

boolean 1 true, false

8、用最有效率的方法算出2乘以8等於几?

2 << 3。因为2 * 8 = 2 * 2 ^ 3 = 2 << 3,采用位运算可以提高计算机的运行效率,一个数乘以2的n次方,就可以使用移位运算左移n位。同时如果一个数除以2的n次方,就可以使用移位运算向可移动n位。位运算是CPU直接支持的,效率非常高。

9、请设计一个一百亿的计算器

设计一个百亿计算器,是一件非常麻烦的事情,因为百亿已经超出了int类型的最大值(2147483647,即21.5亿),long值会出现科学计算法的表示,也不太适合直接做这个计算器,需要使用把数字切分成多段,分别进行计算和加合,段与段之间的运算可能会出现越界,需要进行特殊处理,加减法运算相对容易,乘除法就非常困

难了,再加上浮点数运算,更是难上加难。

10、使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?

引用变量不能重新赋值,但是引用指向的对象的内容可以改变

例1:

final StringBuffer a=new StringBuffer("test");

a=new StringBuffer("  ");

有编译错

例2:

final StringBuffer a=new StringBuffer("test");

a.append(“123”);

正确

例3:

有些人想要在传参时,防止参数值发生变化,以下做法是错误的:

public void test(final StringBuffer buffer) {  }

但是这是做不到的,因为buffer的值是可以改变的,方法体中可以使用 buffer.append(“test”)

11、"=="和equals方法究竟有什么区别?

他们的区别主要存在在引用数据类型上‘==’为比较两侧的对象是否同一对象,是用内存地址来比较的‘equals’是对象的方法,默认是用内存地址比较,重写后,主要是用来比较两侧的对象的值是否相同,和equals方法中的实现有关==是运算符,可以两侧都为null,但equals左侧的引用指向的对象不能空,不然有NullPointerException除非需要比较两个引用指向的对象是同一对象,一般都使用equals方法进行比较。尤其是String之类的值对象,另外,常量尽量放在比较的左侧

12、静态变量和实例变量的区别?

在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。

在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。

13、是否可以从一个static方法内部发出对非static方法的调用?

不可以。非static方法即实例对象方法,是属于某个对象的,必须在对象被创建后才能被调用,成员方法的内部其实隐藏着一个this引用;而static方法是属于类对象的,不属于实例对象,因此static方法在执行时,不能获得当前对象的this引用,从而不能直接调用实例对象的方法。

14、Integer与int的区别

int是java提供的8种原始数据类型之一,占用4个字节,直接存值;Integer是引用数据类型,是int的封装类。

1. 默认值:int的默认值为0,Integer的默认值为null。例如考试成绩为0,表示参加了考试,但成绩为0分,但null意味未参加考试。

2. JSP开发中,Integer的默认值为null, 在EL表达式时,文本框显示的值为空白;如果使用int默认值为0,文本框显示的值是0。int不适合在展示层使用。

3. 在Hibernate中,如果将自增ID字段设置成Integer类型,如果值为null,则表示临时对象,保存时,会自动升成ID值。而使用int类型,则需要在hbm映射文件中,设置unsaved-value属性的值为0。

4. Integer提供了许多跟整数运算相关的操作方法,例如与字符串的转换,还定了一些整数的最大值和最小值的转换。

15、Math.round(11.5)等于多少? Math.round(-11.5)等于多少?

Math.round(11.5)的结果为12,Math.round(-11.5)的结果为-11。

Math类提供了三个与取整有关的方法:ceil、floor、round

方法名 英文意思 功能           示例

ceil     天花板   向上取整 ceil(11.5)=12; ceil(-11.5)=-11

floor     地板   向下取整 floor(11.5)=11; cell(-11.5)=-12

round 圆形   四舍五入 Round(11.5)=12; round(-11.5)=-11

16、下面的代码有什么不妥之处?

1. if(username.equals(“xyz”){}

username可能为null,会报空指针错误;改为"xyz".equals(username)

2. int x = 1;

return x==1?true:false;  这个改成return x==1;就可以!

17、请说出作用域public,private,protected,以及不写时的区别

不写修饰符也是一种特殊的修饰符,在java中叫做默认修饰符、default修饰符或friendly修饰符,只是说法不同。

修饰符的作用范围:

private  default  protected    public

同一个类中      可以  可以   可以    可以

同一个包的类中      可以     可以    可以

不同包的子类中           可以      可以

不同包的类中                可以

从以上表中数据可以看出,访问权限的范围自下向上依次增大。特别强调一点,protected修饰符,在同一包内,即使两个类没有继承关系,依然可以互相访问其protected成员属性和成员方法。

18、Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?

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

Overload和Override有共同之处,两个方法的方法名都必须相同,如果不同,既不构成Overload,也不构成Override。

1.Override必须发生在父子类之间,Overload可以不在父子类之间

2.Override的特点:

a)参数列表完全相同:个数相同、类型相同、顺序相同

b)子类的返回值不能比父类的返回值范围大

c)子类方法抛出的异常不能比父类方法抛出的异常范围大

d)修饰符只能为public、protected、friendly,不能为private

e)父子类方法不能使用static修饰

3.重载发生在同一个类或父子类之间,重载中参数列表至少满足个数不同、类型不同、顺序不同中的一个条件,不包含父子类之间的static方法

19、构造器Constructor是否可被override?

构造器不能被重写Override,但可以被重载Overload。如果类没有显示定义构造器,此类也会有一个系统默认的无参构造器,只是方法体是空的。

20、接口是否可继承接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concrete class)?抽象类中是否可以有静态的main方法?抽象类是否可有以内部类?接口是否可以有内部类?

接口可以继承接口;抽象类可以实现(implements)接口;抽象类可以继承具体类;抽象类中可以有静态的main方法;抽象类可有以内部类;接口可以有内部类,但必须是static内部类,但不一定是final的。

抽象类与普通类的区别有以下两点:

1. 不能创建实例对象

2. 允许有abstract方法

抽象类再补充几点:

1. 抽象类可以没有抽象方法

2. 抽象类可以只有私有构造器

3. 抽象类的修饰符不能使用final

接口补充几点:

1. 可以没有任何抽象方法

2. 接口可以有属性,但必须是public static final类型的

3. 接口中可以定义内部类,但内部类必须是public static类型的(可以是抽象类,

不要求是final类型的)

4. 接口类定义不能使用final修饰符

5. 接口类都是abstract的,即使定义类时,没有显示声明

21、写clone()方法时,通常都有一行代码(不是必须有),是什么?

答案:super.clone()

super.clone()是浅度克隆,只是把原对象的对象属性的引用复制一份,基本数据类型的属性是完全复制的。

要想深度clone,就需要把对象中的引用类型的属性递归复制。

22、面向对象的特征有哪些方面

1. 封装,隐藏内部实现,只暴露公共行为

2. 继承,提高代码的重用性

3. 多态,体现现实生活中相似对象的差异性

4. 抽象,抽取现实世界中相似对象的共同点

23、java中实现多态的机制是什么?

Java中通过继承父类或实现接口,实现多态的机机制。

继承指子类继承父类的所有属性、方法、内部类。对于属性而言,如果子类的属性名和父类的属性名相同,则子类会把父类的属性隐藏。属性根据引用来调用,方法根据对象来调用; Java中只有单继承,一个子类只能直接继承一个父类。实现指某类可以实现接口中的部分或所有方法,并能继承接口中的所有的属性和内部类。接口中的属性都为public static final类型,方法都为public类型,内部类都为public static类型。接口可以继承多个接口,实现类可以实现多个接口。

24、abstract class和interface有什么区别?

使用abstract修饰符的class为抽象类,abstract类不能创建的实例对象。

接口(interface)是一种特殊的类,使用interface关键字进行修饰。

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

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

2. 抽象类中可以有普通成员属性,接口中没有普通成员属性;

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

有非抽象的普通方法;

4. 抽象类中的抽象方法的访问类型可以是public,protected和默认类型,但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型;

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

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

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

8. 在应用上也有区别,接口更多的是在系统架构设计方法发挥作用,主要用于定义模块之间的通信契约;而抽象类在代码实现方面发挥作用,可以实现代码的重用

25、abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized,是否可同时是final?

1. abstract的method不可以同时是static的,因为abstract方法是抽象的方法,不能有方法体,是要被子类实现的,而static方法必须有方法体,两者不能在方法上共用。

2. abstract的method不可以同时是native的,native方法表示该方法要用另外一种依赖平台的编程语言实现的,其实是有实现的,只是不是Java代码实现的,所以,它也不能是抽象的,不能与abstract混用。另外native方法可以被子类重写,例如hashCode方法。

3. abstract的method不可以同时是synchronized的,abstract方法只能存在于抽象类或接口中,它不能直接产生对象,而默认synchronized方法对当前对象加锁,而abstract方法只能被子类继承,synchronized不能被继承,抽象方法使用synchronized,没有意思,因此Java不允许抽象方法使用synchronized修饰;synchronized 可以修饰构造器,但一个对象的构造器不可能同时被多个线程调用,这个也是多余的,但是Java不报错,应该是一个BUG。

4. abstract的method不可以同时是final的,因为抽象方法目的是让子类实现,而final方法是不让子类重写,再者从根本上是冲突的,不可以共用。

26、什么是内部类?Static Nested Class和Inner Class的不同。

内部类就是在一个类的内部定义的类。内部可以定义在除参数位置上的任意位置。

1. 静态内部类需要使用static修饰,而普通内部类不能使用static修饰

2. 静态内部类只能定义在和属性同级,普通内部类可以定义在除参数位置以外的任意位置

3. 静态内部类必需有名称,而普通内部类可以是匿名的

4. 静态内部类没有this引用,只此只能访问外部类的静态成员,而普通内部类可以访问外部类的全部成员

5. 静态内部类访问外部类的同名函数时,使用“外部类名.方法名”即可,而普通内部类需要使用“外部类名.this.外部方法”

6. 静态内部类可以定义静态方法,而普通内部类不能定义静态方法,但能定义简单数据类型的静态属性,不能定义引用类型的静态属性。

7. 创建静态内部类的对象的时候,可以直接new 静态内部类名;创建普通内部类的时候,需要先创建外部类的对象,再使用外部类的对象名.new 内部类的类名,例如:object.new MyClass();

27、内部类可以引用它的包含类的成员吗?有没有什么限制?

1. 如果内部类为静态内部类,只能调用外部类的静态成员;如果有重名成员,需要用“外部类名.成员名”访问;不能调用外部类的对象成员。

2. 如果内部类为非静态内部类,则可以调用外部类的所有成员;如果有重名成员,需要使用“外部类名.this.成员名”

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

匿名内部类可以继承其它类,也可以实现接口,但不能显示使用extends和implements关键字。例如:

继承其它类的:

Thread thread = new Thread() {

public void run() {

}

};

实现接口的:

Runnable runnable = new Runnable() {

public void run() {

}

};

29、super.getClass()方法和this.getClass()方法返回对象是否相同?

返回的Class对象是同一对象,都是子类的对象。final方法,不允许重写。想得一个对象的父类对象的引用可以使用object.getClass().getSuperClass()方法。

30、String是最基本的数据类型吗?

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

String是引用数据类型,它的类全名是:java.lang.String,是final类型,且这个类是不可变类,对象被创建后,只能读取不能改写,是线程安全的。字符串的拼接运算可以使用“+”,但结果是新字符串。为了提高字符串的拼接运算效率,我们常用StringBuffer和StringBuilder类。

31、String s = "Hello";s = s + " world!";这两行代码执行后,原始的String对象中的内容到底变了没有?

没有,String类为不可变量,对象被创建后,只能读,不改修改,s = s+ " world!"是装引用s指向了一个新的字符串"Hello world!"。

s = s+ " world!"在JDK1.5以前版本相当于:s = new StringBuffer(String.valueOf(s)).append(" world!").toString();

s = s+ " world!"在JDK1.5及以后版本相当于:s = new StringBuilder(String.valueOf(s)).append(" world!").toString();

32、是否可以继承String类?

String类是final类故不可以继承,而且String为不可变量,只能读不能修改。

补充:

常用的值类大都为final类,例如:Byte、Character、Short、Integer、Long、Float、Double、Boolean、String、StringBuffer、StringBuilder,但Date、BigInteger、BigDecimal都是非final类,但原则上尽量不继承这些类。

33、String s = new String("xyz");创建了几个String Object?二者之间有什么区别?

两个对象。一个是"xyz",为缓冲区对象。另一个是new出来的String对象。这两个对象的值相同,但不是同一个对象。

补充,新建对象有几种方式?

1. 使用new关键字

2. 使用反射,调用newInstance

3. 使用clone方法

4. 使用序列化与反序列化

5. 动态代理(Proxy类和CGLIB)

补充例题1:

String aaa = "aaa";

String bbb = "bbb";

String aaabbb = "aaabbb";

System.out.println("aaa"+"bbb"=="aaabbb"); // true

System.out.println("aaa"+"bbb"==aaa+bbb); // false

System.out.println("aaa"+"bbb"==aaabbb); // true

System.out.println("aaa"+bbb=="aaabbb"); // false

System.out.println("aaa"+bbb==aaabbb); // false

System.out.println(aaa+bbb=="aaabbb"); // false

System.out.println(aaa+bbb==aaabbb); // false

System.out.println("aaa"+"bbb"==aaabbb.intern()); // true

补充例题2:

final String aaa = "aaa";

final String bbb = "bbb";

String aaabbb = "aaabbb";

System.out.println("aaa"+"bbb"=="aaabbb"); // true

System.out.println("aaa"+"bbb"==aaa+bbb); // true

System.out.println("aaa"+"bbb"==aaabbb); // true

System.out.println("aaa"+bbb=="aaabbb"); // true

System.out.println("aaa"+bbb==aaabbb); // true

System.out.println(aaa+bbb=="aaabbb"); // true

System.out.println(aaa+bbb==aaabbb); // true

System.out.println("aaa"+"bbb"==aaabbb.intern()); // true

这两个例子显示了字符串相加产生多少个对象的结果,原因是JVM对字符串相加进行了特殊的优化处理。在第一个例子中:"aaa"+"bbb",+号两侧的值都是字符串常量,因此结果也必然是字符串常量,因此编译时可以优化为"aaabbb",和=号右侧的字符串相同,结果都放在了字符串的常量池,是同一对象。在第一个例子中,aaa和bbb两个变量不是final类型,因此当"aaa"+bbb在JVM编译时,不能确定bbb的值是否在运行时没有被改变过,因此不能进行优化,在运行到此句时,会产生一个新的"aaabbb"字符串对象,而不是池中的字符串对象,得到false。在第二个例子中,aaa和bbb两个变量都是final类型,因此当"aaa"+bbb在JVM编译时,能确定bbb的值,因此可以在编译期进行优化,得到池中的字符串"aaabbb",因此结果为true。

34、String和StringBuffer的区别

这两个类都实现了CharSequence接口。

1. 类型不同,因为不是一个类,也没有继承关系,做参数时不能共用

2. String对象是不可变对象,不能修改值。而StringBuffer是可变对象,能修改值。

3. 拼接字符串时,String会产生新对象,而StringBuffer只是增加新字符,不产生新对象,因此效率高。

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

34.1、StringBuffer和StringBuilder的区别

相同之处,这两类都是可变长的字符串存储类,都实现了CharSequence接口

1. 类型不同,因为不是一个类,也没有继承关系,做参数时不能共用

2. StringBuffer为线程安全类,StringBuilder为线程非安全类

3. StringBuffer性能低,StringBuilder性能高,如果在局部优先使用StringBuilder

4. JDK在1.5之前,字符串相加使用StringBuffer对象,在1.5之后使用StringBuilder对象

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

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

2.用 StingTokenizer ,代码为:

StringTokenizer tokener = new StringTokenizer(s, ",");

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

Integer i = 0;

while (tokener.hasMoreTokens()) {

result[i++] = tokener.nextToken();

}

3.最笨的办法,用String.indexOf()

int index = -1;

int oldIndex = 0;

List<String> ss = new ArrayList<String>();

while ((index = s.indexOf(',', index + 1)) != -1) {

ss.add(s.substring(oldIndex, index));

oldIndex = index + 1;

}

if (s.charAt(s.length() - 1) == ',') {

ss.add("");

}

String[] array = ss.toArray(new String[ss.size()]);

System.out.println(Arrays.toString(array));

36、数组有没有length()这个方法? String有没有length()这个方法?JS的数组有没有length()方法?JS的字符串有没有length()方法?

数组没有length()这个方法,有length的属性。String有有length()这个方法。JS中只有length属性,没有length方法。

37、下面这条语句一共创建了多少个对象:String s="a"+"b"+"c"+"d";

答:产生了一个对象,即"abcd"

对于如下代码:

String s1 = "a";

String s2 = s1 + "b";

String s3 = "a" + "b";

System.out.println(s2 == "ab"); // false

System.out.println(s3 == "ab"); // true

String s = "a" + "b" + "c" + "d";

System.out.println(s == "abcd"); // true s被优化为”abcd”

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

也许你的答案是在return之前,但往更细地说,我的答案是在return中间执行,请看下面程序代码的运行结果:

public class Test {

public static void main(String[] args) {

System.out.println(test());

}

static int test() {

int x = 1;

try {

return x;

}

finally {

++x;

}

}

}

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

1

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

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

public class SmallT {

public static void main(String args[]) {

SmallT t = new SmallT();

int b = t.get();

System.out.println(b);

}

public int get() {

try {

return 1;

} finally {

return 2;

}

}

}

返回的结果是2。

我可以通过下面一个例子程序来帮助我解释这个答案,从下面例子的运行结果中可

以发现,try中的return语句调用的函数先于finally中调用的函数执行,也就是说return语句先执行,finally语句后执行,所以,返回的结果是2。Return并不是让函数马上返回,而是return语句执行后,将把返回结果放置进函数栈中,此时函数并不是马上返回,它要执行finally语句后才真正开始返回。

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

public class Test {

public static void main(String[] args) {

System.out.println(newTest().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语句后执行

40、final, finally, finalize的区别。

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

内部类要访问局部变量,局部变量必须定义成final类型

final int[] number = { 20 };

new Thread() {

@Override

public void run() {

for (int k = 0; k < 20; k++) {

number[0]++;

}

}

}.start();

Thread.sleep(10);

System.out.println(number[0]);

finally是异常处理语句结构的一部分,表示总是执行,用来释放资源。finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。JVM不保证此方法总被调用.

41、运行时异常(Runtime)与检查异常(Checked)有何异同?

异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。运行时异常为编程时的异常,应该在生产环境正常运行状态下不会发生的异常检查异常通常为一种设计模式,表示某处执行时可能因为条件不足而出现异常,程序必须对此进行处理,JVM会提示编程人员捕获或重新抛出异常

42、error和exception有什么区别?

error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出,不可能指望程序能处理这样的情况。exception表示一种设计或实现问题,也就是说,它表示如果程序运行正常,正常情况下从不会发生的情况。

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

异常是指java程序运行时(非编译)所发生的非正常情况或错误。

Java使用面向对象的方式来处理异常,它把程序中发生的每个异常也都分别封装到一个对象中,该对象中包含有异常的信息。

Java可以自定义异常类,所有异常的根类为java.lang.Throwable,Throwable下面又派生了两个子类:Error和Exception。

1.Error表示应用程序本身无法克服和恢复的一种严重问题,程序只有退的份了,例如说内存溢出和线程死锁等系统问题。

2.Exception表示程序还能够克服和恢复的问题,其中又分为运行时异常和检查异常,运行时异常是软件本身缺陷所导致的问题,也就是软件开发人员考虑不周所导致的问题,软件使用者无法克服和恢复这种问题,但在这种问题下还可以让软件系统继续运行或者让软件死掉。例如,数组越界(ArrayIndexOutOfBoundsException),空指针异常(NullPointerException)、类转换异常(ClassCastException);检查异常是运行环境的变化或异常所导致的问题,是用户能够克服的问题,例如,网络断线,硬盘空间不够,发生这样的异常后,程序不应该死掉。

Java为运行时异常和检查异常提供了不同的解决方案,编译器强制检查异常必须try..catch处理或用throws声明继续抛给上层调用方法处理,所以检查异常也称为checked异常,而运行异常可以处理也可以不处理,所以编译器不强制用try..catch处理或用throws声明,所以运行异常也称为Runtime异常。

44、请写出你最常见到的5个RuntimeException。

NullPointerException、ArrayIndexOutOfBoundsException、ClassCastException、IllegelArgumentException、SecurityException。

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

1.Java语言如何进行异常处理见43题

2.throws为向上抛异常,当前方法无法处理此异常,需要上层方法进行处理throw程序出错时,手工抛出异常,最好能把异常进行堆栈式抛出try尝试执行,里面的语句可能出现异常,如出现异常需要处理catch处理try中出现的异常finally在try后执行清理操作,用于释放资源

3.在try中可以抛出异常

46、Java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用?

java5以前,有如下两种:

第一种:

new Thread(){}.start();这表示调用Thread子类对象的run方法,new Thread(){}表示一个Thread的匿名子类的实例对象,子类加上run方法后的代码如下:

new Thread() {

public void run() {

}

}.start();

第二种:

new Thread(new Runnable(){}).start();这表示调用Thread对象接受的Runnable对象的run方法,new Runnable(){}表示一个Runnable的匿名子类的实例对象,runnable的子类加上run方法后的代码如下:

new Thread(new Runnable() {

public void run() {

}

}).start();

从Java5开始,还有如下一些线程池创建多线程的方式:

ExecutorService pool = Executors.newFixedThreadPool(3);

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

pool.execute(new Runable() {

public void run() {

}

});

}

Executors.newCachedThreadPool().execute(new Runable() {

public void run() {

}

});

Executors.newSingleThreadExecutor().execute(new Runable() {

public void run() {

}

});

有两种实现方法,分别使用new Thread()和new Thread(runnable)形式,第一种直接调用thread的run方法,所以,我们往往使用Thread子类,即new SubThread()。第二种调用runnable的run方法。

1.有两种实现方法,分别是继承Thread类与实现Runnable接口。可以的话使用线程池

2.用synchronized关键字修饰同步方法

3.反对使用stop(),是因为它不安全。它会解除由线程获取的所有锁定,而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改它们。结果很难检查出真正的问题所在。suspend()方法容易发生死锁。调用suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定。此时,其他任何线程都不能访问锁定的资源,除非被"挂起"的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就会造成死锁。所以不应该使用suspend(),而应在自己的Thread类中置入一个标志,指出线程应该活动还是挂起。若标志指出线程应该挂起,便用wait()命其进入等待状态。若标志指出线程应当恢复,则用一个notify()重新启动线程。

47、sleep()和 wait()有什么区别?

1. sleep是在Thread类定义的,wait是在Object类定义的

2. sleep有两个重载方法,wait有三个重载方法

3. sleep能自动唤醒,wait有参数的方法能自动唤醒,但无参数的重载方法不能自动唤醒,需要使用notify/notifyAll进行手动唤醒

4. sleep挂起时,不释放锁资源,wait挂起时,会释放锁资源

5. sleep调用时,不需要放在synchronized内,wait需要放在synchronized内

6. sleep一般不会产生死锁,但是wait可能会产生死锁

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

同步是指所有操作串行化执行,顺序不能改变,前一操作未完成,后个操作不执行。

异步是指所有操作可以并行执行,顺序无关。

例如寄信

同步:如果没有寄完,不能吃饭,邮递员10天后送到,发送人被饿死

异步:寄出后可以立即吃饭,邮递员送完后,通知发送人送信结果。

如果强调执行顺序的话,用同步。如果顺序无关,则可以用异步。

异步执行效率比同步高。该用同步时,如果用了异步,结果可能会出现不一致。

49、多线程有几种实现方法?同步有几种实现方法?

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

同步的实现方面有五种,分别是synchronized、wait与notify、sleep、suspend、joinsynchronized: 一直持有锁,直至执行结束

wait():使一个线程处于等待状态,并且释放所持有的对象的lock,需捕获异常。

sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,需捕获异常,不释放锁。

notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。

notityAll():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。

50、启动一个线程是用run()还是start()?

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

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

如果其它方法中使用当前对象作为锁对象,则不能;

如果其它方法中没有使用当前对象作为锁对象,则能。

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

在多任务操作系统中,为了提高CPU的利用率,可以使用多进程编程。但对进程通信比较困难,进程间数据不能共享,因此可以使用多线程编程。一个进程至少包含一个主入口线程。单个CPU,在同一时间只能处理一个线程的数据,但是操作系统的任务调度非常快,人眼无法识别,感觉上是多个线程同时执行。有的线程可以已经用完CPU,正在作磁盘操作,此时并不使用CPU,可以让出CPU资源给其它线程使用,提高效率。线程有生命周期及相关关系和对应方法见46题。

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

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

主要不同点:

1.更好的语义

2.更高性能

3.synchronized自动释放锁,Lock手动释放,并且必须在finally从句中释放。

4.功能强大,可以用tryLock方法可以非阻塞方式去拿锁

举例说明(对下面的题用lock进行了改写):

package com.huawei.interview;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

public class ThreadTest {

private int j;

private Lock lock = newReentrantLock();

public static void main(String[] args) {

ThreadTest tt = new ThreadTest();

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

new Thread(tt.new Adder()).start();

new Thread(tt.new Subtractor()).start();

}

}

private class Subtractor implements Runnable {

@Override

public void run() {

while (true) {

lock.lock();

try {

System.out.println("j--=" + j--);

} finally {

lock.unlock();

}

}

}

}

private class Adder implements Runnable {

@Override

public void run() {

while (true) {

lock.lock();

try {

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

} finally {

lock.unlock();

}

}

}

}

}

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

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

public class ThreadTest1 {

private int j;

public static void main(String args[]) {

ThreadTest1 tt = new ThreadTest1();

Inc inc = tt.new Inc();

Dec dec = tt.new Dec();

for (inti = 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 (inti = 0; i < 100; i++) {

inc();

}

}

}

class Dec implements Runnable {

public void run() {

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

dec();

}

}

}

}

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

public class ThreadTest {

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

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

MainThread main = new MainThread();

main.start();

main.join();

}

}

}

class MainThread extends Thread {

@Override

public void run() {

SubThread sub = new SubThread();

sub.start();

try {

sub.join();

} catch (InterruptedException e) {

// LOG

}

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

System.out.println("main: " + i);

}

}

}

class SubThread extends Thread {

@Override

public void run() {

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

System.out.println("sub: " + i);

}

}

}

57、介绍Collection框架的结构

Iterable

Collection

List

ArrayList

LinkedList

Vector

Stack

Set

HashSet

SortedSet

TreeSet

Map

SortedMap

TreeMap

Hashtable

Properties

HashMap

LinkedHashMap

Collections,不属于集合,是集合类的工具类

Arrays,不属于集合类,是数据对象的工具类

58、Collection框架中实现比较要实现什么接口

Comparable/Comparator

59、ArrayList和Vector的区别

1. 线程同步,Vector线程安全,ArrayList线程不安全

2. 效率问题,Vector效率低,ArrayList效率高

3. 增长数量,Vector以1.5倍增长,ArrayList以2倍增长

60、HashMap和Hashtable的区别

1. 线程同步,Hashtable线程安全,HashMap线程不安全

2. 效率问题,Hashtable效率低,HashMap效率高

3. HashMap可以使用null作为key,Hashtable不可以使用null为key

4. HashMap使用的是新实现,继承AbstractMap,而Hashtable是继承Dictionary类,实现比较老

5. Hash算法不同,HashMap的hash算法比Hashtable的hash算法效率高

6. HashMap把Hashtable的contains方法去掉了,改成containsValue和containsKey。因为contains方法容易让人引起误解。

7. 取值不同,HashMap用的是Iterator接口,而Hashtable中还有使用Enumeration接口

61、List和 Map区别?

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

1.List有重复值,Map没有重复key,但可以有重复值

2.List有序,Map不一定有序

3.List只能存单列值,Map可以存双列值

62、List, Set, Map是否继承自Collection接口?

List、Set是,Map不是

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

List使用get(index)取值,也可以使用Iterator、toArray取值

Set只能通过Iterator、toArray取值

Map取值使用get(key)取值,也可以使用keySet取键值集合,也可使用values取值集合,entrySet取全部键值对映射。

64、说出ArrayList,Vector, LinkedList的存储性能和特性

1. ArrayList和Vector使用数组存储元素;LinkedList使用链表存储元素

2. ArrayList和Vector插入删除数据时,需要搬运数据,效率较差;LinkedList使用链表,不需要搬运数据,效率高

3. ArrayList和Vectory查询时,按数组下标查询,不需要遍历,效率高;LinkedList需要遍历,查询效率底

4. ArrayList和Vector的区别见59条

65、去掉一个Vector集合中重复的元素

1. 自行遍历,用另外一个Vector来判断是否有重复

2. 用Set(TreeSet或HashSet)来去重

3. 用Apache的CollectionUtil工具类去重

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

66、Collection和 Collections的区别。

Collection是集合类的上级接口,继承与他的接口主要有Set和List.

Collections是针对集合类的一个工具类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。

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

Set里的元素是不能重复的,元素重复与否视具体情况而定:

1. HashSet使用equals比较

2. TreeSet使用compareTo进行比较

68、你所知道的集合类都有哪些?主要方法?

最常用的集合类接口是List 和 Map。

List的具体实现包括ArrayList、Vector、LinkedList,它们是可变大小的列表,比较适合构建、存储和操作任何类型对象的元素列表。List适用于按数值索引访问元素的情形。

Set的具体实现包括HashSet和TreeSet,它们也是可变大小集合,但不适合用索引取值。

Map 提供了一个更通用的元素存储方法。Map集合类用于存储元素对(称作"键"和"值"),其中每个键映射到一个值。

ArrayList/Vector、LinkedList

HashSet/TreeSet

Properties/HashTable/TreeMap/HashMap

List的主要方法有:

add、get、remove、set、iterator、contains、addAll、removeAll、indexOf、toArray、clear、isEmpty

Set的主要方法有:

add、remove、iterator、contains、addAll、removeAll、toArray、clear、isEmpty

Map的主要方法有:

put、get、keySet、values、entrySet、clear、remove、isEmpty

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

1. equals等,hashCode同,因此重写equals方法必须重写hashCode

2. hashCode等,equals不一定同,但hashCode最好散列化

3. 任何对象equals null都得false

4. 没有继承关系的两个类,equals都得false

5. 重写equals方法的类最好是值类,即不可变

6. 如果A对象equals B对象,B对象equals C对象,则A对象equals C对象

70、TreeSet里面放对象,如果同时放入了父类和子类的实例对象,那比较时使用的是父类的compareTo方法,还是使用的子类的compareTo方法,还是抛异常!

1. 如果子类重新实现了Comparable,且比较时全部使用父类的引用和属性,则不会出错

2. 如果子类重新实现了Comparable,且比较时使用了子类的引用和属性,出异常

3. 子类没有重新实现Comparable,则不会了出错。

用哪个对象比较,则调用哪个对象的comparaTo方法

71、说出一些常用的类,包,接口,请各举5个

要让人家感觉你对JavaEE开发很熟,所以,不能仅仅只列core java中的那些东西,要多列你在做ssh项目中涉及的那些东西。就写你最近写的那些程序中涉及的那些类。

常用的类:BufferedReader,BufferedWriter,FileReader,FileWirter,String,Integer,java.util.Date,System,Class,List,HashMap

常用的包:java.lang,java.io,java.util,java.sql,javax.servlet,org.apache.strtuts.action,org.hibernate, org.springframework

常用的接口:List,Map,Document,NodeList,Servlet,HttpServletRequest,HttpServletResponse,HttpSession,Action(Struts),Transaction(Hibernate) ,Session(Hibernate),ApplicationContext(Spring),FactoryBean(Spring)

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

字节流,字符流。字节流继承于InputStream、OutputStream,字符流继承于Reader、Writer。在java.io包中还有许多其他的流,主要是为了提高性能和使用方便。ileInputStream、FileReader、ByteArrayInputStream、CharArrayReader、BufferedInputStream、BufferedReader、ZipInputStream、PrintStream、StringReader、ObjectInputStream、RandomAccessFile(不属于流,但像流)

73、字节流与字符流的区别

字节流是按字节读取或写入设备,但字符流是以字符为单位读取或写入设备。

如果是二进制文件,需要用字节流读取。一般来说,字符流只处理文本文件。在设备中,大多数情况是以字节形式存储数据的,因此字符流通过需要传入字节流当参数。

74、什么是java序列化,如何实现java序列化?或者请解释Serializable接口的作用。

序列化是把内存Java对象保存到存储介质中,反序列化就是把存储介质中的数据转化为Java对象。Java通过ObjectInputStream和ObjectOutputStream实现序列化和反序列化。需要进行序列化的对象的类必须实现Serializable接口,通常情况下需要满足以下条件:

1. 强烈建议手动生成serialVersionUID常量

2. 如果需要加解密的话,需要实现两个方法readObject和writeObject方法

3. 如果使用Hibernate二级缓存或其它缓存服务器的话,对象必须是可序列化的

4. 如果需要远程调用对象或传值的话,则对像需要序列化

5. 序列化类的可序列化成员必须也是可序列化的,不需要序列化的属性用transient修饰

75、描述一下JVM加载class文件的原理机制?

1. 查找当前ClassLoader中是否有此class的类对象,有则返回

2. 若没有的话,向上递归所有的父ClassLoader中有无此class类对象,有则返回

3. 若还没有,查找BootstrapClassLoader中有无此class类对象,有则返回

4. 若还没有的话,使用findClass或resolveClass加载类对象

a. 读取class二进制文件

b. 根据字节数组生成Class对象

c. 缓存到当前ClassLoader中

JVM加载class对象是懒加载,按需加载

76、heap和stack有什么区别。

Java的内存分为两类,一类是栈内存,一类是堆内存。

栈中存储的是当前线程的方法调用、基本数据类型和对象的引用,栈是有序的。

堆中存储的是对象,堆是无序的。

方法中的局部变量使用final修饰后,放在堆中,而不是栈中。

77、GC是什么?为什么要有GC?

GC是垃圾回收的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。线程对象在没有终止前,即使没有任何引用,也不会被垃圾回收。只能建议JVM回收内存,不能强制,可以使用System.gc()建议执行。

GC有三种方式,串行回收、并行回收、混合回收。

78、垃圾回收的优点和原理。并考虑2种回收机制。

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

1.按时间轮询,把没有引用的对象进行回收

2.按内存的使用量超不超过报警值进行回收

3.按CPU空闲时间进行回收

4.程序建议JVM进行垃圾回收

GC有三种方式,串行回收、并行回收、混合回收。

79、垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?

对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的"。当GC确定一些对象为"不可达"时,GC就有责任回收这些内存空间。可以。程序员可以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。

80、什么时候用assert。

assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都支持这种机制。在实现中,assertion就是在程序中的一条语句,它对一个boolean表达式进行检查,一个正确程序必须保证这个boolean表达式的值为true;如果该值为false,说明程序已经处于不正确的状态下,assert将给出警告或退出。一般来说,assertion用于保证程序最基本、关键的正确性。assertion检查通常在开发和测试时开启。为了提高性能,在软件发布后,assertion检查通常是关闭的。

81、java中会存在内存泄漏吗,请简单描述。

会,原因:

如果对象被集合类引用时,如果只是添加,而不删除,会引起内存泄漏,严重时会发出内存溢出。Java中的内存泄露的情况:长生命周期的对象持有短生命周期对象的引用就很可能发生内存泄露 内存泄露的另外一种情况:当一个对象被存储进HashSet或HashMap中以后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存储进HashSet集合中时的哈希值就不同了,在这种情况下,即使在contains方法使用该对象的当前引用作为的参数去HashSet集合中检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中单独删除当前对象,造成内存泄露。

82、能不能自己写个类,也叫java.lang.String?

可以,如果非要实现java.lang.String,需要自已写ClassLoader,不然JVM优先加载默认rt.jar中的java.lang.String。可以,但在应用的时候,需要用自己的类加载器去加载,否则,系统的类加载器永远只是去加载rt.jar包中的那个java.lang.String。由于在tomcat的web应用程序中,都是由webapp自己的类加载器先自己加载WEB-INF/classess目录中的类,然后才委托上级的类加载器加载,如果我们在tomcat的web应用程序中写一个java.lang.String,这时候Servlet程序加载的就是我们自己写的java.lang.String,但是这么干就会出很多潜在的问题,原来所有用了java.lang.String类的都将出现问题。虽然java提供了endorsed技术,可以覆盖jdk中的某些类,但是,能够被覆盖的类是有限制范围,反正不包括java.lang这样的包中的类。(下面的例如主要是便于大家学习理解只用,不要作为答案的一部分,否则,人家怀疑是题目泄露了)例如,运行下面的程序:

package java.lang;

public class String {

public static void main(String[] args) {

System.out.println("string");

}

}

报告的错误如下:

java.lang.NoSuchMethodError:main

Exception inthread "main"

这是因为加载了jre自带的java.lang.String,而该类中没有main方法。

83. Java代码查错

1.

abstract class Name {

private String name;

public abstract boolean isStupidName(String name) {}

}

大侠们,这有何错误?

答案: 错。abstract method必须以分号结尾,且不带花括号。

2.

public class Something {

void doSomething() {

private String s = "";

int l = s.length();

}

}

有错吗?

答案: 错。局部变量前不能放置任何访问修饰符 (private,public,和protected)。final可以用来修饰局部变(final如同abstract和strictfp,都是非访问修饰符,strictfp只能修饰class和method而非variable)。

3.

abstract class Something {

private abstract String doSomething();

}

这好像没什么错吧?

答案: 错。abstract的methods不能以private修饰。abstract的methods就是让子类

implement(实现)具体细节的,怎么可以用private把abstractmethod封锁起来呢? (同理,abstract method前不能加final)。

4.

public class Something {

public int addOne(final int x) {

return ++x;

}

}

这个比较明显。

答案: 错。int x被修饰成final,意味着x不能在addOne method中被修改。

5.

public class Something {

public static void main(String[] args) {

Other o = new Other();

new Something().addOne(o);

}

public void addOne(final Other o) {

o.i++;

}

}

class Other {

public int i;

}

和上面的很相似,都是关于final的问题,这有错吗?

答案: 正确。在addOne method中,参数o被修饰成final。如果在addOne method里

我们修改了o的reference(比如: o = new Other();),那么如同上例这题也是错的。但这里修改的是o的member vairable(成员变量),而o的reference并没有改变。

6.

class Something {

int i;

public void doSomething() {

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

}

}

有什么错呢? 看不出来啊。

答案: 正确。输出的是"i = 0"。int i属於instant variable (实例变量,或叫成员变量)。instant variable有default value。int的default value是0。

7.

class Something {

final int i;

public void doSomething() {

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

}

}

和上面一题只有一个地方不同,就是多了一个final。这难道就错了吗?

答案: 错。final int i是个final的instant variable (实例变量,或叫成员变量)。final的instant variable没有default value,必须在constructor (构造器)结束之前被赋予一个明确的值。可以修改为"final int i =0;"。

8.

public class Something {

public static void main(String[] args) {

Something s = new Something();

System.out.println("s.doSomething() returns " +

doSomething());

}

public String doSomething() {

return "Do something ...";

}

}

看上去很完美。

答案: 错。看上去在main里call doSomething没有什么问题,毕竟两个methods都在同一个class里。但仔细看,main是static的。static method不能直接call non-staticmethods。可改成"System.out.println("s.doSomething()returns " + s.doSomething());"。同理,static method不能访问non-static instant variable。

9.

此处,Something类的文件名叫OtherThing.java

class Something {

private static void main(String[] something_to_do) {

System.out.println("Dosomething ...");

}

}

这个好像很明显。

答案: 正确。从来没有人说过Java的Class名字必须和其文件名相同。但public class的名字必须和文件名相同,如果main方法是public,则为程序的入口方法,而为private只是普通的静态方法而已。

10.

interface A {

int x = 0;

}

class D {

int x = 2;

}

class B extends D {

int x = 1;

}

class C extends B implements A {

public void pX() {

System.out.println(super.x);

}

public static void main(String[] args) {

new C().pX();

}

}

答案:错误。在编译时会发生错误(错误描述不同的JVM有不同的信息,意思就是未

明确的x调用,两个x都匹配(就象在同时import java.util和java.sql两个包时直接声明Date一样)。对于父类的变量,可以用super.x来明确,而接口的属性默认隐含为 public static final.所以可以通过A.x来明确。

11.

interface Playable {

void play();

}

interface Bounceable {

void play();

}

interface Rollable extends Playable, Bounceable {

Ball ball = new Ball("PingPang");

}

class Ball implements Rollable {

private String name;

public String getName() {

return name;

}

public Ball(String name) {

this.name = name;

}

public void play() {

ball = new Ball("Football");

System.out.println(ball.getName());

}

}

这个错误不容易发现。

答案: 错。"interfaceRollable extends Playable, Bounceable"没有问题。interface可继承多个interfaces,所以这里没错。问题出在interface Rollable里的"Ball ball =new Ball("PingPang");"。任何在interface里声明的interface variable (接口变量,也可称成员变量),默认为public static final。也就是说"Ball ball = new Ball("PingPang");"实际上是"public staticfinal Ball ball = new Ball("PingPang");"。在Ball类的Play()方法中,"ball = newBall("Football");"改变了ball的reference,而这里的ball来自Rollable interface,Rollable interface里的ball是public static final的,final的object是不能被改变reference的。因此编译器将在"ball = newBall("Football");"这里显示有错。

二.算法与编程

1、编写一个程序,将a.txt文件中的单词与b.txt文件中的单词交替合并到c.txt文件中,a.txt文件中的单词用回车符分隔,b.txt文件中用回车或空格进行分隔。

本题考核的是使用字符流读写文件,并能切分字符串

package com.bwie.interview;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintStream;

import java.util.StringTokenizer;

public class AnswerB01 {

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

StringTokenizer tokenizer1 = getTokenzer("/a.txt");

StringTokenizer tokenizer2 = getTokenzer("/b.txt");

PrintStream out = new PrintStream("C:/c.txt");

while (tokenizer1.hasMoreTokens() &&

tokenizer2.hasMoreTokens()) {

out.println(tokenizer1.nextToken());

out.println(tokenizer2.nextToken());

}

out.close();

}

private static StringTokenizer getTokenzer(String fileName)

throws IOException {

InputStreamReader reader = new InputStreamReader

(AnswerB01.class.getResourceAsStream(fileName));

StringBuilder builder = new StringBuilder(1000);

int length = -1;

char[] cs = new char[1024];

while ((length = reader.read(cs)) != -1) {

builder.append(cs, 0, length);

}

reader.close();

return new StringTokenizer(builder.toString());

}

}

2、编写一个程序,将d:\java目录下的所有.java文件复制到d:\jad目录下,并将原来文件的扩展名从.java改为.jad。

答:listFiles方法接受一个FileFilter对象,这个FileFilter对象就是过虑的策略对象,不同的人提供不同的FileFilter实现,即提供了不同的过滤策略。

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.FilenameFilter;

import java.io.IOException;

public class AnswerB02 {

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

File sourceFolder = new File("D:/java");

File[] files = sourceFolder.listFiles(new JavaFileFilter

());

for (File file : files) {

String absolutePath = file.getName();

String targetFile = "D:/jad/" +

absolutePath.substring(0, absolutePath.length() - 5) + ".jad";

copy(file, new File(targetFile));

}

}

private static void copy(File source, File target) throws IOException {

FileInputStream input = new FileInputStream(source);

FileOutputStream out = new FileOutputStream(target);

int length = -1;

byte[] bs = new byte[1024];

while ((length = input.read(bs)) != -1) {

out.write(bs, 0, length);

}

input.close();

out.close();

}

private static final class JavaFileFilter implements FilenameFilter {

@Override

public boolean accept(File dir, String name) {

return name.endsWith(".java");

}

}

}

3、编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串,但要保证汉字不被截取半个,如“我ABC”,4,应该截取“我AB”,输入“我ABC汉DEF”,6,应该输出“我ABC”,而不是“我ABC+汉的半个”。

import java.io.IOException;

public class AnswerB03 {

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

String s = "我ABC汉DEF";

System.out.println(substring(s, 6));

}

public static String substring(String s, int length) {

char[] cs = s.toCharArray();

StringBuilder builder = new StringBuilder();

int count = 0;

for (char c : cs) {

if (isAsc(c)) {

count++;

} else {

count += 2;

}

if (count > length) {

break;

}

builder.append(c);

}

return builder.toString();

}

public static boolean isAsc(char c) {

return c < 128;

}

}

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

String content = "中文字符english中文字符&&&****$%#abc";

Map<Character, Integer> map = new HashMap<Character, Integer>();

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

char c = content.charAt(i);

Integer count = map.get(c);

if (count == null) {

count = 0;

}

count = count + 1;

map.put(c, count);

}

Set<Entry> entries = map.entrySet();

for (Entry entry : entries) {

system.out.println(entry.getkey() + ":" + entry.getValue());

}

如果一串字符如"中文字符english中文字符123456"要分别统计英文字符的数量,中文字符的数量,和数字字符的数量,假设字符中没有中文字符、英文字符、数字字符之外的其他特殊字符。

int engishCount;

int chineseCount;

int digitCount;

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

char ch = str.charAt(i);

if (ch >= '0' && ch <= '9' || ch == '.') {

digitCount++;

} else if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))

{

engishCount++;

} else {

chineseCount++;

}

}

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

1,张三,28

2,李四,35

3,张三,28

4,王五,35

5,张三,28

6,李四,35

7,赵六,28

8,田七,35

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.util.ArrayList;

import java.util.Collections;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import java.util.Set;

public class AnswerB06 {

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

BufferedReader reader = new BufferedReader(new

InputStreamReader(new FileInputStream("/person.txt")));

Map<String, Integer> nameMap = new HashMap<String,

Integer>();

String line = null;

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

String[] segments = line.split(",", -1);

String name = segments[1];

Integer count = nameMap.get(name);

if (count == null) {

count = 0;

}

count++;

nameMap.put(name, count);

}

reader.close();

List<PersonCount> personCounts = new

ArrayList<PersonCount>();

Set<String> names = nameMap.keySet();

for (String name : names) {

PersonCount personCount = new PersonCount();

personCount.name = name;

personCount.count = nameMap.get(name);

personCounts.add(personCount);

}

Collections.sort(personCounts);

for (PersonCount personCount : personCounts) {

System.out.println(personCount.name + "=" +

personCount.count);

}

}

static class PersonCount implements Comparable<PersonCount> {

public String name;

public int count;

@Override

public int compareTo(PersonCount o) {

return count - o.count;

}

}

}

7、写一个Singleton出来。

第一种:饱汉模式

public class SingleTon {

private SingleTon() {

}

// 实例化放在静态代码块里可提高程序的执行效率,但也可能更占用空间

private final static SingleTon instance = new SingleTon();

public static SingleTon getInstance() {

return instance;

}

}

第二种:饥汉模式

public class SingleTon {

private SingleTon() {

}

private static SingleTon instance;

public static synchronized SingleTon getInstance() {

if (instance == null) {

instance = new SingleTon();

}

return instance;

}

}

第三种:用枚举

public enum SingleTon {

ONE;

}

第四种:双重校验

public class SingleTon {

private SingleTon() {

}

private static SingleTon instance;

public static SingleTon getInstance() {

if (instance == null) {

synchronized(SingleTon.class) {

if (instance == null) {

instance = new SingleTon();

}

}

}

return instance;

}

}

第五种:全部静态方法、定义一个类,它的所有的方法都是静态方法,且构造器是私有的一般认为第一种形式要更加安全些

8、递归算法题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);

}

public static void doubleNum(int n) {

if (n > 5000) {

System.out.println(n);

return;

}

doubleNum(n * 2);

System.out.println(n);

}

9、递归算法题2

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

import java.util.Date;

public class RecursionDemo {

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;

}

}

10、排序都有哪几种方法?请列举。用JAVA实现一个快速排序。

常用的排序算法有冒泡排序、选择排序和快速排序。下面给出冒泡排序和快速排序的例子。

冒泡排序:

private static void bubbleSort(int[] array) {

for (int i = 1; i < array.length; i++) {

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

if (array[i] < array[j]) {

int temp = array[i];

array[i] = array[j];

array[j] = temp;

}

}

}

}

快速排序:

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

}

}

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

public class AnswerB11 {

public static void main(String[] args) {

int[] array = { 2, 25, 21, 63, 234, 83 };

reverse(array);

System.out.println(Arrays.toString(array));

}

private static void reverse(int[] array) {

for (int i = 0; i < array.length / 2; i++) {

int temp = array[i];

array[i] = array[array.length - 1 - i];

array[array.length - 1 - i] = temp;

}

}

}

12、金额转换,阿拉伯数字的金额转换成中国传统的形式如:(¥1011)->(一千零一拾一元整)输出。

public class AnswerB12 {

private static final char[] data = {

'零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'

};

private static final char[] units = {

'元', '拾', '佰', '仟', '万', '拾', '佰', '仟', '亿'

};

public static void main(String[] args) {

System.out.println(toUpcaseMoney(convert(100215)));

}

private static String toUpcaseMoney(String money) {

return new StringBuilder(money).toString()

.replaceAll("零[拾佰仟]", "零")

.replaceAll("零+万", "万")

.replaceAll("零+元", "元")

.replaceAll("零+", "零");

}

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

}

}

14、以最快的效率找出一个数组中第二大的数

不能使用排序,然后取第二大数,原因有两个,第一个不是最快的效率,第二个是因为题目只是要求找出第二大的数,并没有要求破坏数据。一般情况下尽量不要破坏原始数据。

public class SecondMaxNumber {

public static void main(String[] args) {

int[] nums = {2, 10, 6, 68, 13, 26, 98, 5};

int firstMax = nums[0];

int secondMax = nums[0];

for (int i = 1; i < nums.length; i++) {

int num = nums[i];

if (num < secondMax) {

continue;

}

if (num > firstMax) {

secondMax = firstMax;

firstMax = num;

continue;

}

secondMax = num;

}

System.out.println(secondMax);

}

}

一、JDK常用的包

 java.lang: 这个是系统的基础类,比如String、Math、Integer、System和Thread,提供常用功能。

 java.io: 这里面是所有输入输出有关的类,比如文件操作等

 java.net: 这里面是与网络有关的类,比如URL,URLConnection等。

 java.util : 这个是系统辅助类,特别是集合类Collection,List,Map等。

 java.sql: 这个是数据库操作的类,Connection, Statememt,ResultSet等

三、Java多态的具体体现

面向对象编程有四个特征:抽象,封装,继承,多态。

多态有四种体现形式:

1. 接口和接口的继承。

2. 类和类的继承。

3. 重载。

4. 重写。

其中重载和重写为核心。

重载:重载发生在同一个类中,在该类中如果存在多个同名方法,但是方法的参数类型和个数不一样,那么说明该方法被重载了。

重写:重写发生在子类继承父类的关系中,父类中的方法被子类继承,方法名,返回值类型,参数完全一样,但是方法体不一样,那么说明父类中的该方法被子类重写了。

四、StringBuffer StringBuilder String 区别

String       字符串常量   不可变  使用字符串拼接时是不同的2个空间

StringBuffer  字符串变量   可变   线程安全    字符串拼接直接在字符串后追加

StringBuilder 字符串变量   可变   非线程安全  字符串拼接直接在字符串后追加

1.StringBuilder执行效率高于StringBuffer高于String.

2String是一个常量,是不可变的,所以对于每一次+=赋值都会创建一个新的对象,StringBuffer和StringBuilder都是可变的,当进行字符串拼接时采用append方法,在原来的基础上进行追加,所以性能比String要高,又因为StringBuffer是线程安全的而StringBuilder是线程非安全的,所以StringBuilder的效率高于StringBuffer.

3.对于大数据量的字符串的拼接,采用StringBuffer,StringBuilder.

五、Hashtable与HashMap的区别

HashMap不是线程安全的,HashTable是线程安全。

HashMap允许空(null)的键和值(key),HashTable则不允许。

HashMap性能优于Hashtable。

Map

1.Map是一个以键值对存储的接口。Map下有两个具体的实现,分别是HashMap和

HashTable.

2.HashMap是线程非安全的,HashTable是线程安全的,所以HashMap的效率高于HashTable.

3.HashMap允许键或值为空,而HashTable不允许键或值为空.

十四、List,Set,Collection,Collections

1.List和Set都是接口,他们都继承于接口Collection,List是一个有序的可重复的集合,而Set的无序的不可重复的集合。Collection是集合的顶层接口,Collections是一个封装了众多关于集合操作的静态方法的工具类,因为构造方法是私有的,所以不能实例化。

2.List接口实现类有ArrayList,LinkedList,Vector。ArrayList和Vector是基于数组实现的,所以查询的时候速度快,而在进行增加和删除的时候速度较慢LinkedList是基于链式存储结构,所以在进行查询的时候速度较慢但在进行增加和删除的时候速度较快。又因为Vector是线程安全的,所以他和ArrayList相比而言,查询效率要低。

十五、java的基本数据类型

数据类型 大小

byte(字节) 1(8位)

shot(短整型) 2(16位)

int(整型) 4(32位)

long(长整型) 8(32位)

float(浮点型) 4(32位)

double(双精度) 8(64位)

char(字符型) 2(16位)

boolean(布尔型) 1位

附加:

String是基本数据类型吗?(String不是基本数据类型)

String的长度是多少,有限制?(长度受内存大小的影响)

十八、时间类型转换

public class DateFormat {

public static void fun() {

SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd

日");

String newDate;

try {

newDate = sdf.format(new SimpleDateFormat

("yyyyMMdd")

.parse("20121115"));

System.out.println(newDate);

} catch (ParseException e) {

e.printStackTrace();

}

}

public static void main(String args[]) {

fun();

}

}

十九、阶乘

public class Multiply {

public static int multiply(int num) {

if (num < 0) {

System.out.println("请输入大于0的数!");

return -1;

} else if (num == 0 || num == 1) {

return 1;

} else {

return multiply(num - 1) * num;

}

}

public static void main(String[] args) {

System.out.println(multiply(10));

}

}

jvm的内存结构

Java虚拟机的内存结构分为堆(heap)和栈(stack),堆里面存放是对象实例也就是new出来的对象。栈里面存放的是基本数据类型以及引用数据类型的地址。对于所谓的常量是存储在方法区的常量池里面。

java Exception体系结构

java 异常是程序运行过程中出现的错误。Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。在Java API中定义了许多异常类,分为两大类,错误Error和异常Exception。其中异常类Exception又分为运行时异常(RuntimeException)和非运行时异常(非runtimeException),也称之为不检查异常Unchecked Exception)和检查异常(Checked Exception)。

1、Error与Exception

Error是程序无法处理的错误,比如OutOfMemoryError、ThreadDeath等。

这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。

Exception是程序本身可以处理的异常,这种异常分两大类运行时异常和非运行时异常。程序中应当尽可能去处理这些异常。

2、运行时异常和非运行时异常

运行时异常: 都是RuntimeException类及其子类异常:

IndexOutOfBoundsException 索引越界异常

ArithmeticException:数学计算异常

NullPointerException:空指针异常

ArrayOutOfBoundsException:数组索引越界异常

ClassNotFoundException:类文件未找到异常

ClassCastException:造型异常(类型转换异常)

这些异常是不检查异常(Unchecked Exception),程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的。

非运行时异常:是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如:

IOException、文件读写异常

FileNotFoundException:文件未找到异常

EOFException:读写文件尾异常

MalformedURLException:URL格式错误异常

SocketException:Socket异常

SQLException:SQL数据库异常

字节流与字符流的区别

stream结尾都是字节流,reader和writer结尾都是字符流

两者的区别就是读写的时候一个是按字节读写,一个是按字符。

实际使用通常差不多。

在读写文件需要对内容按行处理,比如比较特定字符,处理某一行数据的时候一般会选择字符流。

只是读写文件,和文件内容无关的,一般选择字节流。

final,finally,finalize 三者区别

Final是一个修饰符:

当final修饰一个变量的时候,变量变成一个常量,它不能被二次赋值

当final修饰的变量为静态变量(即由static修饰)时,必须在声明这个变 量的时候给它赋值

当final修饰方法时,该方法不能被重写

当final修饰类时,该类不能被继承

Final不能修饰抽象类,因为抽象类中会有需要子类实现的抽 象方法,(抽象类中可以有抽象方法,也可以有普通方法,当一个抽象类中没有抽象方法时,这个抽象类也就没有了它存在的必要)

Final不能修饰接口,因为接口中有需要其实现类来实现的方法

Finally:

Finally只能与try/catch语句结合使用,finally语句块中的语句一定会执行,并且会在return,continue,break关键字之前执行

finalize:

Finalize是一个方法,属于java.lang.Object类,finalize()方法是GC(garbage collector垃圾回收)运行机制的一部分,finalize()方法是在 GC清理它所从属的对象时被调用的

Io流的层次结构

从流的方向

输入流   输出流

从流的类型上

字符流    字节流

inputstream和outputstream都是抽象类

它们下面的实现包括

FileInputStream,BufferedInputStream

FileOutputStream,BufferedOutputStream

reader 和 writer

FileReader,BufferedReader,StringReader

FileWriter,BufferedWriter,StringWriter,PrintWriter

JAVA:

Java是面向对象的,跨平台的,它通过java虚拟机来进行跨平台操作,它可以进行自动垃圾回收的【c语言是通过人工进行垃圾回收】,java还会进行自动分配内存。【c语言是通过指定进行分配内存的】,只需要new一个对象,这个对象占用了多少空间,不需要我们来管,java虚拟机负责管这些,用完之后也不需要我们来释放,java虚拟机会自动释放

JavaSE JavaEE JavaME区别

是什么:

Java SE=Java Standard Edition=j2se = java 标准版

Java EE=Java Enterprise Edition=j2ee= java 企业版

Java ME=Java Mobile Edition=j2me = java移动版

特点:

SE主要用于桌面程序(swing),控制台开发(main程序)。

EE企业级开发(JSP,EJB,Spring MVC,Struts,hibernate,ibatis等),

用于企业级软件开发,网络开发,web开发。

ME嵌入式开发(手机,小家电,PDA)。[苹果的ios,黑莓]

三者之间的关系:

Java SE(Java Platform, Standard Edition,Java标准版)就是基于JDK和JRE的。

Java SE为Java EE提供了基础。

Java EE除了基于我们这个所谓的Java SE外,还新加了企业应用所需的类库

JDK  JRE  JVM的区别:

Jdk【Java Development ToolKit】就是java开发工具箱, JDK是整个JAVA的核心里边包含了jre,它除了包含jre之外还包含了一些javac的工具类,把java源文件编译成class文件,java文件是用来运行这个程序的,除此之外,里边还包含了java源生的API,java.lang.integer在rt的jar包里边【可以在项目中看到】,通过rt这个jar包来调用我们的这些io流写入写出等

JDK有以下三种版本:

J2SE,standard edition,标准版,是我们通常用的一个版本

J2EE,enterpsise edtion,企业版,使用这种JDK开发J2EE应用程序

J2ME,micro edtion,主要用于移动设备、嵌入式设备上的java应用程序

Jre【Java  Runtime  Enviromental】是java运行时环境,那么所谓的java运行时环境,就是为了保证java程序能够运行时,所必备的一基础环境,也就是它只是保证java程序运行的,不能用来开发,而jdk才是用来开发的,所有的Java程序都要在JRE下才能运行。包括JVM和JAVA核心类库和支持文件。与JDK相比,它不包含开发工具——编译器、调试器和其它工具。

Jre里边包含jvm

Jvm:【Java Virtual Mechinal】因为jre是java运行时环境,java运行靠什么运行,而底层就是依赖于jvm,即java虚拟机,java虚拟机用来加载类文件,java中之所以有跨平台的作用,就是因为我们的jvm

关系:

J2se是基于jdk和jre,

JDK是整个JAVA的核心里边包含了jre,

Jre里边包含jvm

抽象类与接口的区别

1.一个类只能进行单继承,但可以实现多个接口。

2.有抽象方法的类一定是抽象类,但是抽象类里面不一定有抽象方法;

接口里面所有的方法的默认修饰符为public abstract,接口里的成员变量默认的修饰符为  pulbic static final。

关系

接口和接口      继承

接口和抽象类    抽象类实现接口

类和抽象类      类继承抽象类

类和类          继承

switch默认接受的几种数据类型

Short, int, byte, char

反射的描述

通过字符串可以动态创建java对象,并且可以动态访问方法,属性等。

我们在项目中的时候封装过数据库jdbc的持久层,其中就利用反射这项

技术来达到通用和灵活的目的。

1.4.Hashtable与HashMap的区别

HashMap不是线程安全的,HashTable是线程安全。

HashMap允许空(null)的键和值(key),HashTable则不允许。

HashMap性能优于Hashtable。

Map

1.Map是一个以键值对存储的接口。Map下有两个具体的实现,分别是HashMap和

HashTable.

2.HashMap是线程非安全的,HashTable是线程安全的,所以HashMap的效率高于

HashTable.

3.HashMap允许键或值为空,而HashTable不允许键或值为空.

jvm的类加载机制?  jvm中类的生命周期?

生命周期:加载、连接、初始化,使用,卸载

对象基本上都是在jvm的堆区中创建,在创建对象之前,

会触发类加载(加载、连接、初始化),

当类初始化完成后,

根据类信息在堆中实例化类对象,

初始化非静态变量、非静态代码以及默认构造方法,

当对象使用完之后会在合适的时候被jvm垃圾收集器回收。

要经过三步:加载(Load),链接(Link),初始化(Initializ)。

其中链接又可分为校验(Verify),准备(Prepare),解析(Resolve)三步。

ClassLoader就是用来装载的。通过指定的className,找到二进制码,

生成Class实例,放到JVM中。

Collection 和 Collections 的区别?

Collection 是集合类的上级接口,继承与他的接口主要有 Set 和 List.

Collections 是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作

数组为什么是查询快?

因为数组的内存空间地址是连续的。ArrayList 底层维护了一个 Object[] 用于存储对象,(源码可查)默认数组的长度是 10。 可以通过 new ArrayList(15)显式的指定用于存储对象的数组的长度。当默认的或者指定的容量不够存储对象的时候,容量自动增长为原来的容量的 1.5 倍。由于 ArrayList 是数组实现,在增和删的时候会牵扯到数组增容, 以及拷贝元素, 所以慢。 数组是可以直接按索引查找,所以查找时较快。可以考虑,假设向数组的 0 角标未知添加元素,那么原来的角标位置的元素需要整体往后移,并且数组可能还要增容,一旦增容,就需要要将老数组的内容拷贝到新数组中,所以数组的增删的效率是很低的

Array 和 ArrayList 有何区别?什么时候更适合用 Array?

1. Array 可以容纳基本类型和对象,而 ArrayList 只能容纳对象。

2. Array 是指定大小的,而 ArrayList 大小是固定的

ArrayList 和 LinkedList 的存储查找的优缺点?

1、 ArrayList 是采用动态数组来存储元素的,它允许直接用下标号来直接查找对应的元素。但是,但是插入元素要涉及数组元素移动及内存的操作。总结:查找快,增删慢。

2、 LinkedList 是采用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。总结:增删快,查找慢

HashSet 如何检查重复?

HashSet 会通过元素的 hashcode()和

equals 方法进行判断元素师否重复。

hashCode()和 equals()方法有何重要性?

HashMap 使用 Key 对象的 hashCode()和 equals()方法去决定 key-value

对的索引。当我们试着从 HashMap 中获取值的时候,这些方法也会被用到。如果这些方法没有被正确地实现,在这种情况下,两个不同 Key 也许会产生相同的 hashCode()和 equals()输出,HashMap 将会认为它们是相同的,然后覆盖它们,而非把它们存储到不同的地方。同样的,所有不允许存储重复数据的集合类都使用 hashCode()和 equals()去查找重复,所以正确实现它们非常重要。 equals()和 hashCode()的实现应该遵循以下规则:

(1)如果 o1.equals(o2),那么 o1.hashCode() == o2.hashCode()总是为

true 的。

(2)如果 o1.hashCode() == o2.hashCode(),并不意味着 o1.equals(o2)会为 true

为何 Map 接口不继承 Collection 接口?

尽管 Map 接口和它的实现也是集合框架的一部分,但 Map 不是集合,集合也不是 Map。因此,Map 继承 Collection 毫无意义,反之亦然。如果 Map 继承 Collection 接口,那么元素去哪儿?Map 包含 keyvalue 对,它提供抽取 key 或 value 列表集合的方法,但是它不适合“一组对象”规范

什么是 HashMap?你为什么用到它?

譬如 HashMap 可以接受 null 键值和值,而 Hashtable 则不能;HashMap 是非 synchronized;HashMap 很快;以及 HashMap 储存的是键值对等等。

你知道 HashMap 的工作原理吗?

HashMap 是基于 hashing(散列法)的原理,我们使用 put(key, value)存储对象到 HashMap 中,使用 get(key)从 HashMap 中获取对象。当我们给put()方法传递键和值时,我们先对键调用 hashCode()方法,返回的hashCode 用于找到 bucket 位置来储存 Entry 对象。 这里关键点在于指出,HashMap 是在 bucket 中储存键对象和值对象,作为 Map.Entry。当两个对象的 hashcode 相同会发生什么?因为 hashcode 相同,所以它们的 bucket 位置相同,‘碰撞’会发生。因为 HashMap 使用链表存储对象,这个 Entry(包含有键值对的 Map.Entry 对象)会存储在链表中。”这个答案非常的合理,虽然有很多种处理碰撞的方法,这种方法是最简单的,也正是 HashMap 的处理方法。如果两个键的 hashcode 相同,你如何获取值对象?当我们调用 get()方法,HashMap 会使用键对象的 hashcode 找到bucket 位置,然后获取值对象。 如果有两个值对象储存在同一个 bucket,那么将会遍历链表直到找到值对象。如果 HashMap 的大小超过了负载因子(load factor)定义的容量,怎么办?默认的负载因子大小为 0.75,也就是说,当一个 map 填满了 75%的bucket 时候,和其它集合类(如 ArrayList等)一样,将会创建原来 HashMap大小的两倍的 bucket 数组,来重新调整 map 的大小,并将原来的对象放入新的 bucket 数组中。这个过程叫作rehashing,因为它调用 hash 方法找到新的bucket 位置。你了解重新调整 HashMap 大小存在什么问题吗?当重新调整 HashMap 大小的时候,确实存在条件竞争,因为如果两个线程都发现 HashMap 需要重新调整大小了,它们会同时试着调整大小。在调整大小的过程中,存储在链表中的元素的次序会反过来,因为移动到新的 bucket位置的时候,HashMap 并不会将元素放在链表的尾部,而是放在头部,这是为了避免尾部遍历(tail traversing)。如果条件竞争发生了,那么就死循环了。这个时候,你可以质问面试官,为什么这么奇怪,要在多线程的环境下使用HashMap 呢?

Enumeration 和 Iterator 接口的区别?

Enumeration 的速度是 Iterator 的两倍,也使用更少的内存。

Enumeration 是非常基础的,也满足了基础的需要。但是,与 Enumeration相比,Iterator 更加安全,因为当一个集合正在被遍历的时候,它会阻止其它线程去修改集合。迭代器取代了 Java 集合框架中的 Enumeration。迭代器允许调用者从集合中移除元素,而 Enumeration 不能做到。为了使它的功能更加清晰,迭代器方法名已经经过改善。

Java内存模型:

Java虚拟机规范中将Java运行时数据分为六种。

1.程序计数器: 是一个数据结构, 用于保存当前正常执行的程序的内存地址。 Java虚拟机的多线程就是通过线程轮流切换并分配处理器时间来实现的,为了线程切换后能恢复到正确的位置, 每条线程都需要一个独立的程序计数器, 互不影响, 该区域为“线程私有”。

2.Java虚拟机栈: 线程私有的, 与线程生命周期相同, 用于存储局部变量表, 操作栈, 方法返回值。 局部变量表放着基本数据类型, 还有对象的引用。

3.本地方法栈: 跟虚拟机栈很像, 不过它是为虚拟机使用到的Native方法服务。

4.Java堆: 所有线程共享的一块内存区域, 对象实例几乎都在这分配内存。

5.方法区: 各个线程共享的区域, 储存虚拟机加载的类信息, 常量, 静态变量, 编译后的代码。

6.运行时常量池: 代表运行时每个class文件中的常量表。 包括几种常量: 编译时的数字常量、 方法或者域的引用。

java GC是在什么时候, 对什么东西, 做了什么事情? ”

在什么时候:

1.新生代有一个Eden区和两个survivor区, 首先将对象放入Eden区, 如果空间不足就向其中的一个survivor区上放, 如果仍然放不下就会引发一次发生

在新生代的minor GC, 将存活的对象放入另一个survivor区中, 然后清空Eden和之前的那个survivor区的内存。 在某次GC过程中, 如果发现仍然又放

不下的对象, 就将这些对象放入老年代内存里去。

2.大对象以及长期存活的对象直接进入老年区。

3.当每次执行minor GC的时候应该对要晋升到老年代的对象进行分析, 如果这些马上要到老年区的老年对象的大小超过了老年区的剩余大小, 那么执

行一次Full GC以尽可能地获得老年区的空间。

对什么东西: 从GC Roots搜索不到, 而且经过一次标记清理之后仍没有复活的对象。

做什么: 新生代: 复制清理; 老年代: 标记-清除和标记-压缩算法; 永久代: 存放Java中的类和加载类的类加载器本身。

GC Roots都有哪些:

1. 虚拟机栈中的引用的对象

2. 方法区中静态属性引用的对象, 常量引用的对象

3. 本地方法栈中JNI(即一般说的Native方法) 引用的对象

1) Java 中能创建 Volatile 数组吗?

能, Java 中可以创建 volatile 类型数组, 不过只是一个指向数组的引用, 而不是整个数组。 我的意思是, 如果改变引用指向的数组, 将会受到 volatile 的保护, 但是如果多个线程同时改变数组的元素, volatile 标示符就不能起到之前的保护作用了。

2) volatile 能使得一个非原子操作变成原子操作吗?

一个典型的例子是在类中有一个 long 类型的成员变量。如果你知道该成员变量会被多个线程访问, 如计数器、 价格等, 你最好是将其设置为 volatile。 为什么? 因为 Java 中读取long 类型变量不是原子的, 需要分成两步, 如果一个线程正在修改该 long 变量的值, 另一个线程可能只能看到该值的一半(前 32 位) 。 但是对一个 volatile 型的 long 或double 变量的读写是原子。

3) volatile 修饰符的有过什么实践?

一种实践是用 volatile 修饰 long 和 double 变量,使其能按原子类型来读写。double 和long 都是 64 位宽, 因此对这两种类型的读是分为两部分的, 第一次读取第一个 32 位, 然后再读剩下的 32 位, 这个过程不是原子的, 但 Java 中 volatile 型的 long 或 double

变量的读写是原子的。 volatile 修复符的另一个作用是提供内存屏障(memory barrier) ,

例如在分布式框架中的应用。 简单的说, 就是当你写一个 volatile 变量之前, Java 内存模型会插入一个写屏障(write barrier) , 读一个 volatile 变量之前, 会插入一个读屏

障(read barrier) 。 意思就是说, 在你写一个 volatile 域时, 能保证任何线程都能看到

你写的值, 同时, 在写之前, 也能保证任何数值的更新对所有线程是可见的, 因为内存屏障会将其他所有写的值更新到缓存。

4) volatile 类型变量提供什么保证? (答案)

volatile 变量提供顺序和可见性保证, 例如, JVM 或者 JIT 为了获得更好的性能会对语句重排序, 但是 volatile 类型变量即使在没有同步块的情况下赋值也不会与其他语句重排序。 volatile 提供 happens-before 的保证,确保一个线程的修改能对其他线程是可见的。

某些情况下, volatile 还能提供原子性, 如读 64 位数据类型, 像 long 和 double 都不

是原子的, 但 volatile 类型的 double 和 long 就是原子的。

5) 10 个线程和 2 个线程的同步代码, 哪个更容易写?

从写代码的角度来说, 两者的复杂度是相同的, 因为同步代码与线程数量是相互独立的。 但是同步策略的选择依赖于线程的数量, 因为越多的线程意味着更大的竞争, 所以你需要利用同步技术, 如锁分离, 这要求更复杂的代码和专业知识。

6) 你是如何调用 wait() 方法的? 使用 if 块还是循环? 为什么? (答案)

wait() 方法应该在循环调用, 因为当线程获取到 CPU 开始执行的时候, 其他条件可能还没有满足, 所以在处理前, 循环检测条件是否满足会更好。 下面是一段标准的使用 wait 和notify 方法的代码:

// The standard idiom for using the wait method

synchronized (obj) {while (condition does not hold)

obj.wait(); // (Releases lock, and reacquires on wakeup)

... // Perform action appropriate to condition

} 参见 Effective Java 第 69 条, 获取更多关于为什么应该在循环中来调用 wait 方法的内

容。

7) 什么是多线程环境下的伪共享(false sharing) ?

伪共享是多线程系统(每个处理器有自己的局部缓存) 中一个众所周知的性能问题。 伪共享发生在不同处理器的上的线程对变量的修改依赖于相同的缓存行, 如下图所示:伪共享有经验程序员的 Java 面试题伪共享问题很难被发现, 因为线程可能访问完全不同的全局变量, 内存中却碰巧在很相近的位置上。 如其他诸多的并发问题, 避免伪共享的最基本方式是仔细审查代码, 根据缓存行来调整你的数据结构。

8) 什么是 Busy spin? 我们为什么要使用它?

Busy spin 是一种在不释放 CPU 的基础上等待事件的技术。 它经常用于避免丢失 CPU 缓存中的数据(如果线程先暂停, 之后在其他 CPU 上运行就会丢失) 。 所以, 如果你的工作要求低延迟, 并且你的线程目前没有任何顺序, 这样你就可以通过循环检测队列中的新消息来代替调用 sleep() 或 wait() 方法。 它唯一的好处就是你只需等待很短的时间, 如几微秒或几 纳 秒 。 LMAX 分 布 式 框 架 是 一 个 高 性 能 线 程 间 通 信 的 库 , 该 库 有 一 个BusySpinWaitStrategy 类 就 是 基 于 这 个 概 念 实 现 的 , 使 用 busy spin 循 环EventProcessors 等待屏障。

9) Java 中怎么获取一份线程 dump 文件?

在 Linux 下, 你可以通过命令 kill -3 PID (Java 进程的进程 ID) 来获取 Java 应用的dump 文件。 在 Windows 下, 你可以按下 Ctrl + Break 来获取。 这样 JVM 就会将线程的dump 文件打印到标准输出或错误文件中, 它可能打印在控制台或者日志文件中, 具体位置依赖应用的配置。 如果你使用 Tomcat。

10) Swing 是线程安全的? (答案)

不是, Swing 不是线程安全的。 你不能通过任何线程来更新 Swing 组件, 如 JTable、 JList或 JPanel, 事实上, 它们只能通过 GUI 或 AWT 线程来更新。 这就是为什么 Swing 提供invokeAndWait() 和 invokeLater() 方法来获取其他线程的 GUI 更新请求。这些方法将更新请求放入 AWT 的线程队列中, 可以一直等待, 也可以通过异步更新直接返回结果。 你也可以在参考答案中查看和学习到更详细的内容。

11) 什么是线程局部变量? (答案)

线程局部变量是局限于线程内部的变量, 属于线程自身所有, 不在多个线程间共享。 Java 提供 ThreadLocal 类来支持线程局部变量, 是一种实现线程安全的方式。 但是在管理环境下(如 web 服务器) 使用线程局部变量的时候要特别小心, 在这种情况下, 工作线程的生命周期比任何应用变量的生命周期都要长。 任何线程局部变量一旦在工作完成后没有释放,Java 应用就存在内存泄露的风险。

12) 用 wait-notify 写一段代码来解决生产者-消费者问题? (答案)

请参考答案中的示例代码。 只要记住在同步块中调用 wait() 和 notify()方法, 如果阻塞,通过循环来测试等待条件。

13) 用 Java 写一个线程安全的单例模式(Singleton) ? (答案)

请参考答案中的示例代码, 这里面一步一步教你创建一个线程安全的 Java 单例类。 当我们说线程安全时, 意思是即使初始化是在多线程环境中, 仍然能保证单个实例。 Java 中, 使用枚举作为单例类是最简单的方式来创建线程安全单例模式的方式。

14) Java 中 sleep 方法和 wait 方法的区别? (答案)

虽然两者都是用来暂停当前运行的线程, 但是 sleep() 实际上只是短暂停顿, 因为它不会

释放锁, 而 wait() 意味着条件等待, 这就是为什么该方法要释放锁, 因为只有这样, 其他等待的线程才能在满足条件时获取到该锁。

15) 什么是不可变对象(immutable object) ? Java 中怎么创建一个不可变对象? (答案)

不可变对象指对象一旦被创建, 状态就不能再改变。 任何修改都会创建一个新的对象, 如String、 Integer 及其它包装类。 详情参见答案, 一步一步指导你在 Java 中创建一个不可变的类。

16) 我们能创建一个包含可变对象的不可变对象吗?

是的, 我们是可以创建一个包含可变对象的不可变对象的, 你只需要谨慎一点, 不要共享可变对象的引用就可以了, 如果需要变化时, 就返回原对象的一个拷贝。 最常见的例子就是对象中包含一个日期对象的引用。

数据类型和 Java 基础面试问题

17) Java 中应该使用什么数据类型来代表价格? (答案)

如果不是特别关心内存和性能的话, 使用 BigDecimal, 否则使用预定义精度的 double 类型。

18) 怎么将 byte 转换为 String? (答案)

可以使用 String 接收 byte[] 参数的构造器来进行转换, 需要注意的点是要使用的正确的编码, 否则会使用平台默认编码, 这个编码可能跟原来的编码相同, 也可能不同。

19) Java 中怎样将 bytes 转换为 long 类型?

20) 我们能将 int 强制转换为 byte 类型的变量吗? 如果该值大于 byte 类型的范围, 将

会出现什么现象?

是的, 我们可以做强制转换, 但是 Java 中 int 是 32 位的, 而 byte 是 8 位的, 所以,如果强制转化是, int 类型的高 24 位将会被丢弃, byte 类型的范围是从 -128 到 128。

21) 存在两个类, B 继承 A, C 继承 B, 我们能将 B 转换为 C 么? 如 C = (C) B; (answer

答案)

22) 哪个类包含 clone 方法? 是 Cloneable 还是 Object? (答案)

java.lang.Cloneable 是一个标示性接口, 不包含任何方法, clone 方法在 object 类中定

义。 并且需要知道 clone() 方法是一个本地方法, 这意味着它是由 c 或 c++ 或 其他本地语言实现的。

23) Java 中 ++ 操作符是线程安全的吗? (答案)

不是线程安全的操作。 它涉及到多个指令, 如读取变量值, 增加, 然后存储回内存, 这个过程可能会出现多个线程交差。

24) a = a + b 与 a += b 的区别(答案)

+= 隐式的将加操作的结果类型强制转换为持有结果的类型。如果两这个整型相加,如 byte、short 或者 int, 首先会将它们提升到 int 类型, 然后在执行加法操作。 如果加法操作的结果比 a 的最大值要大, 则 a+b 会出现编译错误, 但是 a += b 没问题, 如下:

byte a = 127;

byte b = 127;

b = a + b; // error : cannot convert from int to byte

b += a; // ok

(译者注:这个地方应该表述的有误,其实无论 a+b 的值为多少,编译器都会报错,因为 a+b

操作会将 a、 b 提升为 int 类型, 所以将 int 类型赋值给 byte 就会编译出错)

25)我能在不进行强制转换的情况下将一个 double 值赋值给 long 类型的变量吗? (答案)

不行, 你不能在没有强制类型转换的前提下将一个 double 值赋值给 long 类型的变量, 因为 double 类型的范围比 long 类型更广, 所以必须要进行强制转换。

26) 3*0.1 == 0.3 将会返回什么? true 还是 false? (答案)

false, 因为有些浮点数不能完全精确的表示出来。

27) int 和 Integer 哪个会占用更多的内存? (答案)

Integer 对象会占用更多的内存。 Integer 是一个对象, 需要存储对象的元数据。 但是 int是一个原始类型的数据, 所以占用的空间更少。

28) 为什么 Java 中的 String 是不可变的(Immutable) ? (answer 答案)

Java 中的 String 不可变是因为 Java 的设计者认为字符串使用非常频繁, 将字符串设置为不可变可以允许多个客户端之间共享相同的字符串。 更详细的内容参见答案。

29) 我们能在 Switch 中使用 String 吗? (answer 答案)

从 Java 7 开始, 我们可以在 switch case 中使用字符串, 但这仅仅是一个语法糖。 内部实现在 switch 中使用字符串的 hash code。

30) Java 中的构造器链是什么? (answer 答案)

当你从一个构造器中调用另一个构造器, 就是 Java 中的构造器链。 这种情况只在重载了类的构造器的时候才会出现。JVM 底层 与 GC(Garbage Collection) 的面试问题

31) 64 位 JVM 中, int 的长度是多数?

Java 中, int 类型变量的长度是一个固定值, 与平台无关, 都是 32 位。 意思就是说, 在 32位 和 64 位 的 Java 虚拟机中, int 类型的长度是相同的。

32) Serial 与 Parallel GC 之间的不同之处? (答案)

Serial 与 Parallel 在 GC 执行的时候都会引起 stop-the-world。 它们之间主要不同serial 收集器是默认的复制收集器, 执行 GC 的时候只有一个线程, 而 parallel 收集器

使用多个 GC 线程来执行。

33) 32 位和 64 位的 JVM, int 类型变量的长度是多数? (答案)

32 位和 64 位的 JVM 中, int 类型变量的长度是相同的, 都是 32 位或者 4 个字节。

34) Java 中 WeakReference 与 SoftReference 的区别? (答案)

虽 然 WeakReference 与 SoftReference 都 有 利 于 提 高 GC 和 内 存 的 效 率 , 但 是WeakReference , 一旦失去最后一个强引用, 就会被 GC 回收, 而软引用虽然不能阻止被回收, 但是可以延迟到 JVM 内存不足的时候。

35) WeakHashMap 是怎么工作的? (答案)

WeakHashMap 的工作与正常的 HashMap 类似, 但是使用弱引用作为 key, 意思就是当 key对象没有任何引用时, key/value 将会被回收。

36) JVM 选项 -XX:+UseCompressedOops 有什么作用? 为什么要使用? (答案)

当你将你的应用从 32 位的 JVM 迁移到 64 位的 JVM 时, 由于对象的指针从 32 位增加到了 64 位, 因此堆内存会突然增加, 差不多要翻倍。 这也会对 CPU 缓存(容量比内存小很多) 的数据产生不利的影响。 因为, 迁移到 64 位的 JVM 主要动机在于可以指定最大堆大小, 通过压缩 OOP 可以节省一定的内存。 通过 -XX:+UseCompressedOops 选项, JVM 会使用 32 位的 OOP, 而不是 64 位的 OOP。

37) 怎样通过 Java 程序来判断 JVM 是 32 位 还是 64 位? (答案)

你可以检查某些系统属性如 sun.arch.data.model 或 os.arch 来获取该信息。

38) 32 位 JVM 和 64 位 JVM 的最大堆内存分别是多数? (答案)

理论上说上 32 位的 JVM 堆内存可以到达 2^32, 即 4GB, 但实际上会比这个小很多。 不同操作系统之间不同, 如 Windows 系统大约 1.5 GB, Solaris 大约 3GB。 64 位 JVM 允许指定最大的堆内存, 理论上可以达到 2^64, 这是一个非常大的数字, 实际上你可以指定堆内存大小到 100GB。 甚至有的 JVM, 如 Azul, 堆内存到 1000G 都是可能的。

39) JRE、 JDK、 JVM 及 JIT 之间有什么不同? (答案)

JRE 代表 Java 运行时(Java run-time) , 是运行 Java 引用所必须的。 JDK 代表 Java 开发工具(Java development kit) , 是 Java 程序的开发工具, 如 Java 编译器, 它也包含JRE。 JVM 代表 Java 虚拟机(Java virtual machine) , 它的责任是运行 Java 应用。 JIT

代表即时编译(Just In Time compilation) , 当代码执行的次数超过一定的阈值时, 会将

Java 字节码转换为本地代码, 如, 主要的热点代码会被准换为本地代码, 这样有利大幅度提高 Java 应用的性能。

最近 5 年 133 个 Java 面试问题列表 ----3 年工作经验的 Java 面试题

40) 解释 Java 堆空间及 GC? (答案)

当通过 Java 命令启动 Java 进程的时候, 会为它分配内存。内存的一部分用于创建堆空间,当程序中创建对象的时候, 就从对空间中分配内存。 GC 是 JVM 内部的一个进程, 回收无效对象的内存用于将来的分配。

JVM 底层面试题及答案

41) 你能保证 GC 执行吗? (答案)

不能, 虽然你可以调用 System.gc() 或者 Runtime.gc(), 但是没有办法保证 GC 的执行。

42) 怎么获取 Java 程序使用的内存? 堆使用的百分比?

可以通过 java.lang.Runtime 类中与内存相关方法来获取剩余的内存, 总内存及最大堆内存 。 通 过 这 些 方 法 你 也 可 以 获 取 到 堆 使 用 的 百 分 比 及 堆 内 存 的 剩 余 空 间 。Runtime.freeMemory() 方法返回剩余空间的字节数, Runtime.totalMemory() 方法总内存的字节数, Runtime.maxMemory() 返回最大内存的字节数。

43) Java 中堆和栈有什么区别? (答案)

JVM 中堆和栈属于不同的内存区域, 使用目的也不同。 栈常用于保存方法帧和局部变量, 而对象总是在堆上分配。 栈通常都比堆小, 也不会在多个线程之间共享, 而堆被整个 JVM 的所有线程共享。

关于内存的的面试问题和答案----Java 基本概念面试题

44) “a==b” 和” a.equals(b)” 有什么区别? (答案)

如果 a 和 b 都是对象, 则 a==b 是比较两个对象的引用, 只有当 a 和 b 指向的是堆中的同一个对象才会返回 true, 而 a.equals(b) 是进行逻辑比较, 所以通常需要重写该方法来提供逻辑一致性的比较。 例如, String 类重写 equals() 方法, 所以可以用于两个不同对象, 但是包含的字母相同的比较。

45) a.hashCode() 有什么用? 与 a.equals(b) 有什么关系? (答案)

hashCode() 方 法 是 相 应 对 象 整 型 的 hash 值 。 它 常 用 于 基 于 hash 的 集 合 类 , 如Hashtable、 HashMap、 LinkedHashMap 等等。 它与 equals() 方法关系特别紧密。 根据 Java规范, 两个使用 equal() 方法来判断相等的对象, 必须具有相同的 hash code。

46) final、 finalize 和 finally 的不同之处? (答案)

final 是一个修饰符, 可以修饰变量、 方法和类。 如果 final 修饰变量, 意味着该变量的值在初始化后不能被改变。 finalize 方法是在对象被回收之前调用的方法, 给对象自己最后一个复活的机会,但是什么时候调用 finalize 没有保证。finally 是一个关键字,与 try

和 catch 一起用于异常的处理。 finally 块一定会被执行, 无论在 try 块中是否有发生异

常。

47) Java 中的编译期常量是什么? 使用它又什么风险?

公共静态不可变(public static final )变量也就是我们所说的编译期常量, 这里的 public

可选的。 实际上这些变量在编译时会被替换掉, 因为编译器知道这些变量的值, 并且知道这些变量在运行时不能改变。这种方式存在的一个问题是你使用了一个内部的或第三方库中的公有编译时常量, 但是这个值后面被其他人改变了, 但是你的客户端仍然在使用老的值, 甚至你已经部署了一个新的 jar。 为了避免这种情况, 当你在更新依赖 JAR 文件时, 确保重新编译你的程序。

Java 集合框架的面试题----这部分也包含数据结构、 算法及数组的面试问题

48) List、 Set、 Map 和 Queue 之间的区别(答案)

List 是一个有序集合, 允许元素重复。 它的某些实现可以提供基于下标值的常量访问时间,但是这不是 List 接口保证的。 Set 是一个无序集合。

49) poll() 方法和 remove() 方法的区别?

poll() 和 remove() 都是从队列中取出一个元素, 但是 poll() 在获取元素失败的时候会

返回空, 但是 remove() 失败的时候会抛出异常。

50) Java 中 LinkedHashMap 和 PriorityQueue 的区别是什么? (答案)

PriorityQueue 保证最高或者最低优先级的的元素总是在队列头部, 但是 LinkedHashMap维持的顺序是元素插入的顺序。 当遍历一个 PriorityQueue 时, 没有任何顺序保证, 但是LinkedHashMap 课保证遍历顺序是元素插入的顺序。

51) ArrayList 与 LinkedList 的不区别? (答案)

最明显的区别是 ArrrayList 底层的数据结构是数组, 支持随机访问, 而 LinkedList 的底层数据结构书链表, 不支持随机访问。 使用下标访问一个元素, ArrayList 的时间复杂度是O(1), 而 LinkedList 是 O(n)。 更多细节的讨论参见答案。

52) 用哪两种方式来实现集合的排序? (答案)

你可以使用有序集合, 如 TreeSet 或 TreeMap, 你也可以使用有顺序的的集合, 如 list,然后通过 Collections.sort() 来排序。

53) Java 中怎么打印数组? (answer 答案)

你可以使用 Arrays.toString() 和 Arrays.deepToString() 方法来打印数组。由于数组没

有实现 toString() 方法, 所以如果将数组传递给 System.out.println() 方法, 将无法打

印出数组的内容, 但是 Arrays.toString() 可以打印每个元素。

54) Java 中的 LinkedList 是单向链表还是双向链表? (答案)

是双向链表, 你可以检查 JDK 的源码。 在 Eclipse, 你可以使用快捷键 Ctrl + T, 直接在编辑器中打开该类。

55) Java 中的 TreeMap 是采用什么树实现的? (答案)

Java 中的 TreeMap 是使用红黑树实现的。

56) Hashtable 与 HashMap 有什么不同之处? (答案)

这两个类有许多不同的地方, 下面列出了一部分:

a) Hashtable 是 JDK 1 遗留下来的类, 而 HashMap 是后来增加的。

b) Hashtable 是同步的, 比较慢, 但 HashMap 没有同步策略, 所以会更快。

c) Hashtable 不允许有个空的 key, 但是 HashMap 允许出现一个 null key。

更多的不同之处参见答案。

57) Java 中的 HashSet, 内部是如何工作的? (answer 答案)

HashSet 的内部采用 HashMap 来实现。 由于 Map 需要 key 和 value, 所以所有 key 的都有一个默认 value。 类似于 HashMap, HashSet 不允许重复的 key, 只允许有一个 null key,意思就是 HashSet 中只允许存储一个 null 对象。

58) 写一段代码在遍历 ArrayList 时移除一个元素? (答案)

该问题的关键在于面试者使用的是 ArrayList 的 remove() 还是 Iterator 的 remove()方法。 这有一段示例代码, 是使用正确的方式来实现在遍历的过程中移除元素, 而不会出现ConcurrentModificationException 异常的示例代码。

59) 我们能自己写一个容器类, 然后使用 for-each 循环码?

可以, 你可以写一个自己的容器类。 如果你想使用 Java 中增强的循环来遍历, 你只需要实现 Iterable 接口。 如果你实现 Collection 接口, 默认就具有该属性。

60) ArrayList 和 HashMap 的默认大小是多数? (答案)

在 Java 7 中, ArrayList 的默认大小是 10 个元素, HashMap 的默认大小是 16 个元素(必须是 2 的幂) 。 这就是 Java 7 中 ArrayList 和 HashMap 类的代码片段:

// from ArrayList.java JDK 1.7

private static final int DEFAULT_CAPACITY = 10;

//from HashMap.java JDK 7

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

61) 有没有可能两个不相等的对象有有相同的 hashcode?

有可能, 两个不相等的对象可能会有相同的 hashcode 值, 这就是为什么在 hashmap 中会

有冲突。 相等 hashcode 值的规定只是说如果两个对象相等, 必须有相同的 hashcode 值,

但是没有关于不相等对象的任何规定。

62) 两个相同的对象会有不同的的 hash code 吗?

不能, 根据 hash code 的规定, 这是不可能的。

63) 我们可以在 hashcode() 中使用随机数字吗? (答案)

不行, 因为对象的 hashcode 值必须是相同的。 参见答案获取更多关于 Java 中重写

hashCode() 方法的知识。

64) Java 中, Comparator 与 Comparable 有什么不同? (答案)

Comparable 接口用于定义对象的自然顺序,而 comparator 通常用于定义用户定制的顺序。

Comparable 总是只有一个, 但是可以有多个 comparator 来定义对象的顺序。

65) 为什么在重写 equals 方法的时候需要重写 hashCode 方法? (答案)

因为有强制的规范指定需要同时重写 hashcode 与 equal 是方法, 许多容器类, 如

HashMap、 HashSet 都依赖于 hashcode 与 equals 的规定。

Java IO 和 NIO 的面试题

IO 是 Java 面试中一个非常重要的点。 你应该很好掌握 Java IO, NIO, NIO2 以及与操作

系统, 磁盘 IO 相关的基础知识。 下面是 Java IO 中经常问的问题。

66) 在我 Java 程序中, 我有三个 socket, 我需要多少个线程来处理?

67) Java 中怎么创建 ByteBuffer?

ByteBuffer.allocate(250) -- 新建byteBuffer

bb.wrap(new byte[100]) -- 新建byteBuffer

68) Java 中, 怎么读写 ByteBuffer ?

put方法写 -- 入缓冲区

get方法  -- 读取缓冲区

69) Java 采用的是大端还是小端?

大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;

小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。

存储量大于1字节,非char类型,如int,float等,要考虑字节的顺序问题了。java由于虚拟机的关系,屏蔽了大小端问题,需要知道的话可用 ByteOrder.nativeOrder() 查询。在操作ByteBuffer中,也可以使用 ByteBuffer.order() 进行设置:

70) ByteBuffer 中的字节序是什么?

字节序分为两种:

BIG-ENDIAN----大字节序

LITTLE-ENDIAN----小字节序

BIG-ENDIAN、LITTLE-ENDIAN与多字节类型的数据有关的比如int,short,long型,而对单字节数据byte却没有影响。

BIG-ENDIAN就是最低地址存放最高有效字节。

LITTLE-ENDIAN是最低地址存放最低有效字节。即常说的低位在先,高位在后。

71) Java 中, 直接缓冲区与非直接缓冲器有什么区别? (答案)

BufferedOutputStream与任何一个OutputStream相同,除了用一个另外的flush( ) 方法来保证数据缓冲器被写入到实际的输出设备。因为BufferedOutputStream是通过减小系统写数据的时间而提高性能的,可以调用flush( )方法生成缓冲器中待写的数据。

72) Java 中的内存映射缓存区是什么? (answer 答案)

73) socket 选项 TCP NO DELAY 是指什么?

在默认情况下,客户端向服务器发送数据时,会根据数据包的大小决定是否立即发送。当数据包中的数据很少时,如只有1个字节,而数据包的头却有几十个字节(IP头+TCP头)时,系统会在发送之前先将较小的包合并到软大的包后,一起将数据发送出去。在发送下一个数据包时,系统会等待服务器对前一个数据包的响应,当收到服务器的响应后,再发送下一个数据包,这就是所谓的Nagle算法;在默认情况下,Nagle算法是开启的。

这种算法虽然可以有效地改善网络传输的效率,但对于网络速度比较慢,而且对实现性的要求比较高的情况下(如游戏、Telnet等),使用这种方式传输数据会使得客户端有明显的停顿现象。因此,最好的解决方案就是需要Nagle算法时就使用它,不需要时就关闭它。而使用setTcpToDelay正好可以满足这个需求。当使用setTcpNoDelay(true)将Nagle算法关闭后,客户端每发送一次数据,无论数据包的大小都会将这些数据发送出去。

74) TCP 协议与 UDP 协议有什么区别? (answer 答案)

小结TCP与UDP的区别:

1.基于连接与无连接;

2.对系统资源的要求(TCP较多,UDP少);

3.UDP程序结构较简单;

4.流模式与数据报模式 ;

5.TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。

75) Java 中, ByteBuffer 与 StringBuffer 有什么区别? (答案)

Java 最佳实践的面试问题

包含 Java 中各个部分的最佳实践, 如集合, 字符串, IO, 多线程, 错误和异常处理, 设计模式等等。

76) Java 中, 编写多线程程序的时候你会遵循哪些最佳实践? (答案)

这是我在写 Java 并发程序的时候遵循的一些最佳实践:

a) 给线程命名, 这样可以帮助调试。

b) 最小化同步的范围, 而不是将整个方法同步, 只对关键部分做同步。

c) 如果可以, 更偏向于使用 volatile 而不是 synchronized。

d) 使用更高层次的并发工具, 而不是使用 wait() 和 notify() 来实现线程间通信, 如

BlockingQueue, CountDownLatch 及 Semeaphore。

e) 优先使用并发集合, 而不是对集合进行同步。 并发集合提供更好的可扩展性。

77) 说出几点 Java 中使用 Collections 的最佳实践(答案)

这是我在使用 Java 中 Collectionc 类的一些最佳实践:

a) 使用正确的集合类, 例如, 如果不需要同步列表, 使用 ArrayList 而不是 Vector。

b) 优先使用并发集合, 而不是对集合进行同步。 并发集合提供更好的可扩展性。

c)使用接口代表和访问集合, 如使用 List 存储 ArrayList, 使用 Map 存储 HashMap 等等。

d) 使用迭代器来循环集合。

e) 使用集合的时候使用泛型。

78) 说出至少 5 点在 Java 中使用线程的最佳实践。 (答案)

这个问题与之前的问题类似, 你可以使用上面的答案。 对线程来说, 你应该:

a) 对线程命名

b) 将线程和任务分离, 使用线程池执行器来执行 Runnable 或 Callable。

c) 使用线程池

79) 说出 5 条 IO 的最佳实践(答案)

IO 对 Java 应用的性能非常重要。理想情况下,你不应该在你应用的关键路径上避免 IO 操

作。 下面是一些你应该遵循的 Java IO 最佳实践:

a) 使用有缓冲区的 IO 类, 而不要单独读取字节或字符。

b) 使用 NIO 和 NIO2

c) 在 finally 块中关闭流, 或者使用 try-with-resource 语句。

d) 使用内存映射文件获取更快的 IO。

80) 列出 5 个应该遵循的 JDBC 最佳实践(答案)

有很多的最佳实践, 你可以根据你的喜好来例举。 下面是一些更通用的原则:

a) 使用批量的操作来插入和更新数据

b) 使用 PreparedStatement 来避免 SQL 异常, 并提高性能。

c) 使用数据库连接池

d) 通过列名来获取结果集, 不要使用列的下标来获取。

81) 说出几条 Java 中方法重载的最佳实践? (答案)

下面有几条可以遵循的方法重载的最佳实践来避免造成自动装箱的混乱。

a) 不要重载这样的方法: 一个方法接收 int 参数, 而另个方法接收 Integer 参数。

b) 不要重载参数数量一致, 而只是参数顺序不同的方法。

c) 如果重载的方法参数个数多于 5 个, 采用可变参数。

Date、 Time 及 Calendar 的面试题

82) 在多线程环境下, SimpleDateFormat 是线程安全的吗? (答案)

不是, 非常不幸, DateFormat 的所有实现, 包括 SimpleDateFormat 都不是线程安全的,

因此你不应该在多线程序中使用, 除非是在对外线程安全的环境中使用, 如 将SimpleDateFormat 限制在 ThreadLocal 中。 如果你不这么做, 在解析或者格式化日期的时

候, 可能会获取到一个不正确的结果。 因此, 从日期、 时间处理的所有实践来说, 我强力推

荐 joda-time 库。

83) Java 中如何格式化一个日期? 如格式化为 ddMMyyyy 的形式? (答案)

Java 中, 可以使用 SimpleDateFormat 类或者 joda-time 库来格式日期。 DateFormat 类

允许你使用多种流行的格式来格式化日期。 参见答案中的示例代码, 代码中演示了将日期格

式化成不同的格式, 如 dd-MM-yyyy 或 ddMMyyyy。

84) Java 中, 怎么在格式化的日期中显示时区? (答案)

其实在格式化的加上Z,表示的就是时区!

85) Java 中 java.util.Date 与 java.sql.Date 有什么区别? (答案)

java.util.Date 就是在除了SQL语句的情况下面使用

java.sql.Date 是针对SQL语句使用的,它只包含日期而没有时间部分

转换是

java.sql.Date date = new Java.sql.Date();

java.util.Date sqlDate = new java.util.Date (date.getTime());

直接说就是:java.sql.Date就是与数据库Date相对应的一个类型,而java.util.Date是纯java的Date

87) Java 中, 如何将字符串 YYYYMMDD 转换为日期? (答案)

单元测试 JUnit 面试题

89) 如何测试静态方法? (答案)

可以使用 PowerMock 库来测试静态方法。

90) 怎么利用 JUnit 来测试一个方法的异常? (答案)

91) 你使用过哪个单元测试库来测试你的 Java 程序? (答案)

92) @Before 和 @BeforeClass 有什么区别? (答案)

@Before:初始化方法   对于每一个测试方法都要执行一次(注意与BeforeClass区别,后者是对于所有方法执行一次)

@After:释放资源  对于每一个测试方法都要执行一次(注意与AfterClass区别,后者是对于所有方法执行一次)

@Test:测试方法,在这里可以测试期望异常和超时时间

@Test(expected=ArithmeticException.class)检查被测方法是否抛出ArithmeticException异常

@Ignore:忽略的测试方法

@BeforeClass:针对所有测试,只执行一次,且必须为static void

@AfterClass:针对所有测试,只执行一次,且必须为static void

一个JUnit4的单元测试用例执行顺序为:

@BeforeClass -> @Before -> @Test -> @After -> @AfterClass;

每一个测试方法的调用顺序为:

@Before -> @Test -> @After;

编程和代码相关的面试题

93) 怎么检查一个字符串只包含数字? (解决方案)

一、用JAVA自带的函数

public static boolean isNumeric(String str){

for (int i = str.length();--i>=0;){

if (!Character.isDigit(str.charAt(i))){

return false;

}

}

return true;

}

94) Java 中如何利用泛型写一个 LRU 缓存? (答案<)

95) 写一段 Java 程序将 byte 转换为 long? (答案)

95) 在不使用 StringBuffer 的前提下, 怎么反转一个字符串? (解决方案)

97) Java 中, 怎么获取一个文件中单词出现的最高频率? (解决方案)

98) 如何检查出两个给定的字符串是反序的? (解决方案)

99) Java 中, 怎么打印出一个字符串的所有排列? (解决方案)

100) Java 中, 怎样才能打印出数组中的重复元素? (解决方案)

101) Java 中如何将字符串转换为整数? (解决方案)

102) 在没有使用临时变量的情况如何交换两个整数变量的值? (解决方案)

关于 OOP 和设计模式的面试题

这部分包含 Java 面试过程中关于 SOLID 的设计原则, OOP 基础, 如类, 对象, 接口, 继

承, 多态, 封装, 抽象以及更高级的一些概念, 如组合、 聚合及关联。 也包含了 GOF 设计

模式的问题。

103) 接口是什么? 为什么要使用接口而不是直接使用具体类?

接口用于定义 API。 它定义了类必须得遵循的规则。 同时, 它提供了一种抽象, 因为客户端

只使用接口, 这样可以有多重实现, 如 List 接口, 你可以使用可随机访问的 ArrayList,

也可以使用方便插入和删除的 LinkedList。 接口中不允许写代码, 以此来保证抽象, 但是

Java 8 中你可以在接口声明静态的默认方法, 这种方法是具体的。

104) Java 中, 抽象类与接口之间有什么不同? (答案)

Java 中, 抽象类和接口有很多不同之处, 但是最重要的一个是 Java 中限制一个类只能继

承一个类, 但是可以实现多个接口。 抽象类可以很好的定义一个家族类的默认行为, 而接口

能更好的定义类型, 有助于后面实现多态机制。 关于这个问题的讨论请查看答案。105) 除了单例模式, 你在生产环境中还用过什么设计模式?

这需要根据你的经验来回答。 一般情况下, 你可以说依赖注入, 工厂模式, 装饰模式或者观

察者模式, 随意选择你使用过的一种即可。 不过你要准备回答接下的基于你选择的模式的问

题。

106) 你能解释一下里氏替换原则吗?(答案)

107) 什么情况下会违反迪米特法则? 为什么会有这个问题? (答案)

迪米特法则建议“只和朋友说话, 不要陌生人说话” , 以此来减少类之间的耦合。

108) 适配器模式是什么? 什么时候使用?

适配器模式提供对接口的转换。 如果你的客户端使用某些接口, 但是你有另外一些接口, 你

就可以写一个适配去来连接这些接口。

109) 什么是“依赖注入” 和“控制反转” ? 为什么有人使用? (答案)

110) 抽象类是什么? 它与接口有什么区别? 你为什么要使用过抽象类? (答案)

111) 构造器注入和 setter 依赖注入, 那种方式更好? (答案)

每种方式都有它的缺点和优点。 构造器注入保证所有的注入都被初始化, 但是 setter 注入

提供更好的灵活性来设置可选依赖。 如果使用 XML 来描述依赖, Setter 注入的可读写会更

强。 经验法则是强制依赖使用构造器注入, 可选依赖使用 setter 注入。

112) 依赖注入和工程模式之间有什么不同? (答案)

虽然两种模式都是将对象的创建从应用的逻辑中分离, 但是依赖注入比工程模式更清晰。 通

过依赖注入, 你的类就是 POJO, 它只知道依赖而不关心它们怎么获取。 使用工厂模式, 你

的类需要通过工厂来获取依赖。 因此, 使用 DI 会比使用工厂模式更容易测试。 关于这个话

题的更详细讨论请参见答案。

113) 适配器模式和装饰器模式有什么区别? (答案)

虽然适配器模式和装饰器模式的结构类似, 但是每种模式的出现意图不同。 适配器模式被用

于桥接两个接口, 而装饰模式的目的是在不修改类的情况下给类增加新的功能。

114) 适配器模式和代理模式之前有什么不同? (答案)

这个问题与前面的类似, 适配器模式和代理模式的区别在于他们的意图不同。 由于适配器模

式和代理模式都是封装真正执行动作的类, 因此结构是一致的, 但是适配器模式用于接口之

间的转换, 而代理模式则是增加一个额外的中间层, 以便支持分配、 控制或智能访问。

115) 什么是模板方法模式? (答案)

模板方法提供算法的框架, 你可以自己去配置或定义步骤。 例如, 你可以将排序算法看做是

一个模板。 它定义了排序的步骤, 但是具体的比较, 可以使用 Comparable 或者其语言中类

似东西, 具体策略由你去配置。 列出算法概要的方法就是众所周知的模板方法。

116) 什么时候使用访问者模式? (答案)

访问者模式用于解决在类的继承层次上增加操作, 但是不直接与之关联。 这种模式采用双派

发的形式来增加中间层。

117) 什么时候使用组合模式? (答案)

组合模式使用树结构来展示部分与整体继承关系。它允许客户端采用统一的形式来对待单个

对象和对象容器。 当你想要展示对象这种部分与整体的继承关系时采用组合模式。

118) 继承和组合之间有什么不同? (答案)

虽然两种都可以实现代码复用, 但是组合比继承共灵活, 因为组合允许你在运行时选择不同

的实现。 用组合实现的代码也比继承测试起来更加简单。

119) 描述 Java 中的重载和重写? (答案)

重载和重写都允许你用相同的名称来实现不同的功能, 但是重载是编译时活动, 而重写是运

行时活动。 你可以在同一个类中重载方法, 但是只能在子类中重写方法。 重写必须要有继承。120) Java 中, 嵌套公共静态类与顶级类有什么不同? (答案)

类的内部可以有多个嵌套公共静态类, 但是一个 Java 源文件只能有一个顶级公共类, 并且

顶级公共类的名称与源文件名称必须一致。

121) OOP 中的 组合、 聚合和关联有什么区别? (答案)

如果两个对象彼此有关系, 就说他们是彼此相关联的。 组合和聚合是面向对象中的两种形式

的关联。 组合是一种比聚合更强力的关联。 组合中, 一个对象是另一个的拥有者, 而聚合则

是指一个对象使用另一个对象。 如果对象 A 是由对象 B 组合的, 则 A 不存在的话, B 一

定不存在, 但是如果 A 对象聚合了一个对象 B, 则即使 A 不存在了, B 也可以单独存在。

122) 给我一个符合开闭原则的设计模式的例子? (答案)

开闭原则要求你的代码对扩展开放, 对修改关闭。 这个意思就是说, 如果你想增加一个新的

功能, 你可以很容易的在不改变已测试过的代码的前提下增加新的代码。 有好几个设计模式

是基于开闭原则的, 如策略模式, 如果你需要一个新的策略, 只需要实现接口, 增加配置,

不需要改变核心逻辑。 一个正在工作的例子是 Collections.sort() 方法, 这就是基于策略

模式, 遵循开闭原则的, 你不需为新的对象修改 sort() 方法, 你需要做的仅仅是实现你自

己的 Comparator 接口。

123) 抽象工厂模式和原型模式之间的区别? (答案)

124) 什么时候使用享元模式? (答案)

享元模式通过共享对象来避免创建太多的对象。 为了使用享元模式, 你需要确保你的对象是

不可变的, 这样你才能安全的共享。 JDK 中 String 池、 Integer 池以及 Long 池都是很好

的使用了享元模式的例子。

Java 面试中其他各式各样的问题

这部分包含 Java 中关于 XML 的面试题, JDBC 面试题, 正则表达式面试题, Java 错误和

异常及序列化面试题

125) 嵌套静态类与顶级类有什么区别? (答案)

一个公共的顶级类的源文件名称与类名相同, 而嵌套静态类没有这个要求。 一个嵌套类位于

顶级类内部, 需要使用顶级类的名称来引用嵌套静态类, 如 HashMap.Entry 是一个嵌套静

态类, HashMap 是一个顶级类, Entry 是一个嵌套静态类。

126) 你能写出一个正则表达式来判断一个字符串是否是一个数字吗? (解决方案)

一个数字字符串, 只能包含数字, 如 0 到 9 以及 +、 - 开头, 通过这个信息, 你可以下一

个如下的正则表达式来判断给定的字符串是不是数字。

127) Java 中, 受检查异常 和 不受检查异常的区别? (答案)

受检查异常编译器在编译期间检查。 对于这种异常, 方法强制处理或者通过 throws 子句声

明。 其中一种情况是 Exception 的子类但不是 RuntimeException 的子类。 非受检查是

RuntimeException 的子类, 在编译阶段不受编译器的检查。

128) Java 中, throw 和 throws 有什么区别? (答案)

throw 用于抛出 java.lang.Throwable 类的一个实例化对象, 意思是说你可以通过关键字

throw 抛出一个 Error 或者 一个 Exception, 如:

throw new IllegalArgumentException(“size must be multiple of 2″ )

而 throws 的作用是作为方法声明和签名的一部分, 方法被抛出相应的异常以便调用者能处

理。 Java 中, 任何未处理的受检查异常强制在 throws 子句中声明。

129) Java 中, Serializable 与 Externalizable 的区别? (答案)

Serializable 接口是一个序列化 Java 类的接口, 以便于它们可以在网络上传输或者可以

将它们的状态保存在磁盘上, 是 JVM 内嵌的默认序列化方式, 成本高、 脆弱而且不安全。Externalizable 允许你控制整个序列化过程, 指定特定的二进制格式, 增加安全机制。

130) Java 中, DOM 和 SAX 解析器有什么不同? (答案)

DOM 解析器将整个 XML 文档加载到内存来创建一棵 DOM 模型树, 这样可以更快的查找节点

和修改 XML 结构, 而 SAX 解析器是一个基于事件的解析器, 不会将整个 XML 文档加载到

内存。 由于这个原因, DOM 比 SAX 更快, 也要求更多的内存, 不适合于解析大 XML 文件。

131) 说出 JDK 1.7 中的三个新特性? (答案)

虽 然 JDK 1.7 不 像 JDK 5 和 8 一 样 的 大 版 本 , 但 是 , 还 是 有 很 多 新 的 特 性 , 如

try-with-resource 语句, 这样你在使用流或者资源的时候, 就不需要手动关闭, Java 会

自动关闭。 Fork-Join 池某种程度上实现 Java 版的 Map-reduce。 允许 Switch 中有

String 变量和文本。 菱形操作符(<>)用于类型推断, 不再需要在变量声明的右边申明泛型,

因此可以写出可读写更强、 更简洁的代码。 另一个值得一提的特性是改善异常处理, 如允许

在同一个 catch 块中捕获多个异常。

132) 说出 5 个 JDK 1.8 引入的新特性? (答案)

Java 8 在 Java 历史上是一个开创新的版本, 下面 JDK 8 中 5 个主要的特性:

Lambda 表达式, 允许像对象一样传递匿名函数

Stream API, 充分利用现代多核 CPU, 可以写出很简洁的代码

Date 与 Time API, 最终, 有一个稳定、 简单的日期和时间库可供你使用

扩展方法, 现在, 接口中可以有静态、 默认方法。

重复注解, 现在你可以将相同的注解在同一类型上使用多次。

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

在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。
在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。

2.是否可以从一个static方法内部发出对非static方法的调用? 

不可以。因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用时不需要创建对象,可以直接调用。也就是说,当一个static方法被调用时,可能还没有创建任何实例对象,如果从一个static方法中发出对非static方法的调用,那个非static方法是关联到哪个对象上的呢?这个逻辑无法成立,所以,一个static方法内部发出对非static方法的调用。

3.Integer与int的区别

int是java提供的8种原始数据类型之一。Java为每个原始类型提供了封装类,Integer是java为int提供的封装类。int的默认值为0,而Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况,例如,要想表达出没有参加考试和考试成绩为0的区别,则只能使用Integer。在JSP开发中,Integer的默认为null,所以用el表达式在文本框中显示时,值为空白字符串,而int默认的默认值为0,所以用el表达式在文本框中显示时,结果为0,所以,int不适合作为web层的表单数据的类型。
在Hibernate中,如果将OID定义为Integer类型,那么Hibernate就可以根据其值是否为null而判断一个对象是否是临时的,如果将OID定义为了int类型,还需要在hbm映射文件中设置其unsaved-value属性为0。
另外,Integer提供了多个与整数相关的操作方法,例如,将一个字符串转换成整数,Integer中还定义了表示整数的最大值和最小值的常量

4.Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型? 

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

5.构造器Constructor是否可被override? 

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

6.接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承具体类(concrete class)? 抽象类中是否可以有静态的main方法?

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

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

面向对象编程就是按现实业务一样的方式将程序代码按一个个对象进行组织和编写,让计算机系统能够识别和理解用对象方式组织和编写的程序代码,这样就可以把现实生活中的业务对象映射到计算机系统中。
面向对象的编程语言有封装、继承 、抽象、多态等4个主要的特征。

封装:
封装是保证软件部件具有优良的模块性的基础,封装的目标就是要实现软件部件的“高内聚、低耦合”,防止程序相互依赖性而带来的变动影响。在面向对象的编程语言中,对象是封装的最基本单位,面向对象的封装比传统语言的封装更为清晰、更为有力。面向对象的封装就是把描述一个对象的属性和行为的代码封装在一个“模块”中,也就是一个类中,属性用变量定义,行为用方法进行定义,方法可以直接访问同一个对象中的属性。通常情况下,只要记住让变量和访问这个变量的方法放在一起,将一个类中的成员变量全部定义成私有的,只有这个类自己的方法才可以访问到这些成员变量,这就基本上实现对象的封装,就很容易找出要分配到这个类上的方法了,就基本上算是会面向对象的编程了。把握一个原则:把对同一事物进行操作的方法和相关的方法放在同一个类中,把方法和它操作的数据放在同一个类中。

抽象:
抽象就是找出一些事物的相似和共性之处,然后将这些事物归为一个类,这个类只考虑这些事物的相似和共性之处,并且会忽略与当前主题和目标无关的那些方面,将注意力集中在与当前目标有关的方面。例如,看到一只蚂蚁和大象,你能够想象出它们的相同之处,那就是抽象。抽象包括行为抽象和状态抽象两个方面。

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

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

8.java中实现多态的机制是什么? 

靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象,而程序调用的方法在运行期才动态绑定,就是引用变量所指向的具体实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变量的类型中定义的方法。

9.abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized? 

abstract的method 不可以是static的,因为抽象的方法是要被子类实现的,而static与子类扯不上关系!
native方法表示该方法要用另外一种依赖平台的编程语言实现的,不存在着被子类实现的问题,所以,它也不能是抽象的,不能与abstract混用。

10.什么是内部类?Static Nested Class 和 Inner Class的不同。

内部类就是在一个类的内部定义的类,内部类中不能定义静态成员(静态成员不是对象的特性,只是为了找一个容身之处,所以需要放到一个类中而已,这么一点小事,你还要把它放到类内部的一个类中,过分了啊!提供内部类,不是为让你干这种事情,无聊,不让你干。我想可能是既然静态成员类似c语言的全局变量,而内部类通常是用于创建内部对象用的,所以,把“全局变量”放在内部类中就是毫无意义的事情,既然是毫无意义的事情,就应该被禁止),内部类可以直接访问外部类中的成员变量,内部类可以定义在外部类的方法外面,也可以定义在外部类的方法体中

在方法体外面定义的内部类的访问类型可以是public,protecte,默认的,private等4种类型,这就好像类中定义的成员变量有4种访问类型一样,它们决定这个内部类的定义对其他类是否可见;对于这种情况,我们也可以在外面创建内部类的实例对象,创建内部类的实例对象时,一定要先创建外部类的实例对象,然后用这个外部类的实例对象去创建内部类的实例对象,

在方法内部定义的内部类前面不能有访问类型修饰符,就好像方法中定义的局部变量一样,但这种内部类的前面可以使用final或abstract修饰符。这种内部类对其他类是不可见的其他类无法引用这种内部类,但是这种内部类创建的实例对象可以传递给其他类访问。这种内部类必须是先定义,后使用,即内部类的定义代码必须出现在使用该类之前,这与方法中的局部变量必须先定义后使用的道理也是一样的。这种内部类可以访问方法体中的局部变量,但是,该局部变量前必须加final修饰符。

在方法体内部还可以采用如下语法来创建一种匿名内部类,即定义某一接口或类的子类的同时,还创建了该子类的实例对象,无需为该子类定义名称

最后,在方法外部定义的内部类前面可以加上static关键字,从而成为Static Nested Class,它不再具有内部类的特性,所有,从狭义上讲,它不是内部类。Static Nested Class与普通类在运行时的行为和功能上没有什么区别,只是在编程引用时的语法上有一些差别,它可以定义成public、protected、默认的、private等多种类型,而普通类只能定义成public和默认的这两种类型。在外面引用Static Nested Class类的名称为“外部类名.内部类名”。在外面不需要创建外部类的实例对象,就可以直接创建Static Nested Class,例如,假设Inner是定义在Outer类中的Static Nested Class,那么可以使用如下语句创建Inner类:
Outer.Inner inner = new Outer.Inner();
由于static Nested Class不依赖于外部类的实例对象,所以,static Nested Class能访问外部类的非static成员变量。当在外部类中访问Static Nested Class时,可以直接使用Static Nested Class的名字,而不需要加上外部类的名字了,在Static Nested Class中也可以直接引用外部类的static的成员变量,不需要加上外部类的名字。
在静态方法中定义的内部类也是Static Nested Class,这时候不能在类前面加static关键字,静态方法中的Static Nested Class与普通方法中的内部类的应用方式很相似,它除了可以直接访问外部类中的static的成员变量,还可以访问静态方法中的局部变量,但是,该局部变量前必须加final修饰符。

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

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

12.String是最基本的数据类型吗? 

基本数据类型包括byte、int、char、long、float、double、boolean和short。 
java.lang.String类是final类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应该用StringBuffer类 ,并且string不可以继承。

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

如果不查jdk api,我很难写出来!我可以说说我的思路:
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();}

14.数组有没有length()这个方法? String有没有length()这个方法? 

数组没有length()这个方法,有length的属性。String有有length()这个方法。

15.final, finally, finalize的区别。 

final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。 
内部类要访问局部变量,局部变量必须定义成final类型,

finally是异常处理语句结构的一部分,表示总是执行。
finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。JVM不保证此方法总被调用

16. 解释下java的跨平台特性?

虽然不知道什么是跨平台也可以使用Java语言进行编程,但是对于一个Java编程员来说,理解跨平台特性能够更深入掌握Java语言,所以企业中往往要求应聘者至少理解这个特性。

参考答案:Java的跨平台特性也被称为可移植性、平台无关性,或者一次编写处处运行。他的意思就是如果用Java语言编写一个应用,那么就可以在不同平台上运行,而不需要为不同平台单独运行开发。之所以能实现跨平台的特性。主要得益于Java虚拟机(JVM),JVM解释器在运行Java应用时根据当前平台进行解释,解释成符合当前平台规范的机器码,所以可以实现同样的应用在不同平台上都能运行。

17. 请举例java语言的主要特点?

解析:了解一门语言,往往从熟悉该语言的主要特点开始入手,所以企业也常常通过应聘者对JAVA语言特点的掌握程度而判断其语言基础是否扎实。

参考答案:JAVA语言有很多特点,主要包括①跨平台性:一个应用可以不经过修改直接运行到不同的平台上。②面 向 对 象:J AV      A   语言是一门面向对面的语言,可以使用对象的属性和行为,可以使用面向对象的思想进行分析设计,并实现整个应用。③解释执行JAVA应用时,JVM中的解释器将解释类文件,生成符合当前平台的字节码。④自动回收:JAVA应用中的垃圾回收是自动进行的,JVM中的后台线程将监视内存中数据的使用,当内存中的数据不再被引用时,将被作为垃圾回收,而不需要程序员动手回收。

1、面向对象的特征有哪些方面? 【基础】

答:面向对象的特征主要有以下几个方面:

1)抽象:抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地

注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一

部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。

2)继承:继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了

一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称

为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原

始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变 量 ,

并且类可以修改或增加新的方法使之更适合特殊的需要。

3)封装:封装是把过程和数据包围起来,对数据的访问只能通过已定义的界 面 。

面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封

装的对象,这些对象通过一个受保护的接口访问其他对象。

4)多态性:多态性是指允许不同类的对象对同一消息作出响应。多态性包括参

数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享、代码共享的

优势,很好的解决了应用程序函数同名问题。

2、作用域 public,private,protected,以及不写时的区别?【基础】

答:区别如下:

作用域 当前类 同包 子孙类 其他

public √ √ √ √

第 2 页 共 59 页

protected √ √ √ ×

default √ √ × ×

private √ × × ×

不写时默认为 default。

11、heap 和 stack 有什么区别?【基础】

答:栈是一种线形集合,其添加和删除元素的操作应在同一段完成,栈按照后进

先出的方式进行处理;堆是栈的一个组成元素。

12、Math.round(11.5) 等于多少? Math.round(-11.5)等于多少? 【基础】

答: Math.round(11.5)==12 Math.round(-11.5)==-11 round 方法返回与参数

最接近的长整数,参数加 1/2 后求其 floor。

14、编程题: 用最有效率的方法算出 2 乘以 8 等於几? 【基础】

答: 2 << 3。

16、在 JAVA 中,如何跳出当前的多重嵌套循环?【基础】

答:在最外层循环前加 label 标识,然后用 break:label 方法即可跳出多重循环

19、是否可以继承 String 类? 【基础】

答:String 类是 final 类,故不可以继承

20、以下二条语句返回值为 true 的有:

A:“beijing”==“beijing”;

B:“beijing”.equalsIgnoreCase(new String(“beijing” )); 【基础】

答: A 和 B 。

21、当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,

并可返回变化后的结果,那么这里到底是值传递还是引用传递? 【基础】

答:是值传递。Java 编程语言只有值传递参数。当一个对象实例作为一个参数

被传递到方法中时,参数的值就是对该对象的引用。对象的内容可以在被调用的

方法中改变,但对象的引用是永远不会改变的

26、定义类 A 和类 B 如下: 【基础】

class A {

int a=1;

double d=2.0;

void show(){

System.out.println("Class A: a="+a +"\td="+d);

}

}

class B extends A{

第 5 页 共 59 页

float a=3.0f;

String d="Java program.";

void show(){

super.show( );

System.out.println("Class B: a="+a +"\td="+d);

}

}

(1) 若在应用程序的 main 方法中有以下语句:

A a=new A();

a.show();

则输出的结果如何?

(2) 若在应用程序的 main 方法中定义类 B 的对象 b:

A b=new B();

b.show();

则输出的结果如何?

答:输出结果为:

1)Class A: a=1 d=2.0 ;

2)Class A: a=1 d=2.0

Class B: a=3.0 d=Java program。

47、在 java 中一个类被声明为 final 类型,表示了什么意思?【基础】

答:表示该类不能被继承,是顶级类。

48、下面哪些类可以被继承? 【基础】

1)java.lang.Thread (T)

第 8 页 共 59 页

2)java.lang.Number (T)

3)java.lang.Double (F)

4)java.lang.Math (F)

5)java.lang.Void (F)

6)java.lang.Class (F)

7)java.lang.ClassLoader (T)

答:1、2、7 可以被继承。

49、指出下面程序的运行结果: 【基础】

class A{

static{

System.out.print("1");

}

public A(){

System.out.print("2");

}

}

class B extends A{

static{

System.out.print("a");

}

public B(){

System.out.print("b");

}

}

public class Hello{

public static void main(String[] ars){

A ab = new B(); //执行到此处,结果: 1a2b

ab = new B(); //执行到此处,结果: 1a2b2b

}

}

答:输出结果为 1a2b2b;类的 static 代码段,可以看作是类首次加载(虚拟机加

载)执行的代码,而对于类加载,首先要执行其基类的构造,再执行其本身的构造。

50、继承时候类的执行顺序问题,一般都是选择题,问你将会打印出什么?【基 础 】

父类:

package test;

public class FatherClass {

public FatherClass() {

System.out.println("FatherClass Create");

}

}

子类:

package test;

第 9 页 共 59 页

import test.FatherClass;

public class ChildClass extends FatherClass {

public ChildClass() {

System.out.println("ChildClass Create");

}

public static void main(String[] args) {

FatherClass fc = new FatherClass();

ChildClass cc = new ChildClass();

}

}

答:输出结果为:

FatherClass Create

FatherClass Create

ChildClass Create

51、内部类的实现方式? 【基础】

答:示例代码如下:

package test;

public class OuterClass {

private class InterClass {

public InterClass() {

System.out.println("InterClass Create");

}

}

public OuterClass() {

InterClass ic = new InterClass();

System.out.println("OuterClass Create");

}

public static void main(String[] args) {

OuterClass oc = new OuterClass();

}

}

输出结果为:

InterClass Create

OuterClass Create

52、关于内部类: 【基础】

public class OuterClass {

private double d1 = 1.0;

//insert code here

}

You need to insert an inner class declaration at line 3,Which two

inner class declarations are valid?(Choose two.)

A. class InnerOne{

第 10 页 共 59 页

public static double methoda() {return d1;}

}

B. public class InnerOne{

static double methoda() {return d1;}

}

C. private class InnerOne{

double methoda() {return d1;}

}

D. static class InnerOne{

protected double methoda() {return d1;}

}

E. abstract class InnerOne{

public abstract double methoda();

}

答:答案为 C、E;说明如下:

1)静态内部类可以有静态成员,而非静态内部类则不能有静态成员;故 A 、 B

错;

2)静态内部类的非静态成员可以访问外部类的静态变量,而不可访问外部类

的非静态变量;故 D 错;

3)非静态内部类的非静态成员可以访问外部类的非静态变量;故 C 正确 。

53、数据类型之间的转换:

1)如何将数值型字符转换为数字?

2)如何将数字转换为字符?

3)如何取小数点前两位并四舍五入? 【基础】

答 : 1)调用数值类型相应包装类中的方法 parse***(String)或 valueOf(String)

即可返回相应基本类型或包装类型数值;

2)将数字与空字符串相加即可获得其所对应的字符串;另外对于基本类型

数字还可调用String 类中的valueOf(…)方法返回相应字符串,而对于包装类型

数字则可调用其 toString()方法获得相应字符串;

3)可用该数字构造一 java.math.BigDecimal 对象,再利用其 round()方法

进行四舍五入到保留小数点后两位,再将其转换为字符串截取最后两位。

54、字符串操作:如何实现字符串的反转及替换?【基础】

答:可用字符串构造一 StringBuffer 对象,然后调用 StringBuffer 中的 reverse

方法即可实现字符串的反转,调用 replace 方法即可实现字符串的替换。

55、编码转换:怎样将 GB2312 编码的字符串转换为 ISO-8859-1 编码的字符串?

【基础】

答:示例代码如下:

String s1 = "你好";

String s2 = new String(s1.getBytes("GB2312"), "ISO-8859-1");

56、写一个函数,要求输入一个字符串和一个字符长度,对该字符串进行分

隔。 【基础】

第 11 页 共 59 页

答:函数代码如下:

public String[] split(String str, int chars){

int n = (str.length()+ chars - 1)/chars;

String ret[] = new String[n];

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

if(i < n-1){

ret[i] = str.substring(i*chars , (i+1)*chars);

}else{

ret[i] = str.substring(i*chars);

}

}

return ret;

}

57、写一个函数,2 个参数,1 个字符串,1 个字节数,返回截取的字符串,要

求字符串中的中文不能出现乱码:如( “我 ABC ” , 4 )应该截为 “我 AB ” ,输入 ( “我

ABC 汉 DEF ” ,6)应该输出为“我 ABC”而不是“我 ABC+汉的半个 ” 。 【基础】

答:代码如下:

public String subString(String str, int subBytes) {

int bytes = 0; // 用来存储字符串的总字节数

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

if (bytes == subBytes) {

return str.substring(0, i);

}

char c = str.charAt(i);

if (c < 256) {

bytes += 1; // 英文字符的字节数看作 1

} else {

bytes += 2; // 中文字符的字节数看作 2

if(bytes - subBytes == 1){

return str.substring(0, i);

}

}

}

return str;

}

58、日期和时间:

1)如何取得年月日、小时分秒?

2)如何取得从 1970 年到现在的毫秒数?

3)如何取得某个日期是当月的最后一天?

4)如何格式化日期?【基础】

答: 1)创建 java.util.Calendar 实例(Calendar.getInstance()),调用其 get()

方法传入不同的参数即可获得参数所对应的值,如:

第 12 页 共 59 页

calendar.get(Calendar.YEAR);//获得年

2)以下方法均可获得该毫秒数:

Calendar.getInstance().getTimeInMillis();

System.currentTimeMillis();

3)示例代码如下:

Calendar time = Calendar.getInstance();

time.set(Calendar.DAY_OF_MONTH,

time.getActualMaximum(Calendar.DAY_OF_MONTH));

4)利用 java.text.DataFormat 类中的 format()方法可将日期格式化。

59、Java 编程,打印昨天的当前时刻。【基础】

答:public class YesterdayCurrent{

public static void main(String[] args){

Calendar cal = Calendar.getInstance();

cal.add(Calendar.DATE, -1);

System.out.println(cal.getTime());

}

}

60、java 和 javasciprt 的区别。【基础】

答: JavaScript 与 Java 是两个公司开发的不同的两个产品。Java 是 SUN 公司推

出的新一代面向对象的程序设计语言,特别适合于 Internet 应用程序开发;而

JavaScript 是 Netscape 公司的产品,其目的是为了扩展 Netscape Navigator

功能,而开发的一种可以嵌入 Web 页面中的基于对象和事件驱动的解释性语言,

它的前身是 Live Script;而 Java 的前身是 Oak 语言。下面对两种语言间的异

同作如下比较:

1)基于对象和面向对象:

Java 是一种真正的面向对象的语言,即使是开发简单的程序,必须设计对象 ;

JavaScript 是种脚本语言,它可以用来制作与网络无关的,与用户交互作用

的复杂软件。它是一种基于对象(Object Based)和事件驱动(Event Driver )

的编程语言。因而它本身提供了非常丰富的内部对象供设计人员使用;

2)解释和编译:

Java 的源代码在执行之前,必须经过编译;

JavaScript 是一种解释性编程语言,其源代码不需经过编译,由浏览器解释

执行;

3)强类型变量和类型弱变量:

Java 采用强类型变量检查,即所有变量在编译之前必须作声明;

JavaScript 中变量声明,采用其弱类型。即变量在使用前不需作声明,而是

解释器在运行时检查其数据类型;

4)代码格式不一样。

61、什么时候用 assert?【中等难度】

答:assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都

支持这种机制。一般来说,assertion 用于保证程序最基本、关键的正确性。

assertion 检查通常在开发和测试时开启。为了提高性能,在软件发布后,

第 13 页 共 59 页

assertion 检查通常是关闭的。在实现中,断言是一个包含布尔表达式的语句,

在执行这个语句时假定该表达式为 true;如果表达式计算为 false,那么系统

会报告一个 Assertionerror。

断言用于调试目的:

assert(a > 0); // throws an Assertionerror if a <= 0

断言可以有两种形式:

assert Expression1 ;

assert Expression1 : Expression2 ;

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

Expression2 可以是得出一个值的任意表达式;这个值用于生成显示更多调

试信息的 String 消息。

断言在默认情况下是禁用的,要在编译时启用断言,需使用 source 1.4 标 记 :

javac -source 1.4 Test.java

要在运行时启用断言,可使用 -enableassertions 或者 -ea 标记。

要在运行时选择禁用断言,可使用 -da 或者 -disableassertions 标记。

要在系统类中启用断言,可使用 -esa 或者 -dsa 标记。还可以在包的基础上

启用或者禁用断言。可以在预计正常情况下不会到达的任何位置上放置断言。断

言可以用于验证传递给私有方法的参数。不过,断言不应该用于验证传递给公有

方法的参数,因为不管是否启用了断言,公有方法都必须检查其参数。不过,既

可以在公有方法中,也可以在非公有方法中利用断言测试后置条件。另外,断言

不应该以任何方式改变程序的状态。

65、JAVA 语言如何进行异常处理,关键字:throws,throw,try,catch,finally

分别代表什么意义?在 try 块中可以抛出异常吗?【基础】

答:Java 通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并

第 14 页 共 59 页

提供了良好的接口。在 Java 中,每个异常都是一个对象,它是 Throwable 类或

其它子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中包含有

异常信息,调用这个对象的方法可以捕获到这个异常并进行处理。Java 的异常

处理是通过 5 个关键词来实现的:try、catch、throw、throws 和 finally。一

般情况下是用 try 来执行一段程序,如果出现异常,系统会抛出(throws)一个

异常,这时候你可以通过它的类型来捕捉(catch)它,或最后(finally)由缺

省处理器来处理;

try 用来指定一块预防所有“异常”的程序;

catch 子句紧跟在 try 块后面,用来指定你想要捕捉的“异常”的类型;

throw 语句用来明确地抛出一个“异常”;

throws 用来标明一个成员函数可能抛出的各种“异常”;

Finally 为确保一段代码不管发生什么“异常”都被执行一段代码;

可以在一个成员函数调用的外面写一个 try 语句,在这个成员函数内部写另一

个 try 语句保护其他代码。每当遇到一个 try 语句, “异常 ” 的框架就放到堆栈

上面,直到所有的 try 语句都完成。如果下一级的 try 语句没有对某种“异常 ”

进行处理,堆栈就会展开,直到遇到有处理这种“异常”的 try 语句。

67、给我一个你最常见到的 runtime exception?【基础】

答 : ArithmeticException, ArrayStoreException, BufferOverflowException,

BufferUnderflowException, CannotRedoException, CannotUndoException,

ClassCastException, CMMException, ConcurrentModificationException,

DOMException, EmptyStackException, IllegalArgumentException,

IllegalMonitorStateException, IllegalPathStateException,

IllegalStateException, ImagingOpException, IndexOutOfBoundsException,

MissingResourceException, NegativeArraySizeException,

NoSuchElementException, NullPointerException, ProfileDataException,

ProviderException, RasterFormatException, SecurityException,

SystemException, UndeclaredThrowableException,

UnmodifiableSetException, UnsupportedOperationException

. 1. 什么是 Java 虚拟机 ? 为什么 Java 被称作是“ “ 平台无关的编程语言” ” ?

Java 虚拟机是一个可以执行 Java 字节码的虚拟机进程。Java 源文件被编译成能被 Java 虚拟

机执行的字节码文件。

Java 被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写

或者是重新编译。Java 虚拟机让这个变为可能,因为它知道底层硬件平台的指令长度和其特性。

2. JDK 和 JRE 的区别是什么 ?

Java 运行时环境(JRE)是将要执行 Java 程序的 Java 虚拟机。它同时也包含了执行 applet 需要 的浏览器

插件。

Java 开发工具包(JDK)是完整的 Java 软件开发包,包含了 JRE,编译器和其他的工具(比如:JavaDoc,Java

调试器),可以让开发者开发、编译、执行 Java 应用程序

3. ” ”static” ” 关键字是什么意思 ?Java 中是否可以覆盖(override) 一个 private 或者是

static 的 方法 ?

“static”关键字表明一个成员变量或者是成员方法可以在没有所属的类的实例变量的情况下被访问。

Java 中 static 方法不能被覆盖,因为方法覆盖是基于运行时动态绑定的,而 static 方法是编 译时静态绑

定的。static 方法跟类的任何实例都不相关,所以概念上不适用。private 也是不支持覆盖的,因为私有的

成员外界是看不到的所以也就不存在覆盖的问题。

. 4. 是否可以在 static 环境中访问非 static 变量 ?

static 变量在 Java 中是属于类的,它在所有的实例中的值是一样的。当类被 Java 虚拟机载入 的时候,

会对 static 变量进行初始化。如果你的代码尝试不用实例来访问非 static 的变量,编译器会报错,因

为这些变量还没有被创建出来,还没有跟任何实例关联上。

. 5. Java 支持的数据类型有哪些 ? 什么是自动拆装箱 ?

Java 语言支持的 8 中基本数据类型是:

整型:byte short int long

浮点型:float double

布尔型:boolean

字符型:char

自动装箱是 Java 编译器在基本数据类型和对应的对象包装类型之间做的一个转化。比如:把 int 转化

成 Integer,double 转化成 double,等等。反之就是自动拆箱。

. 6. Java 中的方法覆盖(Overriding) 和方法重载(Overloading) 是什么意思 ?

重写方法的规则 : (方法重写也称为方法覆盖)

1、参数列表必须完全与被重写的方法相同,否则不能称其为重写而是重载。

2、返回的类型必须一直与被重写的方法的返回类型相同,否则不能称其为重写而是重载。

3、访问修饰符的限制一定要大于被重写方法的访问修饰符(public>protected>default>private)

4、重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常。例如:

父类的一个方法申明了一个检查异常 IOException,在重写这个方法是就不能抛出 Exception,只能抛出

IOException 的子类异常,可以抛出非检查异常。

而重载的规则:

1、必须具有不同的参数列表;

2、可以有不责骂的返回类型,只要参数列表不同就可以了;

3、可以有不同的访问修饰符;

4、可以抛出不同的异常;

重写与重载的区别在于:

重写多态性起作用,对调用被重载过的方法可以大大减少代码的输入量,同一个方法名只要往里面传递不

同的参数就可以拥有不同的功能或返回值。

用好重写和重载可以设计一个结构清晰而简洁的类,可以说重写和重载在编写代码过程中的作用非同一般.

7. Java 中, , 什么是构造函数 ? 什么是构造函数重载 ? 什么是复制构造函数 ?

当新对象被创建的时候,构造函数会被调用。每一个类都有构造函数。在程序员没有给类提

供构造函数的情况下,Java 编译器会为这个类创建一个默认的构造函数。

Java 中构造函数重载和方法重载很相似。可以为一个类创建多个构造函数。每一个构造函数 必须有它自

己唯一的参数列表。

Java 不支持像 C++中那样的复制构造函数,这个不同点是因为如果你不自己写构造函数的情况下,Java 不

会创建默认的复制构造函数。

8. Java 支持多继承么 ? 支持多实现吗?

不支持,Java 不支持多继承。每个类都只能继承一个类,但是可以实现多个接口。

9. 接口 可以继承接口吗 ? 如果可以继承 请 列举一个案例?

可以,List 继承 Collection

10. 接口和抽象类的区别是什么 ?

接口和抽象类有什么区别

你选择使用接口和抽象类的依据是什么?

接口和抽象类的概念不一样。接口是对动作的抽象,抽象类是对根源的抽象。

抽象类表示的是,这个对象是什么。接口表示的是,这个对象能做什么。比如, 苏格兰折耳猫 , 布偶猫 ,这

两个类(如果是类的话„„),他们的抽象类是猫。说明,他们都是猫。

猫可以吃东西,耗子也可以吃东西,你可以把“吃东西”定义成一个接口,然后让这些类去实现它.

所以,在高级语言上,一个类只能继承一个类(抽象类)(正如猫不可能同时是生物和非生物),但是可以

实现多个接口(吃饭接口、走路接口)。

第一点.接口是抽象类的变体,接口中所有的方法都是抽象的。而抽象类是声明方法的存在而不去实现它

的类。

第二点.接口可以多继承,抽象类不行

第三点.接口定义方法,不能实现,而抽象类可以实现部分方法。

第四点.接口中基本数据类型为 static 而抽类象不是的。

第五点.Java 接口中声明的变量默认都是 final 的。抽象类可以包含非 final 的变量。

第六点.Java 接口中的成员函数默认是 public 的。抽象类的成员函数可以是 private,protected 或者

是 public。

当你关注一个事物的本质的时候,用抽象类;当你关注一个操作的时候,用接口。

抽象类的功能要远超过接口,但是,定义抽象类的代价高。因为高级语言来说(从实际设计上来说也是)

每个类只能继承一个类。在这个类中,你必须继承或编写出其所有子类的

所有共性。虽然接口在功能上会弱化许多,但是它只是针对一个动作的描述。而且你可以在一个类中同时实现多个接口。在设计阶段会降低难度的。

接口是绝对抽象的,不可以被实例化。抽象类也不可以被实例化

11. 什么是值传递和引用传递 ?

对象被值传递,意味着传递了对象的一个副本。因此,就算是改变了对象副本,也不会影响 源对象的值。

对象被引用传递,意味着传递的并不是实际的对象,而是对象的引用。因此,外部对引用对 象所做的改变

会反映到所有的对象上。

12. 进程和线程的区别是什么 ?

进程是执行着的应用程序,而线程是进程内部的一个执行序列。一个进程可以有多个线程。

线程又叫做轻量级进程。

13. 创建 线程有几种不同的方式 ? 你喜欢哪一种 ? 为什么 ?

有三种方式可以用来创建线程:

继承 Thread 类

实现 Runnable 接口

应用程序可以使用 Executor 框架来创建线程池

实现 Runnable 接口这种方式更受欢迎,因为这不需要继承 Thread 类。在应用设计中已经继承了别的对

象的情况下,这需要多继承(而 Java 不支持多继承),只能实现接口。同时,线程池也是非常高效的,

很容易实现和使用。

14. 概括的解释下线程的几种可用状态。

线程在执行过程中,可以处于下面几种状态:

就绪(Runnable):线程准备运行,不一定立马就能开始执行。

运行中(Running):进程正在执行线程的代码。

等待中(Waiting):线程处于阻塞的状态,等待外部的处理结束。 睡眠中

(Sleeping):线程被强制睡眠。

I/O 阻塞(Blocked on I/O):等待 I/O 操作完成。

同步阻塞(Blocked on Synchronization):等待获取锁。

死亡(Dead):线程完成了执行

15. 同步方法和同步代码块的区别是什么 ?

在 Java 语言中,每一个对象有一把锁。线程可以使用 synchronized 关键字来获取对象上的

锁。

synchronized 关键字可应用在方法级别(粗粒度锁)或者是代码块级别(细粒度锁)。

16. 在监视器(Monitor) 内部, , 是如何做线程同步的 ? 程序应该做哪种级别的同步 ?

监视器和锁在 Java 虚拟机中是一块使用的。监视器监视一块同步代码块,确保一次只有一

个线程执行同步代码块。每一个监视器都和一个对象引用相关联。线程在获取锁之前不允许

执行同步代码。

17. 什么是死锁(deadlock) ?

两个进程都在等待对方执行完毕才能继续往下执行的时候就发生了死锁。结果就是两个进程

都陷入了无限的等待中。

18. 如何确保 N 个线程可以访问 N 个资源同时又不导致死锁 ?

使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程

按照指定的顺序获取锁。因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出 现死锁了。

19. Java 集合类框架的基本接口有哪些 ?

Java 集合类提供了一套设计良好的支持对一组对象进行操作的接口和类。Java 集合类里面最

基本的接口有:

Collection:代表一组对象,每一个对象都是它的子元素。

Set:不包含重复元素的 Collection。

List:有顺序的 collection,并且可以包含重复元素。

Map:可以把键(key)映射到值(value)的对象,键不能重复。

20. 为什么集合类没有实现 Cloneable 和 和 Serializable 接口?

集合类接口指定了一组叫做元素的对象。集合类接口的每一种具体的实现类都可以选择以它

自己的方式对元素进行保存和排序。有的集合类允许重复的键,有些不允许。

21. 什么是迭代器(Iterator) ?

Iterator 接口提供了很多对集合元素进行迭代的方法。每一个集合类都包含了可以返回迭代

器实例的 迭代方法。迭代器可以在迭代的过程中删除底层集合的元素。

克隆(cloning)或者是序列化(serialization)的语义和含义是跟具体的实现相关的。因此,应该由

集合类的具体实现来决定如何被克隆或者是序列化。

22. Iterator 和 和 ListIterator 的区别是什么?

下面列出了他们的区别:

Iterator 可用来遍历 Set 和 List 集合,但是 ListIterator 只能用来遍历 List。Iterator 对集合只能是前向遍历,ListIterator 既可以前向也可以后向。

ListIterator 实现了 Iterator 接口,并包含其他的功能,比如:增加元素,替换元素,获取前

一个和后一个元素的索引,等等。

23. 快速失败(fail-fast) 和安全失败(fail-safe) 的区别是什么?

Iterator 的安全失败是基于对底层集合做拷贝,因此,它不受源集合上修改的影响。java.util

包下面的所有的集合类都是快速失败的,而 java.util.concurrent 包下面的所有的类都是安全 失

败的。快速失败的迭代器会抛出 ConcurrentModificationException 异常,而安全失败的迭 代

器永远不会抛出这样的异常。

24. Java 中的 HashMap 的工作原理是什么?

Java 中的 HashMap 是以键值对(key-value)的形式存储元素的。HashMap 需要一个 hash 函

数,它使用 hashCode()和 equals()方法来向集合/从集合添加和检索元素。当调用 put()方法的时

候,HashMap 会计算 key 的 hash 值,然后把键值对存储在集合中合适的索引上。如果 key

已经存在了,value 会被更新成新值。HashMap 的一些重要的特性是它的容量(capacity),负 载

因子(load factor)和扩容极限(threshold resizing)。

25. hashCode()和 和 equals() 方法的重要性体现在什么地方?

Java 中的 HashMap 使用 hashCode()和 equals()方法来确定键值对的索引,当根据键获取值

的时候也会用到这两个方法。如果没有正确的实现这两个方法,两个不同的键可能会有相同的

hash 值,因此,可能会被集合认为是相等的。而且,这两个方法也用来发现重复元素。所

以这两个方法的实现对 HashMap 的精确性和正确性是至关重要的。

26. HashMap 和 和 Hashtable 有什么区别?

HashMap 和 Hashtable 都实现了 Map 接口,因此很多特性非常相似。但是,他们有以下不同点:

HashMap 允许键和值是 null,而 Hashtable 不允许键或者值是 null。

Hashtable 是同步的,而 HashMap 不是。因此,HashMap 更适合于单线程环境,而 Hashtable

适合于多线程环境。

HashMap 提供了可供应用迭代的键的集合,因此,HashMap 是快速失败的。另一方面,

Hashtable 提供了对键的列举(Enumeration)。

一般认为 Hashtable 是一个遗留的类。

27. 数组(Array) 和列表(ArrayList) 有什么区别?什么时候应该使用 Array 而不是

ArrayList ?

下面列出了 Array 和 ArrayList 的不同点:

Array 可以包含基本类型和对象类型,ArrayList 只能包含对象类型。

Array 大小是固定的,ArrayList 的大小是动态变化的。

ArrayList 提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。

对于基本类型数据,集合使用自动装箱来减少编码工作量。但是,当处理固定大小的基本数

据类型的时候,这种方式相对比较慢。

28. ArrayList 和 和 LinkedList 有什么区别?

ArrayList 和 LinkedList 都实现了 List 接口,他们有以下的不同点:

ArrayList 是基于索引的数据接口,它的底层是数组。它可以以 O(1)时间复杂度对元素进行随

机访问。与此对应,LinkedList 是以元素列表的形式存储它的数据,每一个元素都和它

的前 一个和后一个元素链接在一起,在这种情况下,查找某个元素的时间复杂度是 O(n)。

相对于 ArrayList ,LinkedList 的插入,添加,删除操作速度更快,因为当元素被添加到集合

任 意位置的时候,不需要像数组那样重新计算大小或者是更新索引。

LinkedList 比 ArrayList 更占内存,因为 LinkedList 为每一个节点存储了两个引用,一个指

向前一个元素,一个指向下一个元素。

也可以参考 ArrayList vs. LinkedList 。

29. Comparable 和 和 Comparator 接口是干什么的?列出它们的区别。

Java 提供了只包含一个 compareTo()方法的 Comparable 接口。这个方法可以个给两个对象排

序。具体来说,它返回负数,0,正数来表明输入对象小于,等于,大于已经存在的对象。

Java 提供了包含 compare()和 equals()两个方法的 Comparator 接口。compare()方法用来给两

个输入参数排序,返回负数,0,正数表明第一个参数是小于,等于,大于第二个参数。equals()

方法需要一个对象作为参数,它用来决定输入参数是否和 comparator 相等。只有当输入参

数也是一个 comparator 并且输入参数和当前 comparator 的排序结果是相同的时候,这个方

法才返回 true 。

30. 什么是 Java 优先级队列(Priority Queue) ?

PriorityQueue 是一个基于优先级堆的无界队列,它的元素是按照自然顺序(natural order)排序

的。在创建的时候,我们可以给它提供一个负责给元素排序的比较器。PriorityQueue 不允许

null 值,因为他们没有自然顺序,或者说他们没有任何的相关联的比较器。最后,PriorityQueue

不是线程安全的,入队和出队的时间复杂度是 O(log(n))。

31. 你了解大 O 符号(big-O notation) 么?你能给出不同数据结构的例子么?

大 O 符号描述了当数据结构里面的元素增加的时候,算法的规模或者是性能在最坏的场景

下有多么好。 大 O 符号也可用来描述其他的行为,比如:内存消耗。因为集合类实际上是

数据结构,我 们一般使用大 O 符号基于时间,内存和性能来选择最好的实现。大 O 符号可

以对大量数据的性能给出一个很好的说明。

32. 如何权衡是使用无序的数组还是有序的数组?

有序数组最大的好处在于查找的时间复杂度是 O(log n),而无序数组是 O(n)。有序数组的缺点是插入操作的时间复杂度是 O(n),因为值大的元素需要往后移动来给新元素腾位置。相反,

无序数组的插入时间复杂度是常量 O(1)。

33. Java 集合类框架的最佳实践有哪些?

根据应用的需要正确选择要使用的集合的类型对性能非常重要,比如:假如元素的大小是固

定的,而且能事先知道,我们就应该用 Array 而不是 ArrayList 。有些集合类允许指定初始容

量。因此,如果我们能估计出存储的元素的数目,我们可以设置

初始容量来避免重新计算 hash 值或者是扩容。为了类型安全,可读性和健壮性的原因总是要

使用泛型。同时,使用泛型还可以避免运行时的 ClassCastException。

使用 JDK 提供的不变类(immutable class)作为 Map 的键可以避免为我们自己的类实现

hashCode()和 equals()方法。

编程的时候接口优于实现。

底层的集合实际上是空的情况下,返回长度是 0 的集合或者是数组,不要返回 null。

34. Enumeration 接口和 Iterator 接口的区别有哪些?

Enumeration 速度是 Iterator 的 2 倍,同时占用更少的内存。但是,Iterator 远远比 Enumeration

安全,因为其他线程不能够修改正在被 iterator 遍历的集合里面的对象。同时,Iterator 允许

调用者删除底层集合里面的元素,这对 Enumeration 来说是不可能的。

35. HashSet 和 和 TreeSet 有什么区别?

HashSet 是由一个 hash 表来实现的,因此,它的元素是无序的。add() ,remove(),contains()

方法的时间复杂度是 O(1)。

另一方面,TreeSet 是由一个树形的结构来实现的,它里面的元素是有序的。因此,add(),

remove(),contains()方法的时间复杂度是 O(logn)。

36. Java 中垃圾回收有什么目的?什么时候进行垃圾回收?

垃圾回收的目的是识别并且丢弃应用不再使用的对象来释放和重用资源。

37. System.gc()和 和 Runtime.gc() 会做什么事情?

这两个方法用来提示 JVM 要进行垃圾回收。但是,立即开始还是延迟进行垃圾回收是取决

于 JVM 的。

38. finalize() 方法什么时候被调用?析构函数(finalization) 的目的是什么?

在释放对象占用的内存之前,垃圾收集器会调用对象的 finalize()方法。一般建议在该方法中

释放对象持有的资源。

39. 如果对象的引用被置为 null ,垃圾收集器是否会立即释放对象占用的内存?

不会,在下一个垃圾回收周期中,这个对象将是可被回收的。

40. Java 堆的结构是什么样子的?什么是堆中的永久代(Perm Gen space)?

JVM 的堆是运行时数据区,所有类的实例和数组都是在堆上分配内存。它在 JVM 启动的时

候被创建。对象所占的堆内存是由自动内存管理系统也就是垃圾收集器回收。

堆内存是由存活和死亡的对象组成的。存活的对象是应用可以访问的,不会被垃圾回收。死

亡的对象是应用不可访问尚且还没有被垃圾收集器回收掉的对象。一直到垃圾收集器把这些

对象回收掉之前,他们会一直占据堆内存空间。

41. 串行(serial) 收集器和吞吐量(throughput) 收集器的区别是什么?

吞吐量收集器使用并行版本的新生代垃圾收集器,它用于中等规模和大规模数据的应用程

序。而串行收集器对大多数的小应用(在现代处理器上需要大概 100M 左右的内存)就足够了

42. 在 在 Java 中,对象什么时候可以被垃圾回收?

当对象对当前使用这个对象的应用程序变得不可触及的时候,这个对象就可以被回收了。

43. JVM 的永久代中会发生垃圾回收么?

垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收 (Full

GC)。如果你仔细查看垃圾收集器的输出信息,就会发现永久代也是被回收的。这就是

为什么正确的永久代大小对避免 Full GC 是非常重要的原因。请参考下 Java8 :从永久代到元

数据区

(译者注:Java8 中已经移除了永久代,新加了一个叫做元数据区的 native 内存区)

43. Java 中的两种异常类型是什么 ? 他们有什么区别 ?

Java 中有两种异常:受检查的(checked)异常和不受检查的(unchecked)异常。不受检查的异常

不需要在方法或者是构造函数上声明,就算方法或者是构造函数的执行可能会抛出这样的异

常,并且不受检查的异常可以传播到方法或者是构造函数的外面。相反,受检查的异常必须 要用 throws

44. Java 中 Exception 和 Error 有什么区别 ?

Exception 和 Error 都是 Throwable 的子类。Exception 用于用户程序可以捕获的异常情况。

Error

定义了不期望被用户程序捕获的异常。

45. throw 和 throws 有什么区 别 ?

throw 关键字用来在程序中明确的抛出异常,相反,throws 语句用来表明方法不能处理的异 常。每一个方

法都必须要指定哪些异常不能处理,所以方法的调用者才能够确保处理可能发

生的异常,多个异常是用逗号分隔的。

46. 异常处理的时候, ,finally 代码块的重要性是什么 ?

无论是否抛出异常,finally 代码块总是会被执行。就算是没有 catch 语句同时又抛出异常的

情况下,finally 代码块仍然会被执行。最后要说的是,finally 代码块主要用来释放资源,比

如:I/O 缓冲区,数据库连接。

47. 异常处理完成以后, ,Exception 对象会发生什么变化 ?

Exception 对象会在下一个垃圾回收过程中被回收掉。

48. finally 代码块和 finalize() 方法有什么区别 ?

无论是否抛出异常,finally 代码块都会执行,它主要是用来释放应用占用的资源。finalize()

方法是 Object 类的一个 protected 方法,它是在对象被垃圾回收之前由 Java 虚拟机来调用

的。

73. 什么是 JDBC ?

JDBC 是允许用户在不同数据库之间做选择的一个抽象层。JDBC 允许开发者用 JAVA 写数据库

应用程序,而不需要关心底层特定数据库的细节。

74. 解释下驱动(Driver) 在 JDBC 中的角色。

JDBC 驱动提供了特定厂商对 JDBC API 接口类的实现,驱动必须要提供 java.sql 包下面这些类

的实现:Connection, Statement, PreparedStatement,CallableStatement, ResultSet 和 Driver。

75. Class.forName() 方法有什么作用 ?

这个方法用来载入跟数据库建立连接的驱动。

78. 数据库连接池是什么意思?

像打开关闭数据库连接这种和数据库的交互可能是很费时的,尤其是当客户端数量增加的时

候,会消耗大量的资源,成本是非常高的。可以在应用服务器启动的时候建立很多个数据库

连接并维护在一个池中。连接请求由池中的连接提供。在连接使用完毕以后,把连接归还到 池中,以用于

满足将来更多的请求。

79. 什么是 RMI ?

Java 远程方法调用(JavaRMI)是 Java API 对远程过程调用(RPC)提供的面向对象的等价形式,

支持直接传输序列化的 Java 对象和分布式垃圾回收。远程方法调用可以看做是激活远程正

在运行的对象上的方法的步骤。RMI 对调用者是位置透明的,因为调用者感觉方法是执行在

本地运行的对象上的。看下 RMI 的一些注意事项。

80. RMI 体系结构的基本原则是什么?

RMI 体系结构是基于一个非常重要的行为定义和行为实现相分离的原则。RMI 允许定义行为的代码和实现

行为的代码相分离,并且运行在不同的 JVM 上。

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

(1)抽象:

抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只

是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。

(2)继承:

继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生

类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。

(3)封装:

封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一

系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。

(4) 多态性:

多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享 、代码共享的优势,很好的解决了应用程序函数同名问题。

2、String是最基本的数据类型吗?

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

java.lang.String类是final类型的,因此不可以继承这个类、不能修改这个类。为了提高效率节省空间,我们应该用StringBuffer

3、int 和 Integer 有什么区别

Java 提供两种不同的类型:引用类型和原始类型(或内置类型)。Int是java的原始数据类型,Integer是java为int提供的封装类。

Java为每个原始类型提供了封装类。

原始类型封装类

booleanBoolean

charCharacter

byteByte

shortShort

intInteger

longLong

floatFloat

doubleDouble

引用类型和原始类型的行为完全不同,并且它们具有不同的语义。引用类型和原始类型具有不同的特征和用法,它们包括:大小和速

度问题,这种类型以哪种类型的数据结构存储,当引用类型和原始类型用作某个类的实例数据时所指定的缺省值。对象引用实例变量

的缺省值为 null,而原始类型实例变量的缺省值与它们的类型有关。

4、String 和StringBuffer的区别

JAVA 平台提供了两个类:String和StringBuffer,它们可以储存和操作字符串,即包含多个字符的字符数据。这个String类提供了

数值不可改变的字符串。而这个StringBuffer类提供的字符串进行修改。当你知道字符数据要改变的时候你就可以使用StringBuffer

。典型地,你可以使用StringBuffers来动态构造字符数据。

5、运行时异常与一般异常有何异同?

异常表示程序运行过程中可能出现的非正常状态,运行时异常表示虚拟机的通常操作中可能遇到的异常,是一种常见运行错误。java

编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常。

6、说出Servlet的生命周期,并说出Servlet和CGI的区别。

Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doXXX方

法(doGet,doPost)等,当服务器决定将实例销毁的时候调用其destroy方法。

与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一

般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。

7、说出ArrayList,Vector, LinkedList的存储性能和特性

ArrayList 和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索

引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程

安全),通常性能上较ArrayList差,而LinkedList使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但是插入数

据时只需要记录本项的前后项即可,所以插入速度较快。

、EJB是基于哪些技术实现的?并说出SessionBean和EntityBean的区别,StatefulBean和StatelessBean的区别。

EJB包括Session Bean、Entity Bean、Message Driven Bean,基于JNDI、RMI、JAT等技术实现。

SessionBean在J2EE应用程序中被用来完成一些服务器端的业务操作,例如访问数据库、调用其他EJB组件。EntityBean被用来代表应

用系统中用到的数据。

对于客户机,SessionBean是一种非持久性对象,它实现某些在服务器上运行的业务逻辑。

对于客户机,EntityBean是一种持久性对象,它代表一个存储在持久性存储器中的实体的对象视图,或是一个由现有企业应用程序实

现的实体。

Session Bean 还可以再细分为 Stateful Session Bean 与 Stateless Session Bean ,这两种的 Session Bean都可以将系统逻辑

放在 method之中执行,不同的是 Stateful Session Bean 可以记录呼叫者的状态,因此通常来说,一个使用者会有一个相对应的

Stateful Session Bean 的实体。Stateless Session Bean 虽然也是逻辑组件,但是他却不负责记录使用者状态,也就是说当使用

者呼叫 Stateless Session Bean 的时候,EJB Container 并不会找寻特定的 Stateless Session Bean 的实体来执行这个 method

。换言之,很可能数个使用者在执行某个 Stateless Session Bean 的 methods 时,会是同一个 Bean 的 Instance 在执行。从内

存方面来看, Stateful Session Bean 与 Stateless Session Bean 比较, Stateful Session Bean 会消耗 J2EE Server 较多的

内存,然而 Stateful Session Bean 的优势却在于他可以维持使用者的状态。

9、Collection 和 Collections的区别。

  Collection是集合类的上级接口,继承与他的接口主要有Set 和List.

Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。

10、&和&&的区别。

&是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)

12、final, finally, finalize的区别。

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

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

finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源

回收,例如关闭文件等。

13、sleep() 和 wait() 有什么区别?

sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,把执行机会给其他线程,但是监控状态依然保持,到时后会自动

恢复。调用sleep不会释放对象锁。

wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify

方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。

14、Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?

方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载

Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写

(Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被"屏蔽"了。如果在一个类中定义

了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。Overloaded的方法是可以改

变返回值的类型。

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

如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这

些数据就是共享数据,必须进行同步存取。

当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很

多情况下采用异步途径往往更有效率。

17、abstract class和interface有什么区别?

声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法

,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,其类型是一个抽象类,并让它指向具体

子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract 类的子类为它们父类中的所有抽象方法提供实现,否则它们也是

抽象类为。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。

接口(interface)是抽象类的变体。在接口中,所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法

都是抽象的,没有一个有程序体。接口只可以定义static final成员变量。接口的实现与子类相似,除了该实现类不能从接口定义中

继承行为。当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对象上

调用接口的方法。由于有抽象类,它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接

口类型转换,instanceof 运算符可以用来决定某对象的类是否实现了接口。

18、heap和stack有什么区别。

栈是一种线形集合,其添加和删除元素的操作应在同一段完成。栈按照后进先出的方式进行处理。

堆是栈的一个组成元素

21、Static Nested Class 和 Inner Class的不同。

Static Nested Class是被声明为静态(static)的内部类,它可以不依赖于外部类实例被实例化。而通常的内部类需要在外部类实

例化后才能实例化。

26、Math.round(11.5)等於多少? Math.round(-11.5)等於多少?

Math.round(11.5)==12

Math.round(-11.5)==-11

round方法返回与参数最接近的长整数,参数加1/2后求其floor.

28、设计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();

}

}

}

}

29、Java有没有goto?

java中的保留字,现在没有在java中使用。

30、启动一个线程是用run()还是start()?

启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线 程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。

33、给我一个你最常见到的runtime exception。

ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException,

CannotUndoException, ClassCastException, CMMException, ConcurrentModificationException, DOMException,

EmptyStackException, IllegalArgumentException, IllegalMonitorStateException, IllegalPathStateException,

IllegalStateException, ImagingOpException, IndexOutOfBoundsException, MissingResourceException,

NegativeArraySizeException, NoSuchElementException, NullPointerException, ProfileDataException, ProviderException,

RasterFormatException, SecurityException, SystemException, UndeclaredThrowableException, UnmodifiableSetException,

UnsupportedOperationException

34、接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)?

接口可以继承接口。抽象类可以实现(implements)接口,抽象类是否可继承实体类,但前提是实体类必须有明确的构造函数。

36、说出数据连接池的工作机制是什么?

J2EE 服务器启动时会建立一定数量的池连接,并一直维持不少于此数目的池连接。客户端程序需要连接时,池驱动程序会返回一个

未使用的池连接并将其表记为忙。如果当前没有空闲连接,池驱动程序就新建一定数量的连接,新建连接的数量由配置参数决定。当

使用的池连接调用完成后,池驱动程序将此连接表记为空闲,其他调用就可以使用这个连接。

38、数组有没有length()这个方法? String有没有length()这个方法?

数组没有length()这个方法,有length的属性。String有有length()这个方法。

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

Set里的元素是不能重复的,那么用iterator()方法来区分重复与否。equals()是判读两个Set是否相等。

equals()和==方法决定引用值是否指向同一对象equals()在类中被覆盖,为的是当两个分离的对象的内容和类型相配的话,返回真值

40、构造器Constructor是否可被override?

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

42、swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?

switch(expr1)中,expr1是一个整数表达式。因此传递给 switch 和 case 语句的参数应该是 int、 short、 char 或者 byte。

long,string 都不能作用于swtich。

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

会执行,在return前执行。

8、编程题: 写一个Singleton出来。

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的。

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

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

不对,有相同的hash code。

46、当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是

引用传递?

是值传递。Java 编程语言只有值传递参数。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用。对象

的内容可以在被调用的方法中改变,但对象的引用是永远不会改变的。

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

不能,一个对象的一个synchronized方法只能由一个线程访问。

48、编程题: 写一个Singleton出来。

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的。

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

49、Java的接口和C++的虚类的相同和不同处。

由于Java不支持多继承,而有可能某个类或对象要使用分别在几个类或对象里面的方法或属性,现有的单继承机制就不能满足要求。

与继承相比,接口有更高的灵活性,因为接口中没有任何实现代码。当一个类实现了接口以后,该类要实现接口里面所有的方法和属

性,并且接口里面的属性在默认状态下面都是public static,所有方法默认情况下是public.一个类可以实现多个接口。

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

当JAVA 程序违反了JAVA的语义规则时,JAVA虚拟机就会将发生的错误表示为一个异常。违反语义规则包括2种情况。一种是JAVA类库

内置的语义检查。例如数组下标越界,会引发IndexOutOfBoundsException;访问null的对象时会引发NullPointerException。另一种

情况就是JAVA允许程序员扩展这种语义检查,程序员可以创建自己的异常,并自由选择在何时用throw关键字引发异常。所有的异常

都是 java.lang.Thowable的子类。

51、垃圾回收的优点和原理。并考虑2种回收机制。

Java 语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程

序的时候不再需要考虑内存管理。由于有个垃圾回收机制,Java中的对象不再有"作用域"的概念,只有对象的引用才有"作用域"。垃

圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情

况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进

行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。

52、请说出你所知道的线程同步的方法。

wait():使一个线程处于等待状态,并且释放所持有的对象的lock。

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

notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定

唤醒哪个线程,而且不是按优先级。

Allnotity():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。

53、你所知道的集合类都有哪些?主要方法?

最常用的集合类是 List 和 Map。 List 的具体实现包括 ArrayList 和 Vector,它们是可变大小的列表,比较适合构建、存储和操

作任何类型对象的元素列表。 List 适用于按数值索引访问元素的情形。

Map 提供了一个更通用的元素存储方法。 Map 集合类用于存储元素对(称作"键"和"值"),其中每个键映射到一个值。

54、描述一下JVM加载class文件的原理机制?

JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader 是一个重要的Java运行时系统组件。它负责在运行时查找和

装入类文件的类。

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

能够定义成为一个中文的,因为java中以unicode编码,一个char占2个字节(Byte)共16位(bit),所以放一个中文是没问题的

57、JSP的内置对象及方法。

request表示HttpServletRequest对象。它包含了有关浏览器请求的信息,并且提供了几个用于获取cookie, header, 和session数据的有用的方法。

response表示HttpServletResponse对象,并提供了几个用于设置送回浏览器的响应的方法(如cookies,头信息等)

out对象是javax.jsp.JspWriter的一个实例,并提供了几个方法使你能用于向浏览器回送输出结果。

pageContext表示一个javax.servlet.jsp.PageContext对象。它是用于方便存取各种范围的名字空间、servlet相关的对象的API,并且包装了通用的servlet相关功能的方法。

session表示一个请求的javax.servlet.http.HttpSession对象。Session可以存贮用户的状态信息

applicaton 表示一个javax.servle.ServletContext对象。这有助于查找有关servlet引擎和servlet环境的信息

config表示一个javax.servlet.ServletConfig对象。该对象用于存取servlet实例的初始化参数。

page表示从该页面产生的一个servlet实例

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

线程指在程序执行过程中,能够执行程序代码的一个执行单位,每个程序至少都有一个线程,也就是程序本身。

Java中的线程有四种状态分别是:运行、就绪、挂起、结束。

67、J2EE是技术还是平台还是框架?

J2EE本身是一个标准,一个为企业分布式应用的开发提供的标准平台。

J2EE也是一个框架,包括JDBC、JNDI、RMI、JMS、EJB、JTA等技术。

68、我们在web应用开发过程中经常遇到输出某种编码的字符,如iso8859-1等,如何输出一个某种编码的字符串?

Public String translate (String str) {

String tempStr = "";

try {

tempStr = new String(str.getBytes("ISO-8859-1"), "GBK");

tempStr = tempStr.trim();

}

catch (Exception e) {

System.err.println(e.getMessage());

}

return tempStr;

}

69、简述逻辑操作(&,|,^)与条件操作(&&,||)的区别。

区别主要答两点:a.条件操作只能操作布尔型的,而逻辑操作不仅可以操作布尔型,而且可以操作数值型

b.逻辑操作不会产生短路

70、XML文档定义有几种形式?它们之间有何本质区别?解析XML文档有哪几种方式?

a: 两种形式 dtd schema

b: 本质区别:schema本身是xml的,可以被XML解析器解析(这也是从DTD上发展schema的根本目的)

c:有DOM,SAX,STAX等

DOM:处理大型文件时其性能下降的非常厉害。这个问题是由DOM的树结构所造成的,这种结构占用的内存较多,而且DOM必须在解析文

件之前把整个文档装入内存,适合对XML的随机访问

SAX:不现于DOM,SAX是事件驱动型的XML解析方式。它顺序读取XML文件,不需要一次全部装载整个文件。当遇到像文件开头,文档结

束,或者标签开头与标签结束时,它会触发一个事件,用户通过在其回调事件中写入处理代码来处理XML文件,适合对XML的顺序访问

STAX:Streaming API for XML (StAX)

xml文档有两种定义方法:

dtd:数据类型定义(data type definition),用以描述XML文档的文档结构,是早期的XML文档定义形式。

schema:其本身是基于XML语言编写的,在类型和语法上的限定能力比dtd强,处理也比较方便,因为此正逐渐代替dtd成为新的模式

定义语言。

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

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

主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放

,并且必须在finally从句中释放。

72、EJB的角色和三个对象

一个完整的基于EJB的分布式计算结构由六个角色组成,这六个角色可以由不同的开发商提供,每个角色所作的工作必须遵循Sun公司

提供的EJB规范,以保证彼此之间的兼容性。这六个角色分别是EJB组件开发者(Enterprise Bean Provider) 、应用组合者

(Application Assembler)、部署者(Deployer)、EJB 服务器提供者(EJB Server Provider)、EJB 容器提供者(EJB

Container Provider)、系统管理员(System Administrator)

三个对象是Remote(Local)接口、Home(LocalHome)接口,Bean类

73、EJB容器提供的服务

主要提供声明周期管理、代码产生、持续性管理、安全、事务管理、锁和并发行管理等服务。

74、EJB规范规定EJB中禁止的操作有哪些?

1. 不能操作线程和线程API(线程API指非线程对象的方法如notify,wait等),2.不能操作awt,3.不能实现服务器功能,4.不能对静

态属生存取,5.不能使用IO操作直接存取文件系统,6.不能加载本地库.,7.不能将this作为变量和返回,8.不能循环调用。

75、remote接口和home接口主要作用

remote接口定义了业务方法,用于EJB客户端调用业务方法。

home接口是EJB工厂用于创建和移除查找EJB实例

76、bean 实例的生命周期

对于Stateless Session Bean、Entity Bean、Message Driven Bean一般存在缓冲池管理,而对于Entity Bean和Statefull Session

Bean存在Cache管理,通常包含创建实例,设置上下文、创建EJB Object(create)、业务方法调用、remove等过程,对于存在缓冲

池管理的Bean,在create之后实例并不从内存清除,而是采用缓冲池调度机制不断重用实例,而对于存在Cache管理的Bean则通过激

活和去激活机制保持Bean的状态并限制内存中实例数量。

77、EJB的激活机制

以Stateful Session Bean 为例:其Cache大小决定了内存中可以同时存在的Bean实例的数量,根据MRU或NRU算法,实例在激活和去

激活状态之间迁移,激活机制是当客户端调用某个EJB实例业务方法时,如果对应EJB Object发现自己没有绑定对应的Bean实例则从

其去激活Bean存储中(通过序列化机制存储实例)回复(激活)此实例。状态变迁前会调用对应的 ejbActive和ejbPassivate方法。

78、EJB的几种类型

会话(Session)Bean ,实体(Entity)Bean 消息驱动的(Message Driven)Bean

会话Bean又可分为有状态(Stateful)和无状态(Stateless)两种

实体Bean可分为Bean管理的持续性(BMP)和容器管理的持续性(CMP)两种

79、客服端调用EJB对象的几个基本步骤

设置JNDI服务工厂以及JNDI服务地址系统属性,查找Home接口,从Home接口调用Create方法创建Remote接口,通过Remote接口调用其

业务方法。

80、如何给weblogic指定大小的内存?

在启动Weblogic的脚本中(位于所在Domian对应服务器目录下的startServerName),增加set MEM_ARGS=-Xms32m -Xmx200m,可以调

整最小内存为32M,最大200M

81、如何设定的weblogic的热启动模式(开发模式)与产品发布模式?

可以在管理控制台中修改对应服务器的启动模式为开发或产品模式之一。或者修改服务的启动文件或者commenv文件,增加set

PRODUCTION_MODE=true。

82、如何启动时不需输入用户名与密码?

修改服务启动文件,增加 WLS_USER和WLS_PW项。也可以在boot.properties文件中增加加密过的用户名和密码.

83、在weblogic管理制台中对一个应用域(或者说是一个网站,Domain)进行jms及ejb或连接池等相关信息进行配置后,实际保存在什么

文件中?

保存在此Domain的config.xml文件中,它是服务器的核心配置文件。

84、说说weblogic中一个Domain的缺省目录结构?比如要将一个简单的helloWorld.jsp放入何目录下,然的在浏览器上就可打入主机:

端口号//helloword.jsp就可以看到运行结果了? 又比如这其中用到了一个自己写的javaBean该如何办?

Domain 目录服务器目录applications,将应用目录放在此目录下将可以作为应用访问,如果是Web应用,应用目录需要满足Web应用

目录要求,jsp文件可以直接放在应用目录中,Javabean需要放在应用目录的WEB-INF目录的classes目录中,设置服务器的缺省应用

将可以实现在浏览器上无需输入应用名。

85、在weblogic中发布ejb需涉及到哪些配置文件

不同类型的EJB涉及的配置文件不同,都涉及到的配置文件包括ejb-jar.xml,weblogic-ejb-jar.xmlCMP实体Bean一般还需要

weblogic-cmp-rdbms-jar.xml

86、如何在weblogic中进行ssl配置与客户端的认证配置或说说j2ee(标准)进行ssl的配置

缺省安装中使用DemoIdentity.jks和DemoTrust.jks KeyStore实现SSL,需要配置服务器使用Enable SSL,配置其端口,在产品模式

下需要从CA获取私有密钥和数字证书,创建identity和trust keystore,装载获得的密钥和数字证书。可以配置此SSL连接是单向还

是双向的。

87、如何查看在weblogic中已经发布的EJB?

可以使用管理控制台,在它的Deployment中可以查看所有已发布的EJB

88、CORBA是什么?用途是什么?

CORBA 标准是公共对象请求代理结构(Common Object Request Broker Architecture),由对象管理组织 (Object Management Group

,缩写为 OMG)标准化。它的组成是接口定义语言(IDL), 语言绑定(binding:也译为联编)和允许应用程序间互操作的协议。其目的为

:用不同的程序设计语言书写在不同的进程中运行,为不同的操作系统开发。

89、说说你所熟悉或听说过的j2ee中的几种常用模式?及对设计模式的一些看法

Session Facade Pattern:使用SessionBean访问EntityBean

Message Facade Pattern:实现异步调用

EJB Command Pattern:使用Command JavaBeans取代SessionBean,实现轻量级访问

Data Transfer Object Factory:通过DTO Factory简化EntityBean数据提供特性

Generic Attribute Access:通过AttibuteAccess接口简化EntityBean数据提供特性

Business Interface:通过远程(本地)接口和Bean类实现相同接口规范业务逻辑一致性

EJB架构的设计好坏将直接影响系统的性能、可扩展性、可维护性、组件可重用性及开发效率。项目越复杂,项目队伍越庞大则越

能体现良好设计的重要性。

90、说说在weblogic中开发消息Bean时的persistent与non-persisten的差别

persistent方式的MDB可以保证消息传递的可靠性,也就是如果EJB容器出现问题而JMS服务器依然会将消息在此MDB可用的时候发送过

来,而non-persistent方式的消息将被丢弃。

既然没有标准答案,就根据自己的所了解的,补充修正一下好了

91、Servlet执行时一般实现哪几个方法?

public void init(ServletConfig config)

public ServletConfig getServletConfig()

public String getServletInfo()

public void service(ServletRequest request,ServletResponse response)

public void destroy()

init ()方法在servlet的生命周期中仅执行一次,在服务器装载servlet时执行。缺省的init()方法通常是符合要求的,不过也可以

根据需要进行 override,比如管理服务器端资源,一次性装入GIF图像,初始化数据库连接等,缺省的inti()方法设置了servlet的

初始化参数,并用它的ServeltConfig对象参数来启动配置,所以覆盖init()方法时,应调用super.init()以确保仍然执行这些任务

service ()方法是servlet的核心,在调用service()方法之前,应确保已完成init()方法。对于HttpServlet,每当客户请求一个

HttpServlet对象,该对象的service()方法就要被调用,HttpServlet缺省的service()方法的服务功能就是调用与 HTTP请求的方法

相应的do功能,doPost()和doGet(),所以对于HttpServlet,一般都是重写doPost()和doGet() 方法。

destroy()方法在servlet的生命周期中也仅执行一次,即在服务器停止卸载servlet时执行,把servlet作为服务器进程的一部分关闭

。缺省的destroy()方法通常是符合要求的,但也可以override,比如在卸载servlet时将统计数字保存在文件中,或是关闭数据库连

接。

getServletConfig()方法返回一个servletConfig对象,该对象用来返回初始化参数和servletContext。servletContext接口提供有

关servlet的环境信息。

getServletInfo()方法提供有关servlet的信息,如作者,版本,版权。

92、j2ee常用的设计模式?说明工厂模式。

Java中的23种设计模式:

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 Responsibleity(责任链模式)

工厂模式:工厂模式是一种经常被使用到的模式,根据工厂模式实现的类可以根据提供的数据生成一组类中某一个类的实例,通常这

一组类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作。首先需要定义一个基类,该

类的子类通过不同的方法实现了基类中的方法。然后需要定义一个工厂类,工厂类可以根据条件生成不同的子类实例。当得到子类的

实例后,开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例。

93、EJB需直接实现它的业务接口或Home接口吗,请简述理由。

远程接口和Home接口不需要直接实现,他们的实现代码是由服务器产生的,程序运行中对应实现类会作为对应接口类型的实例被使用

其实一直都不是很明白EJB的remote接口,home接口,Bean类究竟是如何使用的,或许应该进一步了解EJB的原理吧,查到了一个原创

文章,那就说说EJB调用的原理吧。其实在这个问题上,最需要理解的是RMI机制原理。

一个远程对象至少要包括4个class文件:远程对象、远程对象接口、实现远程接口的对象的stub、对象的skeleton。

而在EJB中则至少要包括10个class:

Bean类,特定App Server的Bean实现类

Bean的remote接口,特定App Server的remote接口实现类,特定App Server的remote接口的实现类的stub类和skeleton类。

Bean的home接口,特定App Server的home接口实现类,特定App Server的home接口的实现类的stub类和skeleton类。

和RMI不同的是,EJB中这10个class真正需要用户写的只有3个,Bean类,remote接口,home接口,其它的7个究竟怎么生成,被打包

在哪里,是否需要更多的类文件,否根据不同的App Server表现出较大的差异。

Weblogic:

home接口和remote接口的weblogic的实现类的stub类和skeleton类是在EJB被部署到weblogic的时候,由weblogic动态生成stub类和

skeleton类的字节码,所以看不到这4个类文件。

对于一次客户端远程调用EJB,要经过两个远程对象的多次RMI循环。首先是通过JNDI查找Home接口,获得Home接口的实现类,这个过

程其实相当复杂,首先是找到Home接口的Weblogic实现类,然后创建一个Home接口的Weblogic实现类的stub类的对象实例,将它序列

化传送给客户端(注意stub类的实例是在第1次RMI循环中,由服务器动态发送给客户端的,因此不需要客户端保存Home接口的

Weblogic实现类的stub 类),最后客户端获得该stub类的对象实例(普通的RMI需要在客户端保存stub类,而EJB不需要,因为服务

器会把stub类的对象实例发送给客户端)。

客户端拿到服务器给它的Home接口的Weblogic实现类的stub类对象实例以后,调用stub类的create方法, (在代码上就是

home.create(),但是后台要做很多事情),于是经过第2次RMI循环,在服务器端,Home接口的Weblogic实现类的 skeleton类收到stub

类的调用信息后,由它再去调用Home接口的Weblogic实现类的create方法。

在服务端, Home接口的Weblogic实现类的create方法再去调用Bean类的Weblogic实现类的ejbCreate方法,在服务端创建或者分配一

个EJB实例,然后将这个EJB实例的远程接口的Weblogic实现类的stub类对象实例序列化发送给客户端。

客户端收到 remote接口的Weblogic实现类的stub类的对象实例,对该对象实例的方法调用(在客户端代码中实际上就是对remote接

口的调用),将传送给服务器端remote接口的Weblogic实现类的skeleton类对象,而skeleton类对象再调用相应的remote接口的

Weblogic实现类,然后remote接口的Weblogic实现类再去调用Bean类的Weblogic实现类,如此就完成一次EJB对象的远程调用。

先拿普通RMI来说,有4个class,分别是远程对象,对象的接口,对象的stub类和skeleton类。而对象本身和对象的stub类同时都实

现了接口类。而我们在客户端代码调用远程对象的时候,虽然在代码中操纵接口,实质上是在操纵stub类,例如:

接口类:Hello

远程对象:Hello_Server

stub类:Hello_Stub

skeleton类:Hello_Skeleton

客户端代码要这样写:

Hello h = new Hello_Stub();

h.getString();

我们不会这些写:

Hello_Stub h = new Hello_Stub();

h.getString();

因为使用接口适用性更广,就算更换了接口实现类,也不需要更改代码。因此客户端需要Hello.class和Hello_Stub.class这两个文

件。但是对于EJB来说,就不需要Hello_Stub.class,因为服务器会发送给它,但是Hello.class文件客户端是省不了的,必须有。表

面上我们的客户端代码在操纵Hello,但别忘记了Hello只是一个接口,抽象的,实质上是在操纵Hello_Stub。

拿Weblogic上的EJB举例子,10个class分别是:

Bean类:HelloBean (用户编写)

Bean类的Weblogic实现类:HelloBean_Impl (EJBC生成)

Home接口:HelloHome (用户编写)

Home接口的Weblogic实现类 HelloBean_HomeImpl(EJBC生成)

Home接口的Weblogic实现类的stub类 HelloBean_HomeImpl_WLStub(部署的时候动态生成字节码)

Home接口的Weblogic实现类的skeleton类 HelloBean_HomeImpl_WLSkeleton(部署的时候动态生成字节码)

Remote接口: Hello (用户编写)

Remote接口的Weblogic实现类 HelloBean_EOImpl(EJBC生成)

Remote接口的Weblogic实现类的stub类 HelloBean_EOImpl_WLStub(部署的时候动态生成字节码)

Remote接口的Weblogic实现类的skeleton类 HelloBean_EOImpl_WLSkeleton(部署的时候动态生成字节码)

客户端只需要Hello.class和HelloHome.class这两个文件。

HelloHome home = (Home) PortableRemoteObject.narrow(ctx.lookup("Hello"), HelloHome.class);

这一行代码是从JNDI获得Home接口,但是请记住!接口是抽象的,那么home这个对象到底是什么类的对象实例呢?很简单,用

toString()输出看一下就明白了,下面一行是输出结果:

HelloBean_HomeImpl_WLStub@18c458

这表明home这个通过从服务器的JNDI树上查找获得的对象实际上是HelloBean_HomeImpl_WLStub类的一个实例。

接下来客户端代码:

Hello h = home.create()

同样Hello只是一个抽象的接口,那么h对象是什么东西呢?打印一下:

HelloBean_EOImpl_WLStub@8fa0d1

原来是HelloBean_EOImpl_WLStub的一个对象实例。

用这个例子来简述一遍EJB调用过程:

首先客户端JNDI查询,服务端JNDI树上Hello这个名字实际上绑定的对象是HelloBean_HomeImpl_WLStub,所以服务端将创建

HelloBean_HomeImpl_WLStub的一个对象实例,序列化返回给客户端。

于是客户端得到home对象,表面上是得到HelloHome接口的实例,实际上是进行了一次远程调用得到了 HelloBean_HomeImpl_WLStub

类的对象实例,别忘记了HelloBean_HomeImpl_WLStub也实现了 HelloHome接口。

然后home.create()实质上就是 HelloBean_HomeImpl_WLStub.create(),该方法将发送信息给 HelloBean_HomeImpl_WLSkeleton,而

HelloBean_HomeImpl_WLSkeleton接受到信息后,再去调用 HelloBean_HomeImpl的create方法,至此完成第1次完整的RMI循环。

注意在这次RMI循环过程中,远程对象是HelloBean_HomeImpl,远程对象的接口是HelloHome,对象的stub是

HelloBean_HomeImpl_WLStub,对象的skeleton是HelloBean_HomeImpl_WLSkeleton。

然后HelloBean_HomeImpl 再去调用HelloBean_Impl的ejbCreate方法,而HelloBean_Impl的ejbCreate方法将负责创建或者分配一个

Bean实例,并且创建一个HelloBean_EOImpl_WLStub的对象实例。

这一步比较有趣的是,在前一步RMI循环中,远程对象HelloBean_HomeImpl在客户端有一个代理类HelloBean_HomeImpl_WLStub,但在

这一步, HelloBean_HomeImpl自己却充当了HelloBean_Impl的代理类,只不过HelloBean_HomeImpl不在客户端,而是在服务端,因

此不进行RMI。

然后HelloBean_EOImpl_WLStub的对象实例序列化返回给客户端,这一步也很有趣,上次RMI过程,主角是HelloBean_HomeImpl和它的

代理类HelloBean_HomeImpl_WLStub,但这这一次换成了 HelloBean_EOImpl和它的代理类HelloBean_EOImpl_WLStub来玩了。

Hello h = home.create();h.helloWorld();

假设Hello接口有一个helloWorld远程方法,那么表面上是在调用Hello接口的helloWorld方法,实际上是在调用

HelloBean_EOImpl_WLStub的helloWorld方法。

然后HelloBean_EOImpl_WLStub的helloWorld方法将发送信息给服务器上的 HelloBean_EOImpl_WLSkeleton,而

HelloBean_EOImpl_WLSkeleton收到信息以后,再去调用 HelloBean_EOImpl的helloWorld方法。至此,完成第2次完整的RMI循环过程

在刚才 HelloBean_EOImpl是作为远程对象被调用的,它的代理类是HelloBean_EOImpl_WLStub,但现在 HelloBean_EOImpl要作为

HelloBean_Impl的代理类了。现在HelloBean_EOImpl去调用 HelloBean_Impl的helloWorld方法。注意!HelloBean_Impl继承了

HelloBean,而HelloBean中的 helloWorld方法是我们亲自编写的代码,现在终于调用到了我们编写的代码了!

至此,一次EJB调用过程终于完成。在整个过程中,服务端主要要调用的类是HelloBean_Impl, HelloBean_HomeImpl,

HelloBean_HomeImpl_WLSkeleton,HelloBean_EOImpl, HelloBean_EOImpl_WLSkeleton。客户端主要调用的类是

HelloBean_HomeImpl_WLStub, HelloBean_EOImpl_WLStub,这两个类在客户端代码中并不会直接出现,出现在代码中的类是他们的

接口HelloHome和 Hello,因此客户端需要这两个接口文件,而Stub是服务器传送给他们的。

http://www.pbase.com/nobo123/image/27229257

http://forum.javaeye.com/viewtop ... der=asc&start=0

94、排序都有哪几种方法?请列举。用JAVA实现一个快速排序。

排序的方法有:插入排序(直接插入排序、希尔排序),交换排序(冒泡排序、快速排序),选择排序(直接选择排序、堆排序),

归并排序,分配排序(箱排序、基数排序)

快速排序的伪代码。

/ /使用快速排序方法对a[ 0 :n- 1 ]排序

从a[ 0 :n- 1 ]中选择一个元素作为m i d d l e,该元素为支点

把余下的元素分割为两段left 和r i g h t,使得l e f t中的元素都小于等于支点,而right 中的元素都大于等于支点

递归地使用快速排序方法对left 进行排序

递归地使用快速排序方法对right 进行排序

所得结果为l e f t + m i d d l e + r i g h t

95、请对以下在J2EE中常用的名词进行解释(或简单描述)

web 容器:给处于其中的应用程序组件(JSP,SERVLET)提供一个环境,使JSP,SERVLET直接和容器中的环境变量接接口互,不必关

注其它系统问题。主要有WEB服务器来实现。例如:TOMCAT,WEBLOGIC,WEBSPHERE等。该容器提供的接口严格遵守J2EE规范中的WEB

APPLICATION 标准。我们把遵守以上标准的WEB服务器就叫做J2EE中的WEB容器。

Web container:实现J2EE体系结构中Web组件协议的容器。这个协议规定了一个Web组件运行时的环境,包括安全,一致性,生命周

期管理,事务,配置和其它的服务。一个提供和JSP和J2EE平台APIs界面相同服务的容器。一个Web container 由Web服务器或者J2EE

服务器提供。

EJB容器:Enterprise java bean 容器。更具有行业领域特色。他提供给运行在其中的组件EJB各种管理功能。只要满足J2EE规范的

EJB放入该容器,马上就会被容器进行高效率的管理。并且可以通过现成的接口来获得系统级别的服务。例如邮件服务、事务管理。

一个实现了J2EE体系结构中EJB组件规范的容器。

这个规范指定了一个Enterprise bean的运行时环境,包括安全,一致性,生命周期,事务,

配置,和其他的服务。

JNDI:(Java Naming & Directory Interface)JAVA命名目录服务。主要提供的功能是:提供一个目录系统,让其它各地的应用程

序在其上面留下自己的索引,从而满足快速查找和定位分布式应用程序的功能。

JMS:(Java Message Service)JAVA消息服务。主要实现各个应用程序之间的通讯。包括点对点和广播。

JTA:(Java Transaction API)JAVA事务服务。提供各种分布式事务服务。应用程序只需调用其提供的接口即可。

JAF:(Java Action FrameWork)JAVA安全认证框架。提供一些安全控制方面的框架。让开发者通过各种部署和自定义实现自己的个

性安全控制策略。

RMI/IIOP: (Remote Method Invocation /internet对象请求中介协议)他们主要用于通过远程调用服务。例如,远程有一台计算机

上运行一个程序,它提供股票分析服务,我们可以在本地计算机上实现对其直接调用。当然这是要通过一定的规范才能在异构的系统

之间进行通信。RMI是JAVA特有的。

RMI-IIOP出现以前,只有RMI和 CORBA两种选择来进行分布式程序设计。RMI-IIOP综合了RMI和CORBA的优点,克服了他们的缺点,使

得程序员能更方便的编写分布式程序设计,实现分布式计算。首先,RMI-IIOP综合了RMI的简单性和CORBA的多语言性(兼容性),其

次RMI-IIOP克服了RMI只能用于Java 的缺点和CORBA的复杂性(可以不用掌握IDL)。

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

Java 通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口。在Java中,每个异常都是一个对象,

它是Throwable类或其它子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中包含有异常信息,调用这个对象的方法

可以捕获到这个异常并进行处理。Java的异常处理是通过5个关键词来实现的:try、catch、throw、throws和finally。一般情况下

是用try来执行一段程序,如果出现异常,系统会抛出(throws)一个异常,这时候你可以通过它的类型来捕捉(catch)它,或最后

(finally)由缺省处理器来处理。

用try来指定一块预防所有"异常"的程序。紧跟在try程序后面,应包含一个catch子句来指定你想要捕捉的"异常"的类型。

throw语句用来明确地抛出一个"异常"。

throws用来标明一个成员函数可能抛出的各种"异常"。

Finally为确保一段代码不管发生什么"异常"都被执行一段代码。

可以在一个成员函数调用的外面写一个try语句,在这个成员函数内部写另一个try语句保护其他代码。每当遇到一个try语句,"异常

"的框架就放到堆栈上面,直到所有的try语句都完成。如果下一级的try语句没有对某种"异常"进行处理,堆栈就会展开,直到遇到

有处理这种"异常"的try语句。

http://www.programfan.com/article/showarticle.asp?id=2731

97、一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制?

可以。必须只有一个类名与文件名相同。

98、MVC的各个部分都有那些技术来实现?如何实现?

MVC 是Model-View-Controller的简写。"Model" 代表的是应用的业务逻辑(通过JavaBean,EJB组件实现), "View" 是应用的表

示面,用于与用户的交互(由JSP页面产生),"Controller" 是提供应用的处理过程控制(一般是一个Servlet),通过这种设计模

型把应用逻辑,处理过程和显示逻辑分成不同的组件实现。这些组件可以进行交互和重用。

model层实现系统中的业务逻辑,view层用于与用户的交互,controller层是model与view之间沟通的桥梁,可以分派用户的请求并选

择恰当的视图以用于显示,同时它也可以解释用户的输入并将它们映射为模型层可执行的操作。

99、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用?

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

用synchronized关键字修饰同步方法

反对使用stop(),是因为它不安全。它会解除由线程获取的所有锁定,而且如果对象处于一种不连贯状态,那么其他线程能在那种状

态下检查和修改它们。结果很难检查出真正的问题所在。suspend()方法容易发生死锁。调用suspend()的时候,目标线程会停下来,

但却仍然持有在这之前获得的锁定。此时,其他任何线程都不能访问锁定的资源,除非被"挂起"的线程恢复运行。对任何线程来说,

如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就会造成死锁。所以不应该使用suspend(),而应在自己的Thread

类中置入一个标志,指出线程应该活动还是挂起。若标志指出线程应该挂起,便用 wait()命其进入等待状态。若标志指出线程应当恢复,则用一个notify()重新启动线程。

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

字节流,字符流。字节流继承于InputStream OutputStream,字符流继承于InputStreamReader OutputStreamWriter。在java.io包

中还有许多其他的流,主要是为了提高性能和使用方便。

101、java中会存在内存泄漏吗,请简单描述。

的确存在Java的内存泄漏, 并且事态可以变得相当严重

Java garbage collector自动释放哪些内存里面程序不在需要的对象, 以此避免大多数的其他程序上下文的内存泄漏. 但是Java应用

程序依旧会有相当的内存泄漏. 查找原因会十分困难.

有两类主要的Java内存泄漏:

* 不再需要的对象引用

* 未释放的系统资源

2.2 非必要的对象引用

Java代码常常保留对于不再需要的对象引用, 并且这组织了内存的垃圾收集器的工作. Java对象通常被其他对象包含引用, 为此一个

单一对象可以保持整个对象树在内存中, 于是导致了如下问题:

* 在向数组添加对象以后遗漏了对于他们的处理

* 直到你再次使用对象的时候都不释放引用. 比如一个菜单指令可以插件一个对象实例引用并且不释放便于以后再次调用的时候使用

, 但是也许永远不会发生.

* 在其他引用依然需要旧有状态的时候贸然修改对象状态. 比如当你为了在一个文本文件里面保存一些属性而使用一个数组, 诸如"

字符个数"等字段在不再需要的时候依然保留在内存当中.

* 允许一个长久执行的线程所引用的对象. 设置引用为NULL也无济于事, 在线程退出和空闲之前, 对象不会被收集释放

2.3 未释放的系统资源

Java方法可以定位Java实例意外的堆内存, 诸如针对视窗和位图的内存资源. Java常常通过JNI(Java Native Interface)调用C/C++

子程序定位这些资源.

102、java中实现多态的机制是什么?

方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载

Overloading是一个类中多态性的一种表现

103、垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃圾回收?

对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址、大小以及使用情况。通常,GC采用有向图的方式记录和管理堆

(heap)中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的"。当GC确定一些对象为"不可达"时,GC就有责

任回收这些内存空间。可以。程序员可以手动执行System.gc(),通知GC运行,但是Java语言规范并不保证GC一定会执行。

104、静态变量和实例变量的区别?

static i = 10; //常量

class A a; a.i =10;//可变

105、什么是java序列化,如何实现java序列化?

序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化

后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。

序列化的实现:将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注

该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个 ObjectOutputStream(对象流)对象,接着,使用

ObjectOutputStream对象的writeObject(Object ob

j)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。

106、是否可以从一个static方法内部发出对非static方法的调用?

不可以,如果其中包含对象的method();不能保证对象初始化.

精心收集java基础106条的更多相关文章

  1. 企业面试问题收集-java基础

    Java基础部分 1.1   在登录时进行后台验证,后台获取到loginpass与数据库值对比一直? 1.2   Java中的方法覆盖(Overwrite)和方法重载(Overloading)是什么意 ...

  2. 面试题收集——Java基础部分(一)

    原博文出自于: http://www.cnblogs.com/xdp-gacl/p/3641769.html 感谢! 1.一个".java"源文件中是否可以包括多个类(不是内部类) ...

  3. (转载)面试题收集——Java基础部分(一)

    转自:http://www.cnblogs.com/xdp-gacl/p/3641769.html 1.一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制? 可 ...

  4. 100道Java基础面试题收集整理(附答案)

    不积跬步无以至千里,这里会不断收集和更新Java基础相关的面试题,目前已收集100题. 1.什么是B/S架构?什么是C/S架构 B/S(Browser/Server),浏览器/服务器程序 C/S(Cl ...

  5. [ 转载 ] Java基础二

    前言 关于赢在面试的Java题系列基本收集整理完成了,所有题目都是经过精心挑选的,很基础又考验求职者的基本功,应该说被面试到的几率很大.这里整理挑选出来供大家面试前拿来看一看,所有题目整理自网络,有一 ...

  6. [Java面经]干货整理, Java面试题(覆盖Java基础,Java高级,JavaEE,数据库,设计模式等)

    如若转载请注明出处: http://www.cnblogs.com/wang-meng/p/5898837.html   谢谢.上一篇发了一个找工作的面经, 找工作不宜, 希望这一篇的内容能够帮助到大 ...

  7. 转载:[Java面经]干货整理, Java面试题(覆盖Java基础,Java高级,JavaEE,数据库,设计模式等)

    原文:http://www.cnblogs.com/wang-meng/p/5898837.html 一:继承.抽象类与接口区别.访问控制(private, public, protected,默认) ...

  8. Java基础面试题集(一)

    Java基础面试题 一.面向对象编程(OOP) 7 二.常见的Java问题 7 2.1.什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”? 7 2.2.JDK和JRE的区别是什么? ...

  9. Java基础知识【上】(转载)

    http://blog.csdn.net/silentbalanceyh/article/details/4608272 (最终还是决定重新写一份Java基础相关的内容,原来因为在写这一个章节的时候没 ...

随机推荐

  1. golang函数 和 条件语句

    /* if : if 语句 由一个布尔表达式后紧跟一个或多个语句组成 is else : if 语句 后可以使用可选的 else 语句, else 语句中的表达式在布尔表达式为 false 时执行 s ...

  2. VFP 用 SPT 来发布一条 SELECT 到一个新的 SQL Server 表

    为了发布一条 SQL SELECT 语句来创建一个新的 SQL Server 表,  SQL Server 数据库的 select into/bulkcopy 选项必须是可用的. 在默认情况下, 对于 ...

  3. numpy 介绍与使用

    一.介绍 中文文档:https://www.numpy.org.cn/ NumPy是Python语言的一个扩展包.支持多维数组与矩阵运算,此外也针对数组运算提供大量的数学函数库.NumPy提供了与Ma ...

  4. Shell脚本 server rsync 控制脚本

    [root@backup ~]# vim /etc/init.d/rsync#!/bin/bash #this script for start|stop rsync daemon service s ...

  5. Cacti 安装插件

            Cacti本身可以以图形化界面显示出流量状态,cacti也可以安装插件,通过插件,cacti的功能被进一步强大:可以监控服务器状态:发送邮件通知:短信通知等.        0.88之 ...

  6. [Pyhton]连接MSSQL实例并执行SQL语句

    运行环境: 服务器端: MSSQL 2014 Server 2012 R2 程序端: Python 3.7.4 MacOS 10.14.6 CentOS Linux release 7.7.1908 ...

  7. Day7前端学习之路——多栏布局

    该文章主要讨论两栏布局和三栏布局,三栏布局包括很著名的圣杯布局和双飞翼布局 一.两栏布局的七种方法(左边固定,右边自适应) 原理: block水平元素宽度能够跟随父容器调节的流动特性,block级别的 ...

  8. thinkphp v5.1.36 LTS 如果设置跨域访问

    修改route/route.php中的路由例如 Route::get('new/:id', 'News/read') ->ext('html') ->header('Access-Cont ...

  9. Properties(hashtable的子类)

    Properties: Properties是hashtable的子类(在java.util包中).该集合的特点:可以用于键值对形式的配置文件,且不允许Key重复,若有重复的,后者会覆盖前者. 也就是 ...

  10. Java的开发—面向对象的7大原则之开闭原则(一)

    开闭原则(Open Close Principle) 一.定义: 软件中的(类.模块.函数等等)应该对于扩展是开放的,对于修改时关闭的.意味着一个实体允许在不改变它的源代码的前提变更它的行为 这里的软 ...