夜光序言:

女孩问:“你喜欢我吗?”
“不喜欢”男孩不假思索的回答
“哦”女孩失落地低下头,眼泪快要掉下来
“傻瓜,我不喜欢你,我爱你”男孩宠溺的摸摸女孩的头

正文:
 
                                              以道御术 / 以术识道



6. throw 和 throws 的区别

throw:
1)throw 语句用在方法体内,表示抛出异常,由方法体内的语句处理。
2)throw 是具体向外抛出异常的动作,所以它抛出的是一个异常实例,执行 throw 一定是抛出了某种异常。
throws
1)throws 语句是用在方法声明后面,表示如果抛出异常,由该方法的调用者来进行异常的处理。
2)throws 主要是声明这个方法会抛出某种类型的异常,让它的使用者要知道需要捕获的异常的类型。
3)throws 表示出现异常的一种可能性,并不一定会发生这种异常

7. final、finally、finalize 的区别?

1)final:用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,被其修饰的类不可继承。
2)finally异常处理语句结构的一部分,表示总是执行。
3)finalizeObject 类的一个方法,在垃圾回收器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。
该方法更像是一个对象生命周期的临终方法,当该方法被系统调用则代表该对象即将“死亡”
但是需要注意的是,我们主动行为上去调用该方法并不会导致该对象“死亡”,这是一个被动的方法(其实就是回调方法),不需要我们调用

五、JavaSE 常用 API

1. Math.round(11.5)等于多少?Math.round(- 11.5) 又等于多少?

Math.round(11.5)的返回值是 12,Math.round(-11.5)的返回值是-11。
四舍五入的原理是在参数上加 0.5然后进行取整。

2. switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String上?

Java5 以前 switch(expr)中,expr 只能是 byte、short、char、int。从 Java 5 开始,Java 中引入了枚举类型,
expr 也可以是 enum 类型。
从 Java 7 开始,expr 还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的

3. 数组有没有 length() 方法?String 有没有 length() 方法?

数组没有 length()方法,而是有 length 的属性。
String 有 length()方法。
JavaScript 中,获得字符串的长度是通过 length 属性得到的,这一点容易和 Java 混淆。

4. String 、StringBuilder 、StringBuffer 的区别?

Java 平台提供了两种类型的字符串:String 和 StringBuffer/StringBuilder,它们都可以储存和操作字符串,区别如下
1)String 是只读字符串,也就意味着 String 引用的字符串内容是不能被改变的。
初学者可能会有这样的误解:
1. String str = “abc”;
2. str = “bcd”;
如上,字符串 str 明明是可以改变的啊        其实不然,str 仅仅是一个引用对象,它指向一个字符串对象“abc”。
第二行代码的含义是让 str 重新指向了一个新的字符串“bcd”对象,而“abc”对象并没有任何改变,只不过该对象已经成为一个不可及对象罢了。
2)StringBuffer/StringBuilder 表示的字符串对象可以直接进行修改。
3)StringBuilder 是 Java5 中引入的,它和 StringBuffer 的方法完全相同,区别在于它是在单线程环境下使用的,
因为它的所有方法都没有被 synchronized 修饰,因此它的效率理论上也比 StringBuffer 要高。

5. 什么情况下用“+”运算符进行字符串连接比调用 StringBuffer/StringBuilder    对象的 append 方法连接字符串性能更好?

字符串是 Java 程序中最常用的数据结构之一。
在 Java 中 String 类已经重载了"+"。
也就是说,字符串可以直接使用"+"进行连接,如下面代码所示:
1.String s = "abc" + "ddd"; 
但这样做真的好吗?当然,这个问题不能简单地回答 yes or no。
要根据具体情况来定。
在 Java 中提供了一个StringBuilder 类(这个类只在 J2SE5 及以上版本提供,以前的版本使用 StringBuffer 类),这个类也可以起到"+"的作用。

那么我们应该用哪个呢?

下面让我们先看看如下的代码:
1. package string;
2.
3. public class TestSimplePlus
4. {
5. public static void main(String[] args)
6. {
7. String s = "abc";
8. String ss = "ok" + s + "xyz" + 5;
9. System.out.println(ss);
10. }
11. }

