笔试题细节整理

该程序编译不通过。被static修饰的变量称为静态变量,静态变量属于整个类,而局部变量属于方法,只在该方法内有效,所以static不能修饰局部变量

在《java虚拟机》一书中明确讲了,释放掉占据的内存空间是由gc完成,但是程序员无法明确强制其运行,该空间在不被引用的时候不一定会立即被释放,这取决于GC本身,无法由程序员通过代码控制。
对象失去引用链之后,只会被标记一次,然后对象被放入一个叫做F-Queue的队列中,在GC前,JVM会启动一个Finalizer的线程(优先级很低),去执行这个F-Queue队列中对象的finalize()方法,一旦对象的这个方法是第一次被调用,同时重写了finalize方法,在finalize中重新回到了引用链,那么这个对象就被移出F-Queue,一旦对象的finalize方法被调用过或者没有重写finalize或者没有重回引用链,那么直接被第二次标记。在下一次GC来的时候被GC掉。

链接:https://www.nowcoder.com/questionTerminal/521a37038afc4dd49f3d92a12b9a5907
来源:牛客网

为什么不是线程安全的呢?这是因为原子性问题,什么是原子性?大家知道cpu工作是以时间片的方式分配cpu资源,当一个线程正在执行的时候,如果此时失去时间片,那么它所有的工作都要暂停,原子性就是:一个完整不再能分割的操作。即使是时间片结束,也要完成当前的原子操作,否则不允许切换。 Synchronized:保证可见性和原子性, 在Java内存模型中,synchronized规定,线程在加锁时 ,先清空工作内存→在主内存中拷贝最新变量的副本到工作内存→执行完代码→将更改后的共享变量的值刷新到主内存中→释放互斥锁

volatile只能保证可见性和有序性,而无法保证原子性。所以volatile不是线程安全的。

输出:finally语句块

和是:43

首先finally执行是必然,没有先输出“和是:”是因为需要先计算add才算println的参数完整,才输出。

String x="fmn";
x.toUpperCase();
String y=x.replace('f','F');
y=y+"wxy";
System.out.println(y);
//Fmnwxy

String x="fmn";  “fmn”是在常量池里的不可变对象。x.toUpperCase();   在堆中new一个"FMN"对象,但无任何引用指向它。String y=x.replace('f','F'); 在堆中 new一个"Fmn"对象,y指向它。y=y+"wxy"; 在堆中 重新new一个"Fmnwxy"对象, 修改y指向,现在y指向它。

System是java.lang包下的一个类,out为System的final静态成员(PrintStream类型),println()是PrintStream类的实例方法。

java中,StringBuilder和StringBuffer的区别,下面说法错误的是?
A.StringBuffer是线程安全的
B.StringBuilder是非线程安全的
C.StringBuffer对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象。
D.效率比较String<StringBuffer<StringBuilder,但是在 String S1 = “This is only a” + “ simple” + “ test”时,String效率最高。

对String的修改其实是new了一个StringBuilder并调用append方法,然后调用toString返回一个新的String。

StringBuffer是在StringBuilder基础上加锁,加锁是一个重量级的操作,需要调用操作系统内核来实现,比较耗时。

因此效率明显有:String<StringBuffer<StringBuilder;

但是这个并不是绝对的,因为JVM会对String进行优化,譬如

String str = "i"+"love"+"java";

其中的字符串在编译时就能确认,编译器会直接将其拼接成一个字符串放在常量池:"i love java";

但是若是String a = "i";    String b = "love";    String c = "java";

String str = a+b+c;

只有运行时才能确认str最终是什么,编译器并不会进行优化,是通过StringBuilder实现的。

猜你喜欢

转载自blog.csdn.net/cuiyaocool/article/details/81432596