
ps:我把答案都放在解析下面了
初识想法:我感觉好像都对,但是这是360的,但是应该有坑,果不其然有坑
解析:常见的代码优化技术有:复写传播,删除死代码,强度削弱,归纳变量删除,那么这几个名词都是什么意思呢?
复写传播:优化过程中会大量引入复写
a = d+e;
b= d+e;
c = b;
复写传播变换的做法是在复写语句c=b之后,尽量用b代替c,本身不算优化,但是是为了给其他的优化带来机会,可以完成如下 *** 作:常量合并(编译时可完成的计算),死代码删除
删除死代码:死代码是指计算的结果不会影响结果的语句,复写传播后可能会产生死代码,即可清理删除
int a=1,b=1,c=1,d=1;
a = d+e;
b= d+e;
c = b;
ArrayList list = new ArrayList();
list.add(1);
System.out.println(list.get(b));
这个时候,我们会发现c的计算毫无意义,直接用的是b的值来取值,即c就是死代码,可以直接清除
削弱强度:代码外提能够削弱强度
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
//代码外提
int length = list.size();
for (int i = 0; i < length; i++) {
System.out.println(list.get(i));
}
当我们需要遍历list数组的时候,如果将list.size()直接放进i循环,意味着每次循环都会计算一次list.size(),这个时候我们就讲list.size()提取出来,定义一个变量,用空间换取时间性能
归纳变量删除
a = a - 1;
b = 4 * a;
list.add(b);
//归纳变量删除
list.add(4*(a-1));
当a和b是成倍的增长的时候,我们可以不用创建新的变量b来接收值,直接用a就好了
答案:ABD
- 关于Float,下列说法错误的是?
A. Float是一个类
B. Float在java.lang包中
C. Float a=1.0是正确的赋值方法
D. Float a= new Float(1.0)是正确的赋值方法
初识想法:Float是float装箱的类
解析:
因为java默认1.0是Double类型的,所以这里要么向上类型转换(强制类型转换),要么将1.0变成float类型
Float a = new Float(1.0); 这个的东西能存在,是因为Float类中有形参是float和double的两个构造器。
Double d = new Double(1.0F);这个能成立的原因是float向上转型了。
Float a = 1.0;这个东西不成立是因为浮点型的默认类型是double,而double不会自动转成float,然后再装箱。
Double d = 1.0f;不成立的原因是因为Double类中的装箱方法,只有valueOf(String s)和valueOf(double d);装箱本身可不会自动向上转型啊。
答案:C
- 以下代码输出为什么?
public class Demo3 {
private String name = "abc";
public static void main(String[] args) {
Demo3 d1 = new Demo3();
Demo3 d2 = new Demo3();
System.out.print(d1.equals(d2) + ",");
System.out.print(d1.name.equals(d2.name) + ",");
System.out.println(d1.name == d2.name);
}
}
初识想法:我记得equals方法比较基本数据类型是比较其值,而比较引用数据类型是比较其地址值,所以第一行肯定是false,
解析:这道题涉及到jvm中数据的存储空间问题,由于反编译文件太长,我们直接用文字和画图来解释
- 首先name是直接复制的,这种赋值的执行过程是先看字符串常量池中有没有[‘a’,‘b’,‘c’]的char数组,如果没有就创建一个,有的话直接拿他的引用(地址)name没有被static修饰所以一开始串池中没有abc这个对象,当第一次调用的时候创建,第二次创建对象的时候,发现串池中已经有了,所以直接拿了他的引用(哈希值)
答案:false,true,true
- try括号里有return语句,finally执行的顺序
A. 不执行finally代码
B. return前执行
C. return后执行
初识想法:首先排除A,finally代码必然执行,那么是在return前还后呢?
解析:我们通过代码来演示,我们先来看一段代码
public class Demo4 {
public static void main(String[] args) {
int i = 0;
int add = add(i);
System.out.println(add);
}
static int add(int i) {
try {
i = 1;
return i;
} catch (Exception e) {
System.out.println(e);
} finally {
i = 2;
System.out.println("我是finally");
}
return i;
}
}
这段代码应该输出的是什么呢?如果finally在return前执行i应该等于什么,在return后输出i应该等于什么呢?
看到这里我先告诉大家finally是在return前执行的,如果有小朋友疑惑为什么输出是1,看看上一篇博客,这里也是小编挖的一个坑。
我们来看这段代码会更明显一点
public class Demo4 {
public static void main(String[] args) {
StringBuffer s = new StringBuffer("a");
StringBuffer add = add(s);
System.out.println(add);
}
static StringBuffer add(StringBuffer s) {
try {
s.append("b");
return s;
} catch (Exception e) {
System.out.println(e);
} finally {
s.append("c");
System.out.println("我是finally");
}
return s;
}
}
这段代码输出的是
所以,我们能看出来先将b用append方法连接上a,再将c连接上b,最后返回回去,产生abc
答案:B
- 对于线程局部存储TLS(thread local storage)以下描述正确的是?
A. TLS是解决多线程中的堆同意变量的一种技术
B. TLS会为每一个线程维护一个和该线程绑定的变量的副本
C. 每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了
D. Java平台的java.lang.ThreadLocal是TLS技术的一种实现
初识想法:在SSM中使用过ThreadLocal类,这个类有自己的内存空间,不会被别的线程干扰
解析:C:同一局部变量或静态变量每个线程访问的是同一变量,多个线程同时存放同一全局变量或者静态变量时会导致冲突,尤其是多个线程同时需要修改这一个变量的时候,通过TSL机制,为每一个使用该全局变量的线程都义工一个变量值的副本,每一个线程可以独立地改变自己的副本,而不会和其他线程的副本发生冲突,而ThreadLocal只能存储一个值,若存储其它值会被替换为最后一个执行set方法的值
答案:ABD
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)