Java笔试面试题汇总

更新时间:2024-01-21 23:06:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

Java笔试面试题: 1.类的定义格式:

[修饰符] class 类名{ 类的主体; }

2.方法声明的基本格式:

[修饰符] 返回值类型 方法名(参数类型 参数名, ...){ 定义变量; 定义方法; }

3.局部变量与成员变量的区别:成员变量有默认值,而局部变量没有;

4.Java的判断条件结果必须是一个布尔值;

5.this关键字和super关键字分别代表什么?以及他们各自的使用场景和作用。

this:代表当前类的对象引用

super:代表父类存储空间的标识。(可以理解为父类的引用,通过这个东西可以访问父类的成员)

应用场景:

A:调用成员变量

this.成员变量 调用本类的成员变量 super.成员变量 调用父类的成员变量 B:调用构造方法

this(...) 调用本类的构造方法 super(...) 调用父类的构造方法 C:调用成员方法

this.成员方法 调用本类的成员方法 super.成员方法 调用父类的成员方法

6.权限修饰符:

本类 同一个包下(子类和无关类) 不同包下(子类) 不同包下(无关类) private Y

默认 Y Y

protected Y Y Y

public Y Y Y Y

JAVA的事件委托机制和垃圾回收机制:

java 事件委托机制的概念,一个源产生一个事件并将它送到一个或多个监听器那里。在这种方案中, 监听器简单的等待, 直到它收到一个事件。 一旦事件

被接受, 监听器将处理这个事件,然后返回。

垃圾回收机制 垃圾收集是将分配给对象但不再使用的内存回收或释放的过程。如果一个对象没有指向它的引用或者其赋值为null,则次对象适合进行垃圾回收

7.控制跳转语句: break:中断 continue:继续 return:返回

break:中断的意思 使用场景:

A:switch语句中 B:循环语句中。

(循环语句中加入了if判断的情况) 注意:离开上面的两个场景,无意义。

如何使用呢?

A:跳出单层循环 B:跳出多层循环

要想实现这个效果,就必须知道一个东西。带标签的语句。 格式:

