java常见题2

6.String作为hashmap的键为什么好?

image-20221112210212234

调用时放到成员变量了 效率会高一点

7.finally和return之间的纠缠
public class Test{	
    public int add(int a,int b){	
         try {	
             return a+b;		
         } 
        catch (Exception e) {	
            System.out.println("catch语句块");	
         }	
         finally{	
             System.out.println("finally语句块");	
         }	
         return 0;	
    } 
     public static void main(String argv[]){ 
         Test test =new Test(); 
         System.out.println("和是:"+test.add(9, 34)); 
     }
}

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

先来看一段代码:

public abstract class Test {
    public static void main(String[] args) {
        System.out.println(beforeFinally());
    }
    
    public static int beforeFinally(){
        int a = 0;
        try{
            a = 1;
            return a;
        }finally{
            a = 2;
        }
    }
}
/**output:
1
*/

从结果上看,貌似finally 里的语句是在return 之后执行的,其实不然,实际上finally 里的语句是在在return 之前执行的。那么问题来了,既然是在之前执行,那为什么a 的值没有被覆盖了?
实际过程是这样的:当程序执行到try{}语句中的return方法时,它会干这么一件事,将要返回的结果存储到一个临时栈中,然后程序不会立即返回,而是去执行finally{}中的程序, 在执行a = 2时,程序仅仅是覆盖了a的值,但不会去更新临时栈中的那个要返回的值 。执行完之后,就会通知主程序“finally的程序执行完毕,可以请求返回了”,这时,就会将临时栈中的值取出来返回。这下应该清楚了,要返回的值是保存至临时栈中的。
再来看一个例子,稍微改下上面的程序:

public abstract class Test {
    public static void main(String[] args) {
        System.out.println(beforeFinally());
    }
    
    public static int beforeFinally(){
        int a = 0;
        try{
            a = 1;
            return a;
        }finally{
            a = 2;
            return a;
        }
    }
}
/**output:
2
*/

在这里,finally{}里也有一个return,那么在执行这个return时,就会更新临时栈中的值。同样,在执行完finally之后,就会通知主程序请求返回了,即将临时栈中的值取出来返回。故返回值是2.

总结:可以把return时看成一个临时储存了 然后去执行finally,finally过程中新的return可以覆盖旧的。

注意:finally块中的return语句会阻止异常的栈调用传输,使caller认为该方法已经正常返回,让catch中抛的异常失效。

finally块中的throw语句会覆盖try和catch语句中的异常。

8.不会初始化子类的3种情况
  1. 调用的是父类的static方法或者字段

    static是在类构造方法执行初始化的。会触发子类的加载、父类的初始化,不会导致子类初始化

2.调用的是父类的final方法或者字段 子类和父类都不会初始化!

  • final+static修饰:使用ConstantValue属性赋值。

    ConstantValue是字节码指令,final修饰的String和基本数据类型都在编译时就初始了

  • 仅仅使用static修饰:在类构造方法中赋值。

image-20221211223530708

类构造方法在初始化阶段,final修饰的String和基本数据在这些之前的编译阶段

final修饰,也就是在编译器把结果放入常量池中

  1. 通过数组来引用
 SuperClass[] superClasses = new SuperClass[10];
9.String s = new String(" a ") 到底产生几个对象?

1或者2个

"a"在字符串常量池存在了 就是1个 不存在就是2个

10.String s=“java”+“and”+360 到底产生几个对象?;

1个

通过反编译。

​ 因为字符串字面量拼接操作是在Java编译器编译期间就执行了,也就是说编译器编译时,直接把"java"、"and"和"360 “这三个字面量进行”+"操作得到一个"javaand360 " 常量,并且直接将这个常量放入字符串池中,这样做实际上是一种优化

这是因为在编译期间,应用了编译器优化中一种被称为常量折叠(Constant Folding)的技术,会将编译期常量的加减乘除的运算过程在编译过程中折叠。编译器通过语法分析,会将常量表达式计算求值,并用求出的值来替换表达式,而不必等到运行期间再进行运算处理,从而在运行期间节省处理器资源。

完整满足下面的要求 会常量折叠

  • 被声明为final
  • 基本类型或者字符串类型
  • 声明时就已经初始化
  • 使用常量表达式进行初始化

String s = “java”

如果是 String s = “java”,如果原来字符串常量池有“java”,就直接将s指向字符串常量池的“java”,不会创建新的对象。如果原来字符串常量池没有“java”,则会在字符串常量池创建一个新的“java”对象;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值