Java 开发面试题及答案
明天抽空来整顿整顿 Java 开发面试中的那点事儿吧,帮忙那些正在找工作或想跳槽找工作的兄弟姐妹们!
分享目前 Java 开发常见的面试问题以及问题的答案给大家浏览参考。
Java 根底学习材料点下边!!!
Java 残缺学习材料
1、String 类能够被继承吗?
String 类在申明时应用 final 关键字润饰,被 final 关键字润饰的类无奈被继承。
接下来咱们能够看一下 String 类的源代码片段:
public final class String
implements java.io.Serializable, Comparable<String>,CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
● 为什么 Java 语言的开发者,把 String 类定义为 final 的呢?
因为只有当字符串是不可变的,字符串池才有可能实现。字符串池的实现能够在运行时节约很多 heap 空间,因为不同的字符串变量都指向池中的同一个字符串。但如果字符串是可变的,那么 String interning 将不能实现,因为这样的话,如果变量扭转了它的值,那么其它指向这个值的变量的值也会一起扭转。如果字符串是可变的,那么会引起很重大的平安问题。譬如,数据库的用户名、明码都是以字符串的模式传入来取得数据库的连贯,或者在 socket 编程中,主机名和端口都是以字符串的模式传入。因为字符串是不可变的,所以它的值是不可扭转的,否则黑客们能够钻到空子,扭转字符串指向的对象的值,造成安全漏洞。
因为字符串是不可变的,所以是多线程平安的,同一个字符串实例能够被多个线程共享。这样便不必因为线程平安问题而应用同步。字符串本人便是线程平安的。
因为字符串是不可变的,所以在它创立的时候 HashCode 就被缓存了,不须要从新计算。这就使得字符串很适宜作为 Map 中的键,字符串的处理速度要快过其它的键对象。这就是 HashMap 中的键往往都应用字符串。
● final 关键字除了润饰类之外,还有哪些用法呢?
- final 润饰的变量,一旦赋值,不可从新赋值;
- final 润饰的办法无奈被笼罩;
- final 润饰的实例变量,必须手动赋值,不能采纳零碎默认值;
- final 润饰的实例变量,个别和 static 联用,用来申明常量;
留神:final 不能和 abstract 关键字联结应用。
总之,final 示意最终的、不可变的。
2、& 和 && 的区别?
● & 运算符是:逻辑与;&& 运算符是:短路与。
● & 和 && 在程序中最终的运算后果是完全一致的,只不过 && 存在短路景象,当 && 运算符右边的表达式后果为 false 的时候,左边的表达式不执行,此时就产生了短路景象。如果是 & 运算符,那么不论右边的表达式是 true 还是 false,左边表达式是肯定会执行的。这就是他们俩的本质区别。
● 当然,& 运算符还能够应用在二进制位运算上,例如按位与操作。
3、两个对象值雷同 equals 后果为 true,但却可有不同的 hashCode,这句话对不对?
不对,如果两个对象 x 和 y 满足 x.equals(y) == true,它们的哈希值(hashCode)该当雷同。Java 对于 equals 办法和 hashCode 办法是这样规定的:
(1)如果两个对象雷同(equals 办法返回 true),那么它们的 hashCode 值肯定要雷同;
(2)如果两个对象的 hashCode 雷同,它们并不一定雷同。当然,你未必依照要求去做,然而如果你违反了上述准则就会发现在应用汇合时,雷同的对象能够呈现在 Set 汇合中,同时减少新元素的效率会大大降低(对于应用哈希存储的零碎,如果哈希码频繁的抵触将会造成存取性能急剧下降)。
对于 equals 和 hashCode 办法,很多 Java 程序员都晓得,但很多人也就是仅仅理解而已,在 Joshua Bloch 的大作《Effective Java》(《Effective Java》在很多公司,是 Java 程序员必看书籍,如果你还没看过,那就连忙去买一本吧)中是这样介绍 equals 办法的:
首先 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 办法的窍门包含:
- 应用 == 操作符查看 ” 参数是否为这个对象的援用 ”;
- 应用 instanceof 操作符查看 ” 参数是否为正确的类型 ”;
- 对于类中的要害属性,查看参数传入对象的属性是否与之相匹配;
- 编写完 equals 办法后,问本人它是否满足对称性、传递性、一致性;
- 重写 equals 时总是要重写 hashCode;
- 不要将 equals 办法参数中的 Object 对象替换为其余的类型,在重写时不要忘掉 @Override 注解。
4、在 Java 中,如何跳出以后的多重嵌套循环?
在最外层循环前加一个标记如 outfor,而后用 break outfor; 能够跳出多重循环。
例如以下代码:
public class TestBreak {public static void main(String[] args) {outfor: for (int i = 0; i < 10; i++){for (int j = 0; j < 10; j++){if (j == 5){break outfor;}
System.out.println("j =" + j);
}
}
}
}
运行后果如下所示:
j = 0
j = 1
j = 2
j = 3
j = 4
5、重载(overload)和重写(override)的区别?重载的办法是否依据返回类型进行辨别?
办法的重载和重写都是实现多态的形式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。
重载产生在一个类中,同名的办法如果有不同的参数列表(类型不同、个数不同、程序不同)则视为重载。
重写产生在子类与父类之间,重写要求子类重写之后的办法与父类被重写办法有雷同的返回类型,比父类被重写办法更好拜访,不能比父类被重写办法申明更多的异样(里氏代换准则)。重载对返回类型没有非凡的要求。
● 办法重载的规定:
- 办法名统一,参数列表中参数的程序,类型,个数不同。
- 重载与办法的返回值无关,存在于父类和子类,同类中。
- 能够抛出不同的异样,能够有不同修饰符。
● 办法重写的规定:
- 参数列表、办法名、返回值类型必须完全一致;
- 构造方法不能被重写;
- 申明为 final 的办法不能被重写;
- 申明为 static 的办法不存在重写(重写和多态联结才有意义);
- 拜访权限不能比父类更低;
- 重写之后的办法不能抛出更宽泛的异样;
6、当一个对象被当作参数传递到一个办法后,此办法可扭转这个对象的属性,并可返回变动后的后果,那么这里是值传递还是援用传递?
是值传递。Java 语言的办法调用只反对参数的值传递。当一个对象实例作为一个参数被传递到办法中时,参数的值就是对该对象的内存地址。这个值(内存地址)被传递后,同一个内存地址指向堆内存当中的同一个对象,所以通过哪个援用去操作这个对象,对象的属性都是扭转的。
7、为什么办法不能依据返回类型来辨别重载?
咱们来看以下的代码:
public void testMethod(){doSome();
}
public void doSome(){}
public int doSome(){return 1;}
在 Java 语言中,调用一个办法,即便这个办法有返回值,咱们也能够不接管这个返回值,例如以上两个办法 doSome(),在 testMethod()中调用的时候,Java 编译器无奈辨别调用的具体是哪个办法。所以对于编译器来说,doSome()办法不是重载而是反复了,编译器报错。所以辨别这两个办法不能依附办法的返回值类型。
8、抽象类 (abstract class) 和接口 (interface) 有什么异同?
不同点:
● 抽象类中能够定义结构器,接口不能;
● 抽象类能够有形象办法和具体方法,接口不能有具体方法;
● 接口中的成员全都是 public 的,抽象类中的成员能够应用 private、public、protected、默认等润饰;
● 抽象类中能够定义成员变量,接口中只能是常量;
● 有形象办法的类必须被申明为抽象类,而抽象类未必要有形象办法;
● 抽象类中能够蕴含静态方法,接口中不能有静态方法;
● 一个类只能继承一个抽象类,一个类能够实现多个接口;
相同点:
● 不可能实例化;
● 能够将抽象类和接口类型作为援用类型;
● 一个类如果继承了某个抽象类或者实现了某个接口都须要对其中的形象办法全副进行实现,否则该类依然须要被申明为抽象类;
9、char 型变量中能不能存储一个中文汉字,为什么?
char 类型能够存储一个中文汉字,因为 Java 中应用的编码是 Unicode(不抉择任何特定的编码,间接应用字符在字符集中的编号,这是对立的惟一办法),一个 char 类型占 2 个字节(16 比特),所以放一个中文是没问题的。
补充:应用 Unicode 意味着字符在 JVM 外部和内部有不同的表现形式,在 JVM 外部都是 Unicode,当这个字符被从 JVM 外部转移到内部时(例如存入文件系统中),须要进行编码转换。所以 Java 中有字节流和字符流,以及在字符流和字节流之间进行转换的转换流,如 InputStreamReader 和 OutputStreamReader,这两个类是字节流和字符流之间的适配器类,承当了编码转换的工作。
10、形象的 (abstract) 办法是否可同时是动态的(static),是否可同时是本地办法(native),是否可同时被 synchronized?
都不能。
● 形象办法须要子类重写,而动态的办法是无奈被重写的,因而二者是矛盾的。
● 本地办法是由本地代码(如 C++ 代码)实现的办法,而形象办法是没有实现的,也是矛盾的。
● synchronized 和办法的实现细节无关,形象办法不波及实现细节,因而也是互相矛盾的。
11、== 和 equals 的区别?
equals 和 == 最大的区别是一个是办法一个是运算符。
● ==:如果比拟的对象是根本数据类型,则比拟的是数值是否相等;如果比拟的是援用数据类型,则比拟的是对象的地址值是否相等。
● equals():用来比拟办法两个对象的内容是否相等。equals 办法不能用于根本数据类型的变量,如果没有对 equals 办法进行重写,则比拟的是援用类型的变量所指向的对象的地址。
12、论述动态变量和实例变量的区别?
不论创立多少个对象,动态变量在内存中有且仅有一个;实例变量必须依存于某一实例,须要先创建对象而后通过对象能力拜访到它。动态变量能够实现让多个对象共享内存。
13、break 和 continue 的区别?
● break 和 continue 都是用来管制循环的语句。
● break 用于齐全完结一个循环,跳出循环体执行循环前面的语句。
continue 用于跳过本次循环,持续下次循环。
14、String s = “Hello”;s = s + ” world!”; 这两行代码执行后,原始的 String 对象中的内容变了没有?
没有。
因为 String 被设计成不可变类,所以它的所有对象都是不可变对象。
在这段代码中,s 原先指向一个 String 对象,内容是 “Hello”,而后咱们对 s 进行了“+”操作,那么 s 所指向的那个对象是否产生了扭转呢?
答案是没有。这时 s 不指向原来那个对象了,而指向了另一个 String 对象,内容为 ”Hello world!”,原来那个对象还存在于内存之中,只是 s 这个援用变量不再指向它了。
通过下面的阐明,咱们很容易导出另一个论断,如果常常对字符串进行各种各样的批改,或者说,不可预感的批改,那么应用 String 来代表字符串的话会引起很大的内存开销。因为 String 对象建设之后不能再扭转,所以对于每一个不同的字符串,都须要一个 String 对象来示意。这时,应该思考应用
StringBuffer/StringBuilder 类,它容许批改,而不是每个不同的字符串都要生成一个新的对象。并且,这两品种的对象转换非常容易。同时,咱们还能够晓得,如果要应用内容雷同的字符串,不用每次都 new 一个 String。例如咱们要在结构器中对一个名叫 s 的 String 援用变量进行初始化,把它设置为初始值,该当这样做:
s = new String(“ 能源节点,口口相传的 Java 黄埔军校 ”);
而不是这样做:
s = new String(“ 能源节点,口口相传的 Java 黄埔军校 ”);
后者每次都会调用结构器,生成新对象,性能低下且内存开销大,并且没有意义,因为 String 对象不可扭转,所以对于内容雷同的字符串,只有一个 String 对象来示意就能够了。也就说,屡次调用下面的结构器创立多个对象,他们的 String 类型属性 s 都指向同一个对象。
下面的论断还基于这样一个事实:对于字符串常量,如果内容雷同,Java 认为它们代表同一个 String 对象。而用关键字 new 调用结构器,总是会创立一个新的对象,无论内容是否雷同。
至于为什么要把 String 类设计成不可变类,是它的用处决定的。其实不只 String,很多 Java 规范类库中的类都是不可变的。在开发一个零碎的时候,咱们有时候也须要设计不可变类,来传递一组相干的值,这也是面向对象思维的体现。不可变类有一些长处,比方因为它的对象是只读的,所以多线程并发拜访也不会有任何问题。当然也有一些毛病,比方每个不同的状态都要一个对象来代表,可能会造成性能上的问题。所以 Java 规范类库还提供了一个可变版本,即 StringBuffer。