上面的代码将会输出正确的结果。从表面上看,对字符串和整型使用"+"号并没有什么区别,但事实真的如此吗?

下面让我们来看看这段代码的本质。

我们首先使用反编译工具(如 jdk 带的 javap、或 jad)将 TestSimplePlus 反编译成 Java Byte Code,其中的奥秘就一目了然了。在本文将使用 jad 来反编译,命令如下:
jad -o -a -s d.java TestSimplePlus.class

反编译后的代码如下:


1. package string;
2.
3. import java.io.PrintStream;
4.
5. public class TestSimplePlus
6. {
7. public TestSimplePlus()
8. {
9. // 0 0:aload_0
10. // 1 1:invokespecial #8 <Method void Object()>
11. // 2 4:return
12. }
13.
14. public static void main(String args[])
15. {
16. String s = "abc";
17. // 0 0:ldc1 #16 <String "abc">
18. // 1 2:astore_1
19. String ss = (new StringBuilder("ok")).append(s).append("xyz").append(5).toString();
20. // 2 3:new #18 <Class StringBuilder>
21. // 3 6:dup
22. // 4 7:ldc1 #20 <String "ok">
23. // 5 9:invokespecial #22 <Method void StringBuilder(String)>
24. // 6 12:aload_1
25. // 7 13:invokevirtual #25 <Method StringBuilder StringBuilder.append(String)>
26. // 8 16:ldc1 #29 <String "xyz">
27. // 9 18:invokevirtual #25 <Method StringBuilder StringBuilder.append(String)>
28. // 10 21:iconst_5
29. // 11 22:invokevirtual #31 <Method StringBuilder StringBuilder.append(int)>
30. // 12 25:invokevirtual #34 <Method String StringBuilder.toString()>
31. // 13 28:astore_2
32. System.out.println(ss);
33. // 14 29:getstatic #38 <Field PrintStream System.out>
34. // 15 32:aload_2
35. // 16 33:invokevirtual #44 <Method void PrintStream.println(String)>
36. // 17 36:return
37. }
38. }
读者可能看到上面的 Java 字节码感到迷糊,不过大家不必担心。
本文的目的并不是讲解 Java Byte Code,因此,并不用了解具体的字节码的含义。
使用 jad 反编译的好处之一就是可以同时生成字节码和源代码。
这样可以进行对照研究。
从上面的代码很容易看出,虽然在源程序中使用了"+",但在编译时仍然将"+"转换成 StringBuilder。因此,我们可以得出结论, Java 无论使用何种方式进行字符串连接,实际上都使用的是 StringBuilder
那么是不是可以根据这个结论推出使用"+"和 StringBuilder 的效果是一样的呢?
这个要从两个方面的解释。
如果从运行结果来解释,那么"+"和 StringBuilder 是完全等效的。但如果从运行效率和资源消耗方面看,那它们将存在很大的区别。
当然,如果连接字符串行表达式很简单(如上面的顺序结构),那么"+"和 StringBuilder 基本是一样的,但如果结构比较复杂,如使用循环来连接字符串,那么产生的 Java Byte Code 就会有很大的区别。
先让我们看看如下的代码:
1. package string;
2.
3. import java.util.*;
4.
5. public class TestComplexPlus
6. {
7. public static void main(String[] args)
8. {
9. String s = "";
10. Random rand = new Random();
11. for (int i = 0; i < 10; i++)
12. {
13. s = s + rand.nextInt(1000) + " ";
14. }
15. System.out.println(s);
16. }
17. }
上面的代码返编译后的 Java Byte Code 如下:
1. package string;
2.
3. import java.io.PrintStream;
4. import java.util.Random;
5.
6. public class TestComplexPlus
7. {
8.
9. public TestComplexPlus()
10. {
11. // 0 0:aload_0
12. // 1 1:invokespecial #8 <Method void Object()>
13. // 2 4:return
14. }
15.
16. public static void main(String args[])
17. {
18. String s = "";
19. // 0 0:ldc1 #16 <String "">
20. // 1 2:astore_1
21. Random rand = new Random();
22. // 2 3:new #18 <Class Random>
23. // 3 6:dup
24. // 4 7:invokespecial #20 <Method void Random()>
25. // 5 10:astore_2
26. for(int i = 0; i < 10; i++)
27. //* 6 11:iconst_0
28. //* 7 12:istore_3
29. //* 8 13:goto 49
30. s = (new StringBuilder(String.valueOf(s))).append(rand.nextInt(1000)).append(" ").t
oString();
31. // 9 16:new #21 <Class StringBuilder>
32. // 10 19:dup
33. // 11 20:aload_1
34. // 12 21:invokestatic #23 <Method String String.valueOf(Object)>
35. // 13 24:invokespecial #29 <Method void StringBuilder(String)>
36. // 14 27:aload_2
37. // 15 28:sipush 1000
38. // 16 31:invokevirtual #32 <Method int Random.nextInt(int)>
39. // 17 34:invokevirtual #36 <Method StringBuilder StringBuilder.append(int)>
40. // 18 37:ldc1 #40 <String " ">
41. // 19 39:invokevirtual #42 <Method StringBuilder StringBuilder.append(String)>
42. // 20 42:invokevirtual #45 <Method String StringBuilder.toString()>
43. // 21 45:astore_1
44.
45. // 22 46:iinc 3 1
46. // 23 49:iload_3
47. // 24 50:bipush 10
48. // 25 52:icmplt 16
49. System.out.println(s);
50. // 26 55:getstatic #49 <Field PrintStream System.out>
51. // 27 58:aload_1
52. // 28 59:invokevirtual #55 <Method void PrintStream.println(String)>
53. // 29 62:return
54. }
55. }
大家可以看到,虽然编译器将"+"转换成了 StringBuilder,但创建 StringBuilder 对象的位置却在 for 语句内部。
这就意味着每执行一次循环,就会创建一个 StringBuilder 对象(对于本例来说,是创建了 10 个 StringBuilder对象),虽然 Java 有垃圾回收器,但这个回收器的工作时间是不定的。
如果不断产生这样的垃圾,那么仍然会占用大量的资源。解决这个问题的方法就是在程序中直接使用 StringBuilder 来连接字符串,代码如下:
1. package string;
2.
3. import java.util.*;
4.
5. public class TestStringBuilder
6. {
7. public static void main(String[] args)
8. {
9. String s = "";
10. Random rand = new Random();
11. StringBuilder result = new StringBuilder();
12. for (int i = 0; i < 10; i++)
13. {
14. result.append(rand.nextInt(1000));
15. result.append(" ");
16. }
17. System.out.println(result.toString());
18. }
19. }
上面代码反编译后的结果如下:
1. package string;
2.
3. import java.io.PrintStream;
4. import java.util.Random;
5.
6. public class TestStringBuilder
7. {
8.
9. public TestStringBuilder()
10. {
11. // 0 0:aload_0
12. // 1 1:invokespecial #8 <Method void Object()>
13. // 2 4:return
14. }
15.
16. public static void main(String args[])
17. {
18. String s = "";
19. // 0 0:ldc1 #16 <String "">
20. // 1 2:astore_1
21. Random rand = new Random();
22. // 2 3:new #18 <Class Random>
23. // 3 6:dup
24. // 4 7:invokespecial #20 <Method void Random()>
25. // 5 10:astore_2
26. StringBuilder result = new StringBuilder();
27. // 6 11:new #21 <Class StringBuilder>
28. // 7 14:dup
29. // 8 15:invokespecial #23 <Method void StringBuilder()>
30. // 9 18:astore_3
31. for(int i = 0; i < 10; i++)
32. //* 10 19:iconst_0
33. //* 11 20:istore 4
34. //* 12 22:goto 47
35. {
36. result.append(rand.nextInt(1000));
37. // 13 25:aload_3
38. // 14 26:aload_2
39. // 15 27:sipush 1000
40. // 16 30:invokevirtual #24 <Method int Random.nextInt(int)>
41. // 17 33:invokevirtual #28 <Method StringBuilder StringBuilder.append(int)>
42. // 18 36:pop
43. result.append(" ");
44. // 19 37:aload_3
45. // 20 38:ldc1 #32 <String " ">
46. // 21 40:invokevirtual #34 <Method StringBuilder StringBuilder.append(String)>
47. // 22 43:pop
48. }
49.
50. // 23 44:iinc 4 1
51. // 24 47:iload 4
52. // 25 49:bipush 10
53. // 26 51:icmplt 25
54. System.out.println(result.toString());
55. // 27 54:getstatic #37 <Field PrintStream System.out>
56. // 28 57:aload_3
57. // 29 58:invokevirtual #43 <Method String StringBuilder.toString()>
58. // 30 61:invokevirtual #47 <Method void PrintStream.println(String)>
59. // 31 64:return
60. }
61. }
从上面的反编译结果可以看出,创建 StringBuilder 的代码被放在了 for 语句外。
虽然这样处理在源程序中看起来复杂,但却换来了更高的效率,同时消耗的资源也更少了。