标签名: 语句 wc:for(int x=0; x<3; x++) {

nc:for(int y=0; y<4; y++) { if(y == 2) { break wc; }

System.out.print(\ }

System.out.println(); }

continue:继续

使用场景:

循环中。离开此场景无意义。

测试,找到和break的区别: break:跳出单层循环

continue:跳出一次循环,进入下一次的执行

练习题:

for(int x=1; x<=10; x++) {

if(x%3==0) {

//在此处填写代码 }

System.out.println(“Java基础班”); }

我想在控制台输出2次:“Java基础班“ break;

我想在控制台输出7次:“Java基础班“ continue;

我想在控制台输出13次:“Java基础班“ System.out.println(“Java基础班”);

return:返回

其实它的作用不是结束循环的,而是结束方法的。

8.什么是 java序列化,如何实现 java序列化? (写一个实例) 序列化:

可以将一个对象保存到一个文件, 所以可以通过流的方式在网络上传输, 可以将文件的内容读取,转化为一个对象。

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

将需要被序列化的类实现 Serializable 接口,该接口没有需要实现的方法, implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流 (如: FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用

ObjectOutputStream对象的writeObject(Objectobj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。

9.一个\源文件中是否可以包括多个类(不是内部类)?有什么限制? 可以。如果这个类的修饰符是public,其类名与文件名必须相同

10.方法重写(Override)和方法重载(Overload)的区别?方法重载能改变返回值类型吗?

Override:方法重写也称方法覆盖 Overload:方法重载

方法重写:

在子类中,出现和父类中一模一样的方法声明的现象。

方法重载:

同一个类中,出现的方法名相同,参数列表不同的现象。 方法重载能改变返回值类型,因为它和返回值类型无关。

子类对象调用方法的时候:先找子类本身,再找父类。

方法重写的应用:

当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法。

这样,即沿袭了父类的功能,又定义了子类特有的内容。

方法重写的注意事项

A:父类中私有方法不能被重写

因为父类私有方法子类根本就无法继承 B:子类重写父类方法时,访问权限不能更低 最好就一致

C:父类静态方法,子类也必须通过静态方法进行重写

其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态中我会讲解

子类重写父类方法的时候,最好声明一模一样。 11.看程序写结果

字符串数据和其他数据做+,结果是字符串类型。 这里的+不是加法运算,而是字符串连接符。

System.out.prinln(8+8+”88”+8+8); //168888

12.final:最终的意思。常见的是它可以修饰类,方法,变量。 final修饰局部变量的问题

基本类型:基本类型的值不能发生改变。

引用类型:引用类型的地址值不能发生改变,但是,该对象的堆内存的值是可以改变的。

final修饰变量的初始化时机

A:被final修饰的变量只能赋值一次。 B:在构造方法完毕前。(非静态的常量)

继承时候类的执行顺序问题,一般都是选择题,问你将会打印出什么? 父类: 13. package test; public class FatherClass{ public FatherClass(){ System.out.println(\); } } 子类:

package test; import test.FatherClass; public class ChildClass extends FatherClass{ public ChildClass(){

System.out.println(\); }

public static void main(String[] args){ FatherClass fc = new FatherClass();

ChildClass cc = new ChildClass(); } }

输出结果:

FatherClass Create FatherClass Create ChildClass Create

14.内部类的实现方式? 答: 示例代码如下:

public class OuterClass{

private class InterClass{ public InterClass(){

System.out.println(\); } }

public OuterClass(){

InterClass ic = new InterClass();

System.out.println(\); }

public static void main(String[] args){ OuterClass oc = new OuterClass(); } }

输出结果:

InterClass Create OuterClass Create

15.如在 Collection框架中, 实现比较要实现什么样的接口?

Collection框架中实现比较要实现Comparable 接口和 Comparator 接口

16.看程序写结果 class A{ static{

System.out.print(\); }

public A(){

System.out.print(\); } }

class B extends A{ static{

System.out.print(\); }

public B(){

System.out.print(\); } }

public class C{

public static void main(String[] ars){ A a = new B(); //执行到此处,结果: 1a2b a = new B(); //执行到此处,结果: 1a2b2b } }

类的static 代码段,可以看作是类首次加载(被虚拟机加载)执行的代码,而对 于类的加载,首先要执行其基类的构造,再执行其本身的构造

17.抽象类和接口的区别?

(1)接口可以被多重implements,抽象类只能被单一extends (2)接口只有定义,抽象类可以有定义和实现

(3)接口的字段定义默认为:public static final,当功能需要累积时用抽象类,不需要累积时用接口

18.什么是类的反射机制?

通过类(Class对象),可以得出当前类的fields、 method、 construtor、 interface、superClass、 modified等,同时可以通过类实例化一个实例、设置属性、唤醒方法。Spring中一切都是反射、 struts、 hibernate都是通过类的反射进行开发的

19.类的反射机制中的包及核心类 java.lang.Class

java.lang.refrection.Method java.lang.refrection.Field

java.lang.refrection.Constructor

java.lang.refrection.Modifier java.lang.refrection.Interface

20.得到 Class的三个过程是什么? 对象.getClass()

类.class或Integer.type(int) Integer.class(java.lang.Integer) Class.forName();

21.如何唤起类中的一个方法?

产生一个Class数组,说明方法的参数 通过Class对象及方法参数得到Method

通过method.invoke(实例,参数值数组)唤醒方法

22.如何将数值型字符转换为数字( Integer, Double)? Integer.parseInt(“1234”); Double.parseDouble(“123.2”);

23.数据类型转换:

byte a = 3;

int b = 4;

//int c = a + b; //这个肯定没有问题 //byte c = a + b; //这个是有问题的

//用强制类型转换改进 byte c = (byte) (a + b);

思考题1:请问下面这个有没有问题 double d = 12.345; float f = d;

答:是有问题的,需要进行强制类型转换

思考题2:看看下面两个定义有没有区别呢? float f1 = (float)12.345; float f2 = 12.345f;

f1其实是通过一个double类型转换过来的。 而f2本身就是一个float类型。 面试题:

byte b1=3,b2=4,b; b=b1+b2; b=3+4;

哪句是编译失败的呢?为什么呢? b = b1 + b2; //编译失败。

因为变量相加,题中首先会转换为int类型数据,最终把结果赋给byte类型的变量b时由于可能会损失精度,因此会报错!

常量相加,首先做加法,然后看结果是否在赋值的数据类型范围内,如果不是,才报错。 具体分析:

//b = b1 + b2; //这个是类型提升,所以有问题

b = 3 + 4; //常量,先把结果计算出来,然后看是否在byte的范围内,如果在就不报错。

byte b = 130;有没有问题?如果我想让赋值正确,可以怎么做?结果是多少呢?

//因为byte的范围是:-128到127。

//而130不在此范围内,所以报错。 //byte b = 130;

//我们可以使用强制类型转换 byte b = (byte) 130;

//结果是多少呢?

System.out.println(b); //-126 分析过程:

我们要想知道结果是什么,就应该知道是如何进行计算的。 而我们又知道计算机中数据的运算都是补码进行的。 而要得到补码,首先要计算出数据的二进制。

A:获取130这个数据的二进制。

00000000 00000000 00000000 10000010 这是130的原码,也是反码,还是补码。 B:做截取操作,截成byte类型的了。 10000010

这个结果是补码。 C:已知补码求原码。

符号位 数值位 补码: 1 0000010

反码: 1 0000001

原码: 1 1111110

24.运算符 面试题:

short s=1;s = s+1; //错误,运算的时候s先转换为int类型,然后参与运算,此时需要强制类型转换为short类型

short s=1;s+=1; //正确 扩展的赋值运算符其实隐含了一个强制类型转换。 s += 1;

不是等价于 s = s + 1;

而是等价于 s = (s的数据类型)(s + 1); 25.位运算符

class OperatorDemo {

public static void main(String[] args) { //&,|,^,~

int a = 3; int b = 4;

System.out.println(3 & 4); //0 System.out.println(3 | 4); //7 System.out.println(3 ^ 4); //7 System.out.println(~3); //-4 } }

分析:因为是位运算,所以我们必须先把数据换算成二进制。

3的二进制:11

00000000 00000000 00000000 00000011 4的二进制:100

00000000 00000000 00000000 00000100

&位与运算:有0则0。

00000000 00000000 00000000 00000011 &00000000 00000000 00000000 00000100 ----------------------------------- 00000000 00000000 00000000 00000000 结果是:0

|位或运算:有1则1。

00000000 00000000 00000000 00000011 |00000000 00000000 00000000 00000100 ----------------------------------- 00000000 00000000 00000000 00000111 结果是:7

^位异或运算:相同则0,不同则1。

00000000 00000000 00000000 00000011 &00000000 00000000 00000000 00000100

----------------------------------- 00000000 00000000 00000000 00000111 结果是:7

~按位取反运算符:0变1,1变0

00000000 00000000 00000000 00000011

~11111111 11111111 11111111 11111100 (补码)

补码:11111111 11111111 11111111 11111100 反码:11111111 11111111 11111111 11111011 原码:10000000 00000000 00000000 00000100 结果是:-4 面试题:

<<:左移 左边最高位丢弃,右边补齐0

>>:右移 最高位是0,左边补齐0;最高为是1,左边补齐1 >>>:无符号右移 无论最高位是0还是1,左边补齐0

请用最有效率的方式写出计算2乘以8的结果? 2 * 8 2 << 3

class OperatorDemo {

public static void main(String[] args) { //<< 把<<左边的数据乘以2的移动次幂

System.out.println(3 << 2); //3*2^2 = 3*4 = 12;

//>> 把>>左边的数据除以2的移动次幂

System.out.println(24 >> 2); //24 / 2^2 = 24 / 4 = 6 System.out.println(24 >>> 2); //6

System.out.println(-24 >> 2); //-6

System.out.println(-24 >>> 2); //1073741818 } }

详细分析:

计算出3的二进制:11

00000000 00000000 00000000 00000011 (00)000000 00000000 00000000 0000001100 计算出24的二进制11000

00000000 00000000 00000000 00011000 0000000000 00000000 00000000 000110(00)

计算出24的二进制:11000

原码:10000000 00000000 00000000 00011000

反码:11111111 11111111 11111111 11100111 补码:11111111 11111111 11111111 11101000

11111111 11111111 11111111 11101000

1111111111 11111111 11111111 111010(00) 补码

补码:1111111111 11111111 11111111 111010 反码:1111111111 11111111 11111111 111001 原码:1000000000 00000000 00000000 000110

结果:-6

>>>的移动:

计算出24的二进制:11000

原码:10000000 00000000 00000000 00011000 反码:11111111 11111111 11111111 11100111 补码:11111111 11111111 11111111 11101000

11111111 11111111 11111111 11101000 0011111111 11111111 11111111 111010(00)

结果:1073741818 /*

面试题:

请自己实现两个整数变量的交换 */

class OperatorDemo {

public static void main(String[] args) { int a = 10; int b = 20;

System.out.println(\+a+\+b);

//方式1:使用第三方变量(开发中用的)

int c = a; a = b; b = c;

System.out.println(\+a+\+b); System.out.println(\);

//方式2:用位异或实现(面试用)

//左边:a,b,a //右边:a ^ b

a = a ^ b;

b = a ^ b; //a ^ b ^ b = a a = a ^ b; //a ^ b ^ a = b

System.out.println(\+a+\+b);

//方式3:用变量相加的做法

a = a + b; //a=30 b = a - b; //b=10 a = a - b; //a=20

System.out.println(\+a+\+b);

//方式4:一句话搞定

b = (a+b) - (a=b); //b=30-20=10,a=20 System.out.println(\+a+\+b); } } /*

练习:

获取两个整数中的最大值 获取三个整数中的最大值 比较两个整数是否相同 */

public class OperatorTest {

public static void main(String[] args) { //获取两个整数中的最大值 int x = 100; int y = 200;

int max = (x > y? x: y);

System.out.println(\+max); System.out.println(\);

//获取三个整数中的最大值 int a = 10; int b = 30; int c = 20;

//分两步:

//A:先比较a,b的最大值

//B:拿a,b的最大值再和c进行比较 int temp = ((a > b)? a: b); //System.out.println(temp); max = (temp > c? temp: c);

System.out.println(\+max);

//一步搞定

//int max = (a > b)?((a > c)? a: c):((b > c)? b: c); //这种做法不推荐。

//int max = a > b?a > c? a: c:b > c? b: c; //System.out.println(\ System.out.println(\);

//比较两个整数是否相同 int m = 100; int n = 200;

boolean flag = (m == n); System.out.println(flag); } }

If语句与三目运算符的区别:

由于if语句的第二种格式刚才也完成了三元运算符可以完成的效果。 所以,我们就认为他们可以完成一样的操作。 但是,他们就一点区别没有吗?肯定不是。

区别:

三元运算符实现的,都可以采用if语句实现。反之不成立。

什么时候if语句实现不能用三元改进呢?

当if语句控制的操作是一个输出语句的时候就不能。

为什么呢?因为三元运算符是一个运算符,运算符操作完毕就应该有一个结果,而不是一个输出。

面试题:

字符参与运算

是查找ASCII里面的值 'a' 97 'A' 65 '0' 48

System.out.println('a'); //a System.out.println('a' + 1); //98

字符串参与运算

这里其实是字符串的连接

System.out.println(\+'a'+1); //helloa1 System.out.println('a'+1+\); //98hello System.out.println(\+5+5); //5+5=55 System.out.println(5+5+\); //10=5+5 24.

面试题:

byte可以作为switch的表达式吗? //可以 long可以作为switch的表达式吗? //不可以

String可以作为switch的表达式吗? //JDK7以后可以是字符串 25. 面试题

静态代码块,构造代码块,构造方法的执行顺序? 静态代码块 > 构造代码块 > 构造方法 静态代码块:只执行一次

构造代码块:每次调用构造方法都执行 class Code { //静态代码块 static {

int a = 100;

System.out.println(a); }

//构造代码块 {

int x = 1000;

System.out.println(x); }

//构造方法

public Code(){

System.out.println(\); }

//构造代码块 {

int y = 2000;

System.out.println(y); }

//静态代码块 static {

int b = 200;

System.out.println(b); } }

public class CodeDemo {

public static void main(String[] args) { //局部代码块 {

int x = 10;

System.out.println(x); }

//找不到符号

//System.out.println(x); {

int y = 20;

System.out.println(y); }

System.out.println(\);

Code c1 = new Code();

System.out.println(\); Code c2 = new Code(); } }

输出结果: 10 20

--------------- 100 200 1000 2000 code

--------------- 1000 2000 Code

看程序写结果: class Student { static {

System.out.println(\静态代码块\);

} {

System.out.println(\构造代码块\); }

public Student() {

System.out.println(\构造方法\); } }

public class StudentDemo { static {

System.out.println(\你好,明天!\); }

public static void main(String[] args) { System.out.println(\我是main方法\);

Student s1 = new Student(); Student s2 = new Student(); }

/*输出结果: 你好,明天! 我是main方法

Student 静态代码块 Student 构造代码块 Student 构造方法 Student 构造代码块 Student 构造方法*/ }

问题:不仅要输出局部范围的num,还要输出本类成员范围的num,我还想要输出父类成员范围的num。怎么办呢? class Father {

public int num = 10; }

class Son extends Father { public int num = 20;

public void show() { int num = 30;

System.out.println(num);

System.out.println(this.num); System.out.println(super.num); } }

class ExtendsDemo {

public static void main(String[] args) { Son s = new Son(); s.show(); } }

数据初始化的面试题

A:一个类的初始化过程 B:子父类的构造执行过程 C:分层初始化 class Father {

public Father() {

System.out.println(\的无参构造方法\); }

public Father(String name) {

System.out.println(\的带参构造方法\); } }

class Son extends Father { public Son() { //super();

System.out.println(\的无参构造方法\); }

public Son(String name) { //super();

System.out.println(\的带参构造方法\); } }

class ExtendsDemo {

public static void main(String[] args) { //创建对象 new Son();

System.out.println(\);

new Son(\蒙蒙\);

//运行结果:

//Father的无参构造方法 //Son的无参构造方法 //------------

//Father的无参构造方法 //Son的带参构造方法 } }

看程序写结果: A:成员变量 就近原则 B:this和super的问题 this访问本类的成员 super访问父类的成员

C:子类构造方法执行前默认先执行父类的无参构造方法 D:一个类的初始化过程 成员变量进行初始化 默认初始化 显示初始化 构造方法初始化 class Fu{

public int num = 10; public Fu(){

System.out.println(\); } }

class Zi extends Fu{ public int num = 20; public Zi(){

System.out.println(\); }

public void show(){ int num = 30;

System.out.println(num); //30 System.out.println(this.num); //20 System.out.println(super.num); //10 } }

class ExtendsTest {

public static void main(String[] args) { Zi z = new Zi();

z.show(); } }

结果: fu zi 30 20 10

看程序写结果:

A:一个类的静态代码块,构造代码块,构造方法的执行流程 静态代码块 > 构造代码块 > 构造方法 B:静态的内容是随着类的加载而加载 静态代码块的内容会优先执行

C:子类初始化之前先会进行父类的初始化 class Fu { static {

System.out.println(\静态代码块Fu\); }

{

System.out.println(\构造代码块Fu\); }

public Fu() {

System.out.println(\构造方法Fu\); } }

class Zi extends Fu { static {

System.out.println(\静态代码块Zi\); }

{

System.out.println(\构造代码块Zi\); }

public Zi() {

System.out.println(\构造方法Zi\); } }

public class ExtendsTest {

public static void main(String[] args) { Zi z = new Zi();

/*

结果是:

静态代码块Fu 静态代码块Zi 构造代码块Fu 构造方法Fu 构造代码块Zi 构造方法Zi*/ } }

看程序写结果:

A:成员变量的问题

int x = 10; //成员变量是基本类型 Student s = new Student(); //成员变量是引用类型 B:一个类的初始化过程 成员变量的初始化 默认初始化 显示初始化 构造方法初始化

C:子父类的初始化(分层初始化)

先进行父类初始化,然后进行子类初始化。 问题:

虽然子类中构造方法默认有一个super() 初始化的时候,不是按照那个顺序进行的。 而是按照分层初始化进行的。

它仅仅表示要先初始化父类数据,再初始化子类数据。 class X {

Y b = new Y(); X() {

System.out.print(\); } }

class Y { Y() {

System.out.print(\); } }

public class Z extends X { Y y = new Y(); Z() {

//super();

System.out.print(\); }

public static void main(String[] args) { new Z(); } }

结果: YXYZ

面试题:

package,import,class有没有顺序关系? 有。

package > import > class

Package:只能有一个 import:可以有多个

class:可以有多个,以后建议是一个

面试题:

局部内部类访问局部变量的注意事项?

A:局部内部类访问局部变量必须用final修饰 B:为什么呢?

局部变量是随着方法的调用而调用,随着调用完毕而消失。 而堆内存的内容并不会立即消失。所以,我们加final修饰。 加入final修饰后,这个变量就成了常量。既然是常量。你消失了。

我在内存中存储的是数据20,所以,我还是有数据在使用。

面试题:

要求请填空分别输出30,20,10。 注意:

1:内部类和外部类没有继承关系。 2:通过外部类名限定this对象 Outer.this

成员内部类的面试题(填空) 控制台输出:30,20,10 class Outer {

public int num = 10;

class Inner {

public int num = 20; public void show() { int num = 30;

System.out.println(num);

System.out.println(this.num);

System.out.println(Outer.this.num); } } }

class InnerClassTest {

public static void main(String[] args) {

Outer.Inner oi = new Outer().new Inner(); oi.show(); } }

//匿名内部类面试题: //按照要求,补齐代码

//要求在控制台输出”HelloWorld” /*

interface Inter { void show(); }

class Outer { //补齐代码 }

class OuterDemo {

public static void main(String[] args) { Outer.method().show(); } } */

//答案:

interface Inter { void show(); //public abstract }

class Outer { //补齐代码

public static Inter method() { //子类对象 -- 子类匿名对象

return new Inter() { public void show() {

System.out.println(\ } }; } }

class OuterDemo {

public static void main(String[] args) { Outer.method().show();

//1:Outer.method()可以看出method()应该是Outer中的一个静态方法。

//2:Outer.method().show()可以看出method()方法的返回值是一个对象。

// 又由于接口Inter中有一个show()方法,所以我认为method()方法的返回值类型是一个接口。 } }

字符串的面试题(看程序写结果)

==和equals()的区别?

A:==

基本类型:比较的是值是否相同 引用类型:比较的是地址值是否相同 B:equals()

只能比较引用类型。默认情况下,比较的是地址值是否相同。 但是,我们可以根据自己的需要重写该方法。

A:==和equals()

String s1 = new String(\ String s2 = new String(\

System.out.println(s1 == s2);// false System.out.println(s1.equals(s2));// true

String s3 = new String(\ String s4 = \

System.out.println(s3 == s4);// false System.out.println(s3.equals(s4));// true

String s5 = \ String s6 = \

System.out.println(s5 == s6);// true

System.out.println(s5.equals(s6));// true B:字符串的拼接 /*

* 字符串如果是变量相加,先开空间,再拼接。

* 字符串如果是常量相加,是先加,然后在常量池找,如果有就直 接返回,否则,就创建。 */

public class StringDemo {

public static void main(String[] args) { String s1 = \ String s2 = \

String s3 = \

System.out.println(s3 == s1 + s2);// false

System.out.println(s3.equals((s1 + s2)));// true

System.out.println(s3 == \这个我们错了,应该是true

System.out.println(s3.equals(\+ \true

// 通过反编译看源码,我们知道这里已经做好了处理。 // System.out.println(s3 == \

// System.out.println(s3.equals(\ }

}

面试题:

StringBuffer:同步的,数据安全,效率低。

StringBuilder:不同步的,数据不安全,效率高。

1:String,StringBuffer,StringBuilder的区别?

A:String是内容不可变的,而StringBuffer,StringBuilder都是内容可变的。 B:StringBuffer是同步的,数据安全,效率低;StringBuilder是不同步的,数据不安全,效率高

2:StringBuffer和数组的区别?

二者都可以看出是一个容器,装其他的数据。

但是呢,StringBuffer的数据最终是一个字符串数据。 而数组可以放置多种数据,但必须是同一种数据类型的。

3:形式参数问题

String作为参数传递

StringBuffer作为参数传递

形式参数:

基本类型:形式参数的改变不影响实际参数 引用类型:形式参数的改变直接影响实际参数

注意:

String作为参数传递,效果和基本类型作为参数传递是一样的。 面试题

-128到127之间的数据缓冲池问题

注意:Integer的数据直接赋值,如果在-128到127之间,会直接从缓冲池里获取数据

通过查看源码,我们就知道了,针对-128到127之间的数据,做了一个数据缓冲池,如果数据是该范围内的,每次并不创建新的空间

注意:

public class BigDecimalDemo {

public static void main(String[] args) { System.out.println(0.09 + 0.01); System.out.println(1.0 - 0.32); System.out.println(1.015 * 100); System.out.println(1.301 / 100);

System.out.println(1.0 - 0.12);

//0.09999999999999999 //0.6799999999999999 //101.49999999999999 //0.013009999999999999 //0.88 } }

面试题:数组有没有length()方法呢?字符串有没有length()方法呢?集合有没有length()方法呢?

List:(面试题List的子类特点) ArrayList:

底层数据结构是数组,查询快,增删慢。 线程不安全,效率高。 Vector:

底层数据结构是数组,查询快,增删慢。 线程安全,效率低。 LinkedList:

底层数据结构是链表,查询慢,增删快。

线程不安全,效率高。

List有三个儿子,我们到底使用谁呢? 看需求(情况)。 要安全吗?

要:Vector(即使要安全,也不用这个了,后面有替代的) 不要:ArrayList或者LinkedList 查询多:ArrayList 增删多:LinkedList

如果你什么都不懂,就用ArrayList。

面试题:

Collection和Collections的区别?

Collection:是单列集合的顶层接口,有子接口List和Set。

Collections:是针对集合操作的工具类,有对集合进行排序和二分查找的方法

1.Hashtable和HashMap的区别?

Hashtable:线程安全,效率低。不允许null键和null值 HashMap:线程不安全,效率高。允许null键和null值

2.List,Set,Map等接口是否都继承子Map接口?

List,Set不是继承自Map接口,它们继承自Collection接口 Map接口本身就是一个顶层接口

编译时异常和运行时异常的区别

编译期异常:Java程序必须显示处理,否则程序就会发生错误,无法通过编译 运行期异常:无需显示处理,也可以和编译时异常一样处理

throws和throw的区别(面试题) throws

用在方法声明后面,跟的是异常类名 可以跟多个异常类名,用逗号隔开

表示抛出异常,由该方法的调用者来处理

throws表示出现异常的一种可能性,并不一定会发生这些异常 throw

用在方法体内,跟的是异常对象名 只能抛出一个异常对象名

表示抛出异常,由方法体内的语句处理

throw则是抛出了异常,执行throw则一定抛出了某种异常

finally关键字及其面试题

1:final,finally和finalize的区别

final:最终的意思,可以修饰类,成员变量,成员方法 修饰类,类不能被继承 修饰变量,变量是常量 修饰方法,方法不能被重写

finally:是异常处理的一部分,用于释放资源。

一般来说,代码肯定会执行,特殊情况:在执行到finally之前jvm退出了

finalize:是Object类的一个方法,用于垃圾回收

2:如果catch里面有return语句,请问finally里面的代码还会执行吗? 如果会,请问是在return前,还是return后。 会。前。

准确的说,应该是在中间。

3:try...catch...finally的格式变形 A:try...catch...finally B:try...catch

C:try...catch...catch...

D:try...catch...catch...finally E:try...finally

这种做法的目前是为了释放资源。

面试题:

public class FinallyDemo {

public static void main(String[] args) { System.out.println(getInt()); }

public static int getInt() { int a = 10; try {

System.out.println(a / 0); a = 20;

} catch (ArithmeticException e) { a = 30; return a; /*

* return a在程序执行到这一步的时候,这里不是return a而是return 30;这个返回路径就形成了。

* 但是呢,它发现后面还有finally,所以继续执行finally的内容,a=40

* 再次回到以前的返回路径,继续走return 30; */

} finally { a = 40;

//return a;//如果这样结果就是40了。 }

return a; } }

面试题:

什么时候序列化? 如何实现序列化? 什么是反序列化?

调用run()方法为什么是单线程的呢?

因为run()方法直接调用其实就相当于普通的方法调用,所以你看到的是单线程的效果

要想看到多线程的效果,就必须说说另一个方法:start() 面试题:run()和start()的区别?

run():仅仅是封装被线程执行的代码,直接调用是普通方法

start():首先启动了线程,然后再由jvm去调用该线程的run()方法。

多线程常见面试题:

1:多线程有几种实现方案,分别是哪几种? 两种。

继承Thread类 实现Runnable接口

扩展一种:实现Callable接口。这个得和线程池结合。

2:同步有几种方式,分别是什么? 两种。

同步代码块 同步方法

3:启动一个线程是run()还是start()?它们的区别? start();

run():封装了被线程执行的代码,直接调用仅仅是普通方法的调用 start():启动线程,并由JVM自动调用run()方法

4:sleep()和wait()方法的区别

sleep():必须指定时间;不释放锁。

wait():可以不指定时间,也可以指定时间;释放锁。

5:为什么wait(),notify(),notifyAll()等方法都定义在Object类中

因为这些方法的调用是依赖于锁对象的,而同步代码块的锁对象是任意锁。 而Object代表任意的对象,所以,定义在这里面。

6:线程的生命周期图

新建 -- 就绪 -- 运行 -- 死亡

新建 -- 就绪 -- 运行 -- 就绪 -- 运行 -- 死亡

新建 -- 就绪 -- 运行 -- 其他阻塞 -- 就绪 -- 运行 -- 死亡 新建 -- 就绪 -- 运行 -- 同步阻塞 -- 就绪 -- 运行 -- 死亡

新建 -- 就绪 -- 运行 -- 等待阻塞 -- 同步阻塞 -- 就绪 -- 运行 -- 死亡

面试题:单例模式的思想是什么?请写一个代码体现。

面试题:close()和flush()的区别?

A:close()关闭流对象,但是先刷新一次缓冲区。关闭之后,流对象不可以继续再使用了。

B:flush()仅仅刷新缓冲区,刷新之后,流对象还可以继续使用。

本文来源:https://www.bwwdw.com/article/o7ro.html

Top