通往 BATJ 的 160 道 Java 面试题及答案(一)

一、题目(1~40题)

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

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

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

4、float f=3.4; 是否正确?

5、short s1 = 1; s1 = s1 + 1; 有错吗?short s1 = 1; s1 += 1; 有错吗?

6、Java 有没有 goto?

7、int 和 Integer 有什么区别?

8、& 和 && 的区别?

9、解释内存中的栈 (stack)、堆(heap) 和静态区 (static area) 的用法。

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

11、switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上?

12、用最有效率的方法计算 2 乘以 8?

13、数组有没有 length()方法?String 有没有 length() 方法?

14、在 Java 中,如何跳出当前的多重嵌套循环?

15、构造器(constructor)是否可被重写(override)?

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

17、是否可以继承 String 类?

18、当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

19、String 和 StringBuilder、StringBuffer 的区别?

20、重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?

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

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

23、抽象类(abstract class)和接口(interface)有什么异同?

24、静态嵌套类 (Static Nested Class) 和内部类(Inner Class)的不同?

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

26、抽象的(abstract)方法是否可同时是静态的(static), 是否可同时是本地方法(native),是否可同时被 synchronized 修饰?

27、阐述静态变量和实例变量的区别。

28、是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?

29、如何实现对象克隆?

30、String s = new String(“xyz”); 创建了几个字符串对象?

31、接口是否可继承(extends)接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concrete class)?

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

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

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

35、Java 中的 final 关键字有哪些用法?

36、数据类型之间的转换:

37、如何实现字符串的反转及替换?

38、怎样将 GB2312 编码的字符串转换为 ISO-8859-1 编码的字符串?

39、日期和时间:

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

二、参考答案(含题目)

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

 面向对象的三大特征:1.继承  2.封装 3.多态性

(1)继承:就是保留父类的属性,开扩新的东西。通过子类可以实现继承,子类继承父类的所有状态和行为,同时增加自身的状态和行为。

(2)封装:就是类的私有化。将代码及处理数据绑定在一起的一种编程机制,该机制保证程序和数据不受外部干扰。

(3)多态:是允许将父对象设置成为和一个和多个它的子对象相等的技术。包括重载和重写。

                    重载为编译时多态,重写是运行时多态。

重载与覆盖: Overloading:重载是指两个或者多个函数在同一类中,名一样,参数列表不一样,或者说:方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同。 

注意:仅仅是返回值不同的两个函数,不叫重载,是错误的。

方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现. Overriding(重写)=覆盖:在父类有个函数,在子类也有一个同样名字的函数,而且在子类内中把这个功能做的更具体化。

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

饰符       当前类      同 包      子 类     其他包
public         √             √             √            √
protected    √            √             √             ×
default        √            √              ×            ×
private        √            ×              ×            ×

类的成员不写访问修饰时默认为default。默认对于同一个包中的其他类相当于公开(public),对于不是同一个包中的其他类相当于私有(private)。

受保护(protected)对子类相当于公开,对不是同一包中的没有父子关系的类相当于私有。

Java中,外部类的修饰符只能是public或默认,类的成员(包括内部类)的修饰符可以是以上四种。

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

不是,

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

而String类代表字符串,属于引用类型,所谓引用类型包括:类,接口,数组...

4、float f=3.4; 是否正确?

答案:不正确。 
原因:精度不准确,应该用强制类型转换,如下所示:

float f=(float)3.4 或 float f = 3.4f 
在java里面,没小数点的默认是 int,有小数点的默认是 double
编译器可以自动向上转型,如int 转成 long 系统自动转换没有问题,因为后者精度更高 
double 转成 float 就不能自动做了,所以后面的加上个 f

5、short s1 = 1; s1 = s1 + 1; 有错吗?short s1 = 1; s1 += 1; 有错吗?

先说一下Java的基本数据类型转换规则,大的数据类型转换为小的数据类型需要强制转换,反之可以自动转换。