在使用 StringBuilder 时要注意,尽量不要"+"和 StringBuilder 混着用,否则会创建更多的 StringBuilder 对象,如下面代码所:

for (int i = 0; i < 10; i++)
{
result.append(rand.nextInt(1000));
result.append(" ");
}

改成如下形式:

for (int i = 0; i < 10; i++)
{
result.append(rand.nextInt(1000) + " ");
}

则反编译后的结果如下:

for(int i = 0; i < 10; i++)
//* 10 19:iconst_0
//* 11 20:istore 4
//* 12 22:goto 65
{
result.append((new StringBuilder(String.valueOf(rand.nextInt(1000)))).append(" ").toString());
// 13 25:aload_3
// 14 26:new #21 <Class StringBuilder>
// 15 29:dup
从上面的代码可以看出,Java 编译器将"+"编译成了 StringBuilder,这样 for 语句每循环一次,又创建了一个StringBuilder 对象。
如果将上面的代码在 JDK1.4 下编译,必须将 StringBuilder 改为 StringBuffer,而 JDK1.4 将"+"转换为 StringBuffer(因为 JDK1.4 并没有提供 StringBuilder 类)。

StringBuffer 和 StringBuilder 的功能基本一样,只是 StringBuffer 是线程安全的,而 StringBuilder 不是线程安全的。

因此,StringBuilder 的效率会更高。

6. 请说出下面程序的输出

1. class StringEqualTest {
2. public static void main(String[] args) {
3. String s1 = "Programming";
4. String s2 = new String("Programming");
5. String s3 = "Program";
6. String s4 = "ming";
7. String s5 = "Program" + "ming";
8. String s6 = s3 + s4;
9. System.out.println(s1 == s2); //false
10. System.out.println(s1 == s5); //true
11. System.out.println(s1 == s6); //false
12. System.out.println(s1 == s6.intern()); //true
13. System.out.println(s2 == s2.intern()); //false
14. }
15. }

补充:解答上面的需要知道如下两个知识点:

1. String 对象的 intern()方法会得到字符串对象在常量池中对应的版本的引用(如果常量池中有一个字符串与String 对象的 equals 结果是 true)
如果常量池中没有对应的字符串,则该字符串将被添加到常量池中,然后返回常量池中字符串的引用;
2. 字符串的+操作其本质是创建了 StringBuilder 对象进行 append 操作
然后将拼接后的 StringBuilder 对象用 toString 方法处理成 String 对象

这一点可以用 javap -c StringEqualTest.class 命令获得 class 文件对应的 JVM 字节码指令就可以看出来。

夜光:Java成神之路(四)擅长的语言相关推荐

  1. Java成神之路技术整理

    转载自 Java成神之路技术整理 以下是Java技术栈微信公众号发布的所有关于 Java 的技术干货,会从以下几个方面汇总,本文会长期更新. Java 基础篇 Java 集合篇 Java 多线程篇 J ...

  2. Java成神之路[转]

    阿里大牛珍藏架构资料,点击链接免费获取 针对本文,博主最近在写<成神之路系列文章> ,分章分节介绍所有知识点.欢迎关注. 主要版本 更新时间 备注 v1.0 2015-08-01 首次发布 ...

  3. Alibaba技术专家倾心五年打造 Java成神之路:基础篇

    近日里,很多人邀请我回答各种j2ee开发的初级问题,我无一都强调java初学者要先扎实自己的基础知识,那什么才是Java的基础知识?又怎么样才算掌握了java的基础知识呢?这个问题还真值得仔细思考. ...

  4. 夜光带你走进 Java 成神之路--Spring(四十六)擅长的领域

    夜光序言: 人生不要被过去所控制,决定你前行的,是未来; 人生不要被安逸所控制,决定你成功的,是奋斗; 人生不要被别人所控制,决定你命运的,是自己; 人生不要被金钱所控制,决定你幸福的,是知足; 人生 ...

  5. 夜光:Java成神之路(二)擅长的语言

    夜光序言: 命中注定的人,并不是注定与之相爱.结合.交配的人. 命中注定的人,是为了令你成为你注定成为的样子而出现的人. 正文:                                     ...

  6. 夜光:Java成神之路(九)擅长的语言

    夜光序言: 学会去看透一切的谜题. Learning to see the puzzle in everything. 它们无处不在. They're everywhere. 一旦你开始寻找,就不可能 ...

  7. Java成神之路技术整理,本文长期更新!

    原文地址:https://mp.weixin.qq.com/s/N507Cfb_mbkGvHtg_FIaVg(来源:java技术栈微信公众号) 以下是Java技术栈微信公众号发布的所有关于 Java ...

  8. 【学海无涯】Java成神之路

    基础篇 面向对象 面向对象与面向过程   面向过程就是按照程序进行的顺序依次编写索要完成相应任务的方法,依次调用.面型对象注重对逻辑概念的封装,将若干变量和方法封装成类,各个对象互相调用.面向对象占用 ...

  9. Java成神之路——ASM,Javassist,cglib区别。

    class文件简介及加载 Java编译器编译好Java文件之后,产生.class 文件在磁盘中.这种class文件是二进制文件,内容是只有JVM虚拟机能够识别的机器码.JVM虚拟机读取字节码文件,取出 ...

最新文章

  1. 如何解读「量子计算应对大数据挑战:中国科大首次实现量子机器学习算法」?——是KNN算法吗?...
  2. python实用小方法
  3. 深度解密Go语言之反射
  4. 十三、Tomcat的WebSocket支持
  5. 计算机图形学方向投稿国外期刊
  6. Intellij IDEA 配置
  7. angular学习笔记(六)-非入侵式javascript
  8. 如何打开计算机的Oracle服务,win10系统手动启动oracle服务的操作方法
  9. 计算机技术比武优秀获奖感言,技能比赛获奖感言范文
  10. putty linux上安装及使用
  11. 徐直军、何小鹏等大咖加盟,2021互联网岳麓峰会即将重磅开幕
  12. 智能血糖仪方案/案列/APP/小程序/项目
  13. IE浏览器版本测试方法
  14. 使用Python做接口测试
  15. 随机算法 之随机数的产生
  16. 怎么制作升温曲线图_炉温曲线图是怎么看的啊!
  17. 晨风机器人插件编辑器_晨风机器人文本编辑器
  18. windows +linux(ubuntu) 2020.7 双系统最新安装心得
  19. 春节荐书 | 2019年我读过的十本好书
  20. Spring Cloud Task 主要是干什么的啊?跟 Quartz 和 Spring Task 有啥关系?

热门文章

  1. 常用硬盘数据恢复软件的功能解析
  2. Linux 安装subversion+mod_dav_svn,搭建subversion(svn)服务器
  3. vue+relation-graphs快速实现组织机构图谱、股权架构图谱、集团关系图谱等知识图谱,树形、力学等关系图
  4. Linux下Apache Web服务器的安装与配置
  5. 御龙在天经典服登录服务器未响应,《御龙在天经典版》登录升级wegame公告
  6. ipad pro 11寸四周黑边,屏幕适配解决
  7. 解决”dllhost进程消耗cpu 100%的问题
  8. Ubuntu20.04安装Pytorch:Anaconda3+Pycharm+Pytorch+CUDA
  9. js 实现音乐播放器中歌词与歌曲同步的原理
  10. Integer类超详解