Java 笔试:常见题目总结

而是在编译时去掉其中的加号,直接将其编译成一个这些常量相连的结果。

写如下两行代码,

String s = “a” + “b” + “c” + “d”;

System.out.println(s == “abcd”);

最终打印的结果应该为true。


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

public class Test {

public static void main(String[] args) {

System.out.println(“return:” + new Test().test());

}

public int test() {

int x = 1;

try {

return x;

} finally {

++x;

System.out.println(“finally:” + x);

}

}

}

执行结果:

finally:2

return:1

那么下面的程序代码输出的结果是多少?

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(new Test().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语句后执行


3. final, finally, finalize的区别

  • final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。内部类要访问局部变量,局部变量必须定义成final类型

  • finally是异常处理语句结构的一部分,表示总是执行。

  • finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。JVM不保证此方法总被调用


4. Java中的异常处理机制的简单原理和应用

Java对异常进行了分类,不同类型的异常分别用不同的Java类表示,所有异常的根类为java.lang.Throwable,Throwable下面又派生了两个子类:ErrorException

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

  • Exception表示程序还能够克服和恢复的问题,其中又分为系统异常和普通异常,系统异常是软件本身缺陷所导致的问题,也就是软件开发人员考虑不周所导致的问题,软件使用者无法克服和恢复这种问题,但在这种问题下还可以让软件系统继续运行或者让软件死掉,例如:

数组越界(ArrayIndexOutOfBoundsException)

空指针异常(NullPointerException)

类转换异常(ClassCastException)

找不到类(ClassNotFoundException)

普通异常是运行环境的变化或异常所导致的问题,是用户能够克服的问题,例如:网络断线硬盘空间不够,发生这样的异常后,程序不应该死掉。

java为系统异常和普通异常提供了不同的解决方案,编译器强制

  • 系统异常可以处理也可以不处理,所以,编译器不强制用try…catch处理或用throws声明,所以系统异常也称为unchecked异常。

  • 普通异常必须try…catch处理或用throws声明继续抛给上层调用方法处理,所以普通异常也称为checked异常。

提示答题者,就按照三个级别去思考:

虚拟机必须宕机的错误

程序可以死掉也可以不死掉的错误

程序不应该死掉的错误


5. sleep() 和 wait() 有什么区别?

  • sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。

  • wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。)

下面用一个例子来说明:

public class Test {

public static void main(String[] args) {

new Thread(new Thread1()).start();

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

new Thread(new Thread2()).start();

}

private static class Thread1 implements Runnable {

@Override

public void run() {

// 由于这里的Thread1和下面的Thread2内部run方法要用同一对象作为监视器,

// 我们这里不能用this,因为在Thread2里面的this和这个Thread1的this不是同一个对象。

// 我们用Test.class这个字节码对象,当前虚拟机里引用这个变量时,指向的都是同一个对象。

synchronized (Test.class) {

System.out.println(“enter thread1…”);

System.out.println(“thread1 is waiting”);

try {

// 释放锁有两种方式:

// 第一种方式是程序自然离开监视器的范围,也就是离开了synchronized关键字管辖的代码范围,

// 另一种方式就是在synchronized关键字管辖的代码内部调用监视器对象的wait方法。

// 这里,使用wait方法释放锁。

Test.class.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(“thread1 is going on…”);

System.out.println(“thread1 is being over!”);

}

}

}

private static class Thread2 implements Runnable {

@Override

public void run() {

synchronized (Test.class) {

System.out.println(“enter thread2…”);

System.out.println(“thread2 notify other thread can release wait status…”);

// 由于notify方法并不释放锁,

// 即使thread2调用下面的sleep方法休息了10毫秒,

// 但thread1仍然不会执行,因为thread2没有释放锁,所以Thread1无法得不到锁。

Test.class.notify();

System.out.println(“thread2 is sleeping ten millisecond…”);

try {

Thread.sleep(10);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println(“thread2 is going on…”);

System.out.println(“thread2 is being over!”);

}

}

}

}

执行结果:

enter thread1…

thread1 is waiting

enter thread2…

thread2 notify other thread can release wait status…

thread2 is sleeping ten millisecond…

thread2 is going on…

thread2 is being over!

thread1 is going on…

thread1 is being over!

  • sleep就是正在执行的线程主动让出cpu,cpu去执行其他线程,在sleep指定的时间过后,cpu才会回到这个线程上继续往下执行,如果当前线程进入了同步锁,sleep方法并不会释放锁,即使当前线程使用sleep方法让出了cpu,但其他被同步锁挡住了的线程也无法得到执行

  • wait是指在一个已经进入了同步锁的线程内,让自己暂时让出同步锁,以便其他正在等待此锁的线程可以得到同步锁并运行,只有其他线程调用了notify()方法(notify并不释放锁,只是告诉调用过wait方法的线程可以去参与获得锁的竞争了,但不是马上得到锁,因为锁还在别人手里,别人还没释放。如果notify方法后面的代码还有很多,需要这些代码执行完后才会释放锁,可以在notfiy方法后增加一个等待和一些代码,看看效果),调用wait方法的线程就会解除wait状态和程序可以再次得到锁后继续向下运行。wait()必须在synchronized内部调用


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

分几种情况:

  1. 其他方法前是否加了synchronized关键字,如果没加,则能。

  2. 如果这个方法内部调用了wait,则可以进入其他synchronized方法。

  3. 如果其他个方法都加了synchronized关键字,并且内部没有调用wait,则不能。

  4. 如果其他方法是static,它用的同步锁是当前类的字节码,与非静态的方法不能同步,因为非静态的方法用的是this。


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

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

  • 主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。Lock还有更强大的功能,例如,它的tryLock方法可以非阻塞方式去拿锁。

例子:

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

public class Test {

private int j;

// ReentrantLock 可重入锁,

// 一个线程可以对已被加锁的ReentrantLock锁再次加锁

private Lock lock = new ReentrantLock();

public static void main(String[] args) {

Test tt = new Test();

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

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

}

private class SubTractor implements Runnable {

@Override

public void run() {

while (true) {

// synchronized (Test.this) {

// System.out.println(“j–=” + j–);

// //这里抛异常了,锁能释放吗?

// }

lock.lock();

try {

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

} finally {

lock.unlock();

}

}

}

}

private class Adder implements Runnable {

@Override

public void run() {

while (true) {

// synchronized (Test.this) {

// System.out.println(“j++=” + j++);

// }

lock.lock();

try {

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

} finally {

lock.unlock();

}

}

}

}

}

执行结果:

···

j++ = 42218

j++ = 42219

j++ = 42220

j-- = 42221

j-- = 42220

j-- = 42219

···


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

public class Test {

private int j;

public static void main(String args[]) {

Test tt = new Test();

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

}

}

}

最后

腾讯T3大牛总结的500页MySQL实战笔记意外爆火,P8看了直呼内行

腾讯T3大牛总结的500页MySQL实战笔记意外爆火,P8看了直呼内行

找小编(vip1024c)领取
ead 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();

}

}

}

最后

[外链图片转存中…(img-k1Lj9pKe-1721632032857)]

[外链图片转存中…(img-K0BOOIFI-1721632032858)]

找小编(vip1024c)领取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值