1、Java经典面试题及答案1、访问修饰符public,private,protected,以及不写(默认)时的区别?答:区别如下:作用域 当前类 同包 子类 其他public protected default private 类的成员不写访问修饰时默认为default。默认对于同一个包中的其他类相当于公开(public),对于不是同一个包中的其他类相当于私有(private)。受保护(protected)对子类相当于公开,对不是同一包中的没有父子关系的类相当于私有。2、float f=3.4;是否正确?答:不正确。3.4 是双精度数,将双精度型(double)赋值给浮点型(float)属于下转
2、型(down-casting,也称为窄化)会造成精度损失,因此需要强制类型转换float f =(float)3.4; 或者写成float f =3.4F;。3、Java 有没有goto?答:goto 是Java中的保留字,在目前版本的Java中没有使用。其中有 goto 和 const,但是这两个是目前无法使用的关键字,因此有些地方将其称之为保留字,其实保留字这个词应该有更广泛的意义,因为熟悉 C 语言的程序员都知道,在系统类库中使用过的有特殊意义的单词或单词的组合都被视为保留字)4、&和&的区别?答:&运算符有两种用法:(1)按位与;(2)逻辑与。&运算符是短路与运算。逻辑与跟短路与的差别
3、是非常巨大的,虽然二者都要求运算符左右两端的布尔值都是 true 整个表达式的值才是 true。&之所以称为短路运算是因为,如果&左边的表达式的值是 false,右边的表达式会被直接短路掉,不会进行运算。很多时候我们可能都需要用&而不是&,例如在验证用户登录时判定用户名不是null而且不是空字符串,应当写为:username != null &!username.equals(“”),二者的顺序不能交换,更不能用&运算符,因为第一个条件如果不成立,根本不能进行字符串的equals比较,否则会产生NullPointerException异常。注意:逻辑或运算符(|)和短路或运算符(|)的差别也是
4、如此。补充:如果你熟悉 JavaScript,那你可能更能感受到短路运算的强大,想成为JavaScript的高手就先从玩转短路运算开始吧。5、Math.round(11.5) 等于多少? Math.round(-11.5)等于多少?答:Math.round(11.5)的返回值是12,Math.round(-11.5)的返回值是-11。四舍五入的原理是在参数上加0.5然后进行下取整。6、用最有效率的方法计算2乘以8?答: 2 3(左移3位相当于乘以2的3次方,右移3位相当于除以2的3次方)。补充:我们为编写的类重写 hashCode 方法时,可能会看到如下所示的代码,其实我们不太理解为什么要使用
5、这样的乘法运算来产生哈希码(散列码),而且为什么这个数是个素数,为什么通常选择31这个数?前两个问题的答案你可以自己XX一下,选择31是因为可以用移位和减法运算来代替乘法,从而得到更好的性能。说到这里你可能已经想到了:31 * num (num 0); / throws an AssertionError if a = 0断言可以有两种形式:assert Expression1;assert Expression1 : Expression2 ;Expression1 应该总是产生一个布尔值。Expression2 可以是得出一个值的任意表达式;这个值用于生成显示更多调试信息的字符串消息。断言
6、在默认情况下是禁用的,要在编译时启用断言,需使用source 1.4 标记:javac -source 1.4 Test.java要在运行时启用断言,可使用-enableassertions 或者-ea 标记。要在运行时选择禁用断言,可使用-da 或者-disableassertions 标记。要在系统类中启用断言,可使用-esa 或者-dsa 标记。还可以在包的基础上启用或者禁用断言。可以在预计正常情况下不会到达的任何位置上放置断言。断言可以用于验证传递给私有方法的参数。不过,断言不应该用于验证传递给公有方法的参数,因为不管是否启用了断言,公有方法都必须检查其参数。不过,既可以在公有方法中,
7、也可以在非公有方法中利用断言测试后置条件。另外,断言不应该以任何方式改变程序的状态。23、try里有一个return语句,那么紧跟在这个try后的finally里的code会不会被执行,什么时候被执行,在return前还是后?答:会执行,在方法返回调用者前执行。Java允许在finally中改变返回值的做法是不好的,因为如果存在 finally 代码块,try 中的return 语句不会立马返回调用者,而是记录下返回值待finally代码块执行完毕之后再向调用者返回其值,然后如果在finally中修改了返回值,这会对程序造成很大的困扰,C#中就从语法上规定不能做这样的事。24、Java 语言如
8、何进行异常处理,关键字:throws、throw、try、catch、finally分别如何使用?答:Java 通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口。在Java 中,每个异常都是一个对象,它是Throwable 类或其子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中包含有异常信息,调用这个对象的方法可以捕获到这个异常并进行处理。Java 的异常处理是通过5 个关键词来实现的:try、catch、throw、throws 和finally。一般情况下是用try 来执行一段程序,如果出现异常,系统会抛出(throw)一个异常,这时候你可以通过它的
9、类型来捕捉(catch)它,或最后(finally)由缺省处理器来处理;try 用来指定一块预防所有“异常”的程序;catch 子句紧跟在try块后面,用来指定你想要捕捉的“异常”的类型; throw 语句用来明确地抛出一个“异常”;throws用来标明一个成员函数可能抛出的各种“异常”;finally 为确保一段代码不管发生什么“异常”都被执行一段代码;可以在一个成员函数调用的外面写一个try 语句,在这个成员函数内部写另一个try 语句保护其他代码。每当遇到一个try 语句,“异常”的框架就放到栈上面,直到所有的try 语句都完成。如果下一级的 try 语句没有对某种“异常”进行处理,栈就
10、会展开,直到遇到有处理这种“异常”的try 语句。25、列出一些你常见的运行时异常?答:ArithmeticException(算术异常)ClassCastException (类转换异常)IllegalArgumentException (非法参数异常)IndexOutOfBoundsException (下表越界异常)NullPointerException (空指针异常)SecurityException (安全异常)26、Java中实现多线程有几种方法 继承Thread类; 实现Runnable接口; 实现Callable接口通过FutureTask包装器来创建Thread线程; 使用
11、ExecutorService、Callable、Future实现有返回结果的多线程(也就是使用了ExecutorService来管理前面的三种方式)。27、notify()和notifyAll()有什么区别? notify可能会导致死锁,而notifyAll则不会 任何时候只有一个线程可以获得锁,也就是说只有一个线程可以运行synchronized 中的代码 使用notifyall,可以唤醒 所有处于wait状态的线程,使其重新进入锁的争夺队列中,而notify只能唤醒一个。wait() 应配合while循环使用,不应使用if,务必在wait()调用前后都检查条件,如果不满足,必须调用 no
12、tify()唤醒另外的线程来处理,自己继续wait()直至条件满足再往下执行。notify() 是对notifyAll()的一个优化,但它有很精确的应用场景,并且要求正确使用。不然可能导致死 锁。正确的场景应该是 WaitSet中等待的是相同的条件,唤醒任一个都能正确处理接下来的事项,如果 唤醒的线程无法正确处理,务必确保继续notify()下一个线程,并且自身需要重新回到WaitSet中。28、volatile 是什么?可以保证有序性吗? 一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语 义:1)保证了不同线程对这个变量进行操作时的可见性,即一
13、个线程修改了某个变量的值,这新值对其他 线程来说是立即可见的,volatile关键字会强制将修改的值立即写入主存。 2)禁止进行指令重排序。volatile 不是原子性操作什么叫保证部分有序性?当程序执行到volatile变量的读操作或者写操作时,在其前面的操作的更改肯定全部已经进行,且结果 已经对后面的操作可见;在其后面的操作肯定还没有进行;由于ag变量为volatile变量,那么在进行指令重排序的过程的时候,不会将语句3放到语句1、语句2前 面,也不会讲语句3放到语句4、语句5后面。但是要注意语句1和语句2的顺序、语句4和语句5的顺序是 不作任何保证的。使用 Volatile 一般用于 状
14、态标记量 和 单例模式的双检锁。29、为什么wait, notify 和 notifyAll这些方法不在thread类里面?明显的原因是JAVA提供的锁是对象级的而不是线程级的,每个对象都有锁,通过线程获得。如果线程需 要等待某些锁那么调用对象中的wait()方法就有意义了。如果wait()方法定义在Thread类中,线程正在 等待的是哪个锁就不明显了。简单的说,由于wait,notify和notifyAll都是锁级别的操作,所以把他们 定义在Object类中因为锁属于对象。30、Java中interrupted 和 isInterruptedd方法的区别? interrupted() 和 i
15、sInterrupted()的主要区别是前者会将中断状态清除而后者不会。Java多线程的中断机 制是用内部标识来实现的,调用Thread.interrupt()来中断一个线程就会设置中断标识为true。当中断线 程调用静态方法Thread.interrupted()来检查中断状态时,中断状态会被清零。而非静态方法 isInterrupted()用来查询其它线程的中断状态且不会改变中断状态标识。简单的说就是任何抛出 InterruptedException异常的方法都会将中断状态清零。无论如何,一个线程的中断状态有有可能被其 它线程调用中断来改变。31、有三个线程T1,T2,T3,如何保证顺序执
16、行? 在多线程中有多种方法让线程按特定顺序执行,你可以用线程类的join()方法在一个线程中启动另一个 线程,另外一个线程完成该线程继续执行。为了确保三个线程的顺序你应该先启动后一个(T3调用 T2,T2调用T1),这样T1就会先完成而T3后完成。实际上先启动三个线程中哪一个都行, 因为在每个线程的run方法中用join方法限定了三个线程的执行顺序。32、什么是线程安全 线程安全就是说多线程访问同一代码,不会产生不确定的结果。在多线程环境中,当各线程不共享数据的时候,即都是私有(private)成员,那么一定是线程安全的。 但这种情况并不多见,在多数情况下需要共享数据,这时就需要进行适当的同步控制了。线程安全一般都涉及到synchronized, 就是一段代码同时只能有一个线程来操作 不然中间过程可能会 产生不可预制的结果。如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运 行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。33、Java线程池中submit() 和 execute()方法有什
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1