赋值表达式等号两侧的转换的规则是右侧的向左侧的看齐,即右侧表达式要转换到和左边的类型一样。

第一题:short s1 = 1; s1 = s1 + 1;

错! s1 + 1,s1是short类型,1是int型,s1会自动转换为int型的1,与1相加后,得到int型的2,要向左侧的short类型的s1看齐,即需要通过强制类型转换。正确写法:s1 = (short) (s1 + 1);

第二题:short s1 = 1; s1 += 1;

正确! 执行s1+=1;其实执行的是s1 = (short) (s1 + 1); 其中会有一个强制转换的过程。

另外:short s1=1,s2=1;short s3=s1+s2;

错误!这里是编译器从数据安全方面考虑,如果s1和s2都是较大的short类型数,可能会导致溢出,所以会要求强制转换到int。正确写法: short s3=(short) ((short)s1+(short)s2); 注意short 取值范围 

基本类型:short 二进制位数:16
包装类:java.lang.Short
最小值:Short.MIN_VALUE=-32768 (-2的15此方)
最大值:Short.MAX_VALUE=32767 (2的15次方-1)

6、Java 有没有 goto?

由于goto关键字在java之前的语言中广泛使用,因此尽管现在在java中还没有使用该关键字,但是仍然设置为了保留字,一旦在开发环境中输入goto就会变色为关键字颜色。

7、int 和 Integer 有什么区别?

(1)Integer是int的包装类;int是基本数据类型; 
(2)Integer变量必须实例化后才能使用;int变量不需要; 
(3)Integer实际是对象的引用,指向此new的Integer对象;int是直接存储数据值 ; 
(4)Integer的默认值是null;int的默认值是0。

8、& 和 && 的区别?

对于:&  -- >  只要左右两边有一个为false,则为false;只有全部都为true的时候,结果为true

对于:&& -- > 只要符号左边为false,则结果为false;当左边为true,同时右边也为true,则结果为tru

9、解释内存中的栈 (stack)、堆(heap) 和静态区 (static area) 的用法。

通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用内存中的栈空间;

而通过new关键字和构造器创建的对象放在堆空间;

程序中的字面量(literal)如直接书写的100、“hello”和常量都是放在静态存储区中。栈空间操作最快但是也很小,通常大量的对象都是放在堆空间,整个内存包括硬盘上的虚拟内存都可以被当成堆空间来使用。

String str = new String(“hello”);

上面的语句中str放在栈上,用new创建出来的字符串对象放在堆上,而“hello”这个字面量放在静态存储区。

补充:较新版本的Java中使用了一项叫“逃逸分析“的技术,可以将一些局部对象放在栈上以提升对象的操作性能。

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

round()方法可以这样理解:将括号内的数+0.5之后,向下取值,

比如:round(3.4)就是3.4+0.5=3.9,向下取值是3,所以round(3.4)=3; 

round(-10.5)就是-10.5+0.5=-10,向下取值就是-10,所以round(-10.5)=-10

所以,Math.round(11.5)=12;Math.round(-11.5)=-11

扩展:常用的还有2个

Math.ceil :求最小的整数,但不小于本身.  

                    ceil的英文意义是天花板,该方法就表示向上取整,

                    Math.ceil(11.3)的结果为12,Math.ceil(-11.3)的结果是-11;

Math.floor:最大的整数,但不大于本身.

                    floor的英文意义是地板,该方法就表示向下取整,

                    Math.floor(11.6)的结果为11,Math.floor(-11.6)的结果是-12;

11、switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上?

 * 基本类型的包装类(如:Character、Byte、Short、Integer)
 * switch可作用于char byte short int
 * switch可作用于char byte short int对应的包装类
 * switch不可作用于long double float boolean,包括他们的包装类
 * switch中可以是字符串类型,String (jdk1.7之后才可以作用在string上)
 * switch中可以是枚举类型

12、用最有效率的方法计算 2 乘以 8?

2<<3

对于计算机而言,位操作是最快的。

13、数组有没有 length()方法?String 有没有 length() 方法?

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

String有length()方法。

注意:JavaScript中,获得字符串的长度是通过length属性得到的,这一点容易和Java混淆。

14、在 Java 中,如何跳出当前的多重嵌套循环?

两种常用方式:

a、break跳出当前循环,通过内部跳出条件控制跳出外部循环

for(int i=0;i<4;i++){
for(int j=0;j<5;j++){
System.out.println("i="+i+"; j="+j);
if(j==3) {
i=4;
                break;
            }
        }
}
  •  

b、抛出异常也可以跳出多重循环

try {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 5; j++) {
System.out.println("i=" + i + "; j=" + j);
if (j == 3) {
throw new Exception();
}
}
}
} catch (Exception e) {
System.out.println("e");
}

 

15、构造器(constructor)是否可被重写(override)?

      Constructor(构造器)不能被继承,所以不能被override(重写),但是可以被overloading(重载)。

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

不对,如果两个对象x和y满足x.equals(y) == true,它们的哈希码(hash code)应当相同。

Java对于eqauls方法和hashCode方法是这样规定的:

(1)如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同;

(2)如果两个对象的hashCode相同,它们并不一定相同。

当然,你未必要按照要求去做,但是如果你违背了上述原则就会发现在使用容器时,相同的对象可以出现在Set集合中,同时增加新元素的效率会大大下降(对于使用哈希存储的系统,如果哈希码频繁的冲突将会造成存取性能急剧下降)。

首先equals方法必须满足自反性(x.equals(x)必须返回true)、对称性(x.equals(y)返回true时,y.equals(x)也必须返回true)、传递性(x.equals(y)和y.equals(z)都返回true时,x.equals(z)也必须返回true)和一致性(当x和y引用的对象信息没有被修改时,多次调用x.equals(y)应该得到同样的返回值),而且对于任何非null值的引用x,x.equals(null)必须返回false。

实现高质量的equals方法的诀窍包括:

1. 使用==操作符检查”参数是否为这个对象的引用”;

2. 使用instanceof操作符检查”参数是否为正确的类型”;

3. 对于类中的关键属性,检查参数传入对象的属性是否与之相匹配;

4. 编写完equals方法后,问自己它是否满足对称性、传递性、一致性;

5. 重写equals时总是要重写hashCode;

6. 不要将equals方法参数中的Object对象替换为其他的类型,在重写时不要忘掉@Override注解。

17、是否可以继承 String 类?

不可以,因为String类有final修饰符,而final修饰的类是不能被继承的,实现细节不允许改变。

public final class String implements java.io.Serializable, Comparable<String>, CharSequence 

18、当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

是值传递。Java编程语言中只有由值传递参数的。当一个对象实例作为一个参数被传递到方法中时,参数的值就是该对象的引用。对象的内容可以在被调用的方法中改变,但对象的引用是永远不会改变的

19、String 和 StringBuilder、StringBuffer 的区别?

StringBuilder是线程不安全的,而StringBuffer是线程安全的

如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。

String:适用于少量的字符串操作的情况

StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况

StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况

20、重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?

方法的重载和重写都是实现多态的方式,

区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。

重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求

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

 JVM中类的装载是由类加载器(ClassLoader)和他的子类来实现的,java中的类加载器是一个重要的java运行时系统组件,它负责在运行时查找和装入类文件中的类。

  1. 加载 
    把类的.class文件中的数据读入内存中,通常是创建一个字节数组读入.class文件,然后产生与所加载类对应的class对象。此时的对象还不稳重,类还不可以使用。
  2. 连接 
    当类被加载后就进入连接阶段,这一阶段包括验证、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用替换为直接引用)三个步骤
  3. 初始化 
    1)如果类存在直接的父类并且这个类还没有被初始化,那么就先初始化父类; 
    2)如果类中存在初始化语句,就依次执行这些初始化语句
 

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

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

 所以,char型变量中当然可以存储汉字啦。

不过,如果某个特殊的汉字没有被包含在unicode编码字符集中,那么,这个char型变量中就不能存储这个特殊汉字

 说明:unicode编码占用两个字节,所以,char类型的变量也是占用两个字节。

23、抽象类(abstract class)和接口(interface)有什么异同?

抽象类:包含抽象方法的类就是抽象类 
接口:指抽象方法的集合,方法不包含方法体

相同点:

  1. 都不能被实例化
  2. 接口的实现类或者抽象类的子类都必须实现了接口或抽象类中的方法后才可以被实例化

不同点:

  1. 接口只有定义,方法不能在接口中实现,实现接口的类要实现接口中所有的方法;抽象类可以有定义与实现,方法可以在抽象类中实现
  2. 接口要实现,抽象类要继承,一个类可以实现多个接口,但只能继承一个抽象类
  3. 接口强调设计理念为“has -a”的关系,抽象类强调“is -a”关系
  4. 接口中定义变量默认为public static final 要赋初值,方法必须是public,static,且只能是这两个;抽象类中可以有自己的数据成员变量,也可以有非抽象的成员方法,而且成员变量默认为default。这些成员变量可以在子类中被重新定义,也可以重新赋值,抽象方法(有abstract修饰)不能用peivate,static,synchronized,native等访问修饰符修饰,同时方法以分号结尾,并且不带花括号
  5. 接口被运用于比较常用的功能,便于日后的维护或者添加删除方法;而抽象类更倾向于充当公共类的角色,不适用于对里面的代码进行修改

    接口是一种特殊形式的抽象类,使用接口完全有可能实现与抽象类相同的操作。当子类和父类之间存在有逻辑上的层次结构时,推荐使用抽象类;当用于不同类之间,定义不同类之间的通信规则,希望支持差别较大的两个或者更多对象之间的特定交互行为时,应该使用接口。 
    此外,接口可以继承接口,抽象类可以实现接口,抽象类也可以继承具体类。抽象类也可以有静态的main方法。

24、静态嵌套类 (Static Nested Class) 和内部类(Inner Class)的不同?

Inner Class(内部类)定义在类中的类。 (一般是JAVA的说法)

Nested Class(嵌套类)是静态(static)内部类。(一般是C++的说法)
静态内部类:

1 创建一个static内部类的对象,不需要一个外部类对象

2 不能从一个static内部类的一个对象访问一个外部类对象

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

(1)静态集合类,例如HashMap和Vector。如果这些容器为静态的,由于它们的声明周期与程序一致,那么容器中的对象在程序结束之前将不能被释放,从而造成内存泄漏。

(2)各种连接,例如数据库的连接、网络连接以及IO连接等。

(3)监听器。在Java语言中,往往会使用到监听器。通常一个应用中会用到多个监听器,但在释放对象的同时往往没有相应的删除监听器,这也可能导致内存泄漏。

(4)变量不合理的作用域。一般而言,如果一个变量定义的作用域大于其使用范围,很有可能会造成内存泄漏,另一方面如果没有及时地把对象设置为Null,很有可能会导致内存泄漏的放生

26、抽象的(abstract)方法是否可同时是静态的(static), 是否可同时是本地方法(native),是否可同时被 synchronized 修饰?

答:都不能。

抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。

本地方法是由本地代码(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。

synchronized和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。

27、阐述静态变量和实例变量的区别。

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

28、是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?

不可以。因为非static方法是要与对象关联在一起的,必须创建一个对象后,才可以在该对象上进行方法调用,而static方法调用时不需要创建对象,可以直接调用。也就是说,当一个static方法被调用时,可能还没有创建任何实例对象,如果从一个static方法中发出对非static方法的调用,那个非static方法是关联到哪个对象上的呢?这个逻辑无法成立,所以,一个static方法内部发出对非static方法的调用。

29、如何实现对象克隆?

两种不同的克隆方法,浅克隆(ShallowClone)和深克隆(DeepClone)。 
在Java语言中,数据类型分为值类型(基本数据类型)和引用类型,值类型包括int、double、byte、boolean、char等简单数据类型,引用类型包括类、接口、数组等复杂类型。浅克隆和深克隆的主要区别在于是否支持引用类型的成员变量的复制。 
有两种方式: 
1). 实现Cloneable接口并重写Object类中的clone()方法; 
2). 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆;

30、String s = new String(“xyz”); 创建了几个字符串对象?

    在String的工作原理中,已经提到了,new 一个String对象,是需要先在字符串常量中查找相同值或创建一个字符串常量,然后再在内存中创建一个String对象,所以 String s = new String("xyz"); 会创建两个对象。

31、接口是否可继承(extends)接口?抽象类是否可实现(implements)接口?抽象类是否可继承具体类(concrete class)?

接口可以继承接口,而且支持多重继承。抽象类可以实现(implements)接口。抽象类可继承具体类也可以继承抽象类。

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

这个是可以的,一个“.java”源文件里面可以包含多个类,但是只允许有一个public类,并且类名必须和文件名一致。

每个编译单元只能有一个public 类。这么做的意思是,每个编译单元只能有一个公开的接口,而这个接口就由其public 类来表示。
你可以根据需要,往这个文件里面添加任意多个提供辅助功能的package 权限的类。但是如果这个编译单元里面有两个或两个以上的public 类的话,程序就不知道从哪里导入了,编译器就会报错。

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

回答:匿名内部类在实现时必须借助一个借口或者一个抽象类或者一个普通类来构造,从这过层次上讲匿名内部类是实现了接口或者继承了类,但是不能通过extends或implement关键词来继承类或实现接口。

匿名内部类即没有名字的内部类。当我们只需要用某一个类一次时,且该类从意义上需要实现某个类或某个接口,这个特殊的扩展类就以匿名内部类来展现。

一般的用途:

1、覆盖某个超类的方法,并且该扩展类只在本类内用一次。

2、继承抽象类,并实例化其抽象方法,并且该扩展类只在本类内用一次。

3、实现接口,实例化其方法,并且该扩展类只在本类内用一次。

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

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

35、Java 中的 final 关键字有哪些用法?

(1)修饰类:表示该类不能被继承;

(2)修饰方法:表示方法不能被重写;

(3)修饰变量:表示变量只能一次赋值以后值不能被修改(常量)。

36、数据类型之间的转换:

1)低级到高级的自动类型转换;

2)高级到低级的强制类型转换(会导致溢出或丢失精度);

3)基本类型向类类型转换;

4)基本类型向字符串的转换;

5)类类型向字符串转换

具体的不再详细说明,应该一想就明白了。

37、如何实现字符串的反转及替换?

可用字符串构造一 StringBuffer 对象,然后调用 StringBuffer 中的 reverse方法即可实现字符串的反转

调用 replace 方法即可实现字符串的替换。

public class test {

    public static void main(String[] args) {

    StringBuffer sb=new StringBuffer("hello");

    System.out.println(sb);

    sb.reverse();

    System.out.println(sb);

    }

}

输出结果:

hello
olleh

38、怎样将 GB2312 编码的字符串转换为 ISO-8859-1 编码的字符串?


String s1 = "你好";
String s2 = new String(s1.getBytes("GB2312"), "ISO-8859-1");

39、日期和时间:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
try {  
    //1、日期转字符串  
    Calendar calendar = Calendar.getInstance();  
    Date date = calendar.getTime();  
    String dateStringParse = sdf.format(date);  
    System.out.println(dateStringParse);  
    //2、字符串转日期  
    String dateString = "2017-12-20 14:02:08";  
    Date dateParse = sdf.parse(dateString);  
    System.out.println(dateParse);  
} catch (ParseException e) {  
    e.printStackTrace();  
}      

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

  public static void main(String[] args) {
    // TODO Auto-generated method stub
    Calendar cal = Calendar.getInstance();
    cal.add(Calendar.DATE, -1);
    System.out.println(cal.getTime());
  }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值