前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java语言中的生僻知识

Java语言中的生僻知识

作者头像
帅地
发布2019-06-06 14:49:34
3850
发布2019-06-06 14:49:34
举报
文章被收录于专栏:苦逼的码农苦逼的码农

本文来自微友的投稿。 来源:互联网全栈架构 作者:践行精神自由

最近有一首名叫《生僻字》的流行歌曲火遍大江南北,创作者给佶屈聱牙的生僻字,配上了优美明快的旋律,竟然让歌曲变得琅琅上口、悦耳动听起来,平时不太常见的拒人于千里之外的这些汉字也不再那么陌生,人们带着一种猎奇和挑战的心理,在街头巷尾争相传唱。

同样,在Java语言中,也有一些相对生僻的知识,平时用的机会可能不是很多,但如果不了解不掌握这些知识点的话,也可能会掉入陷阱之中,今天我们就来初步梳理一下:

1. goto是java语言中的关键字。

“臭名昭著”、“十恶不赦”的goto竟然是java中的关键字!没错,参看下图中的关键字列表,goto赫然在列:

虽然goto是java中的关键字,但它没有在java中使用,如果我们需要类似跳转的功能,可以使用break关键字,比如,如果要求在满足某种条件时跳出整个两重循环,可以用如下的代码来实现:

代码语言:javascript
复制
label:
for(int i=0;i<10;i++){
    for(int j=0;j<10;j++){
        System.out.println("%i"+i+",j"+j);
        if(i>j)
            break label;
    }
}
2. Integer中,-128至127被缓存起来了

我们先来看看下面这段代码:

代码语言:javascript
复制
public static void main(String[] args){
    Integer a = 100;
    Integer b = 100;
    Integer c = 200;
    Integer d = 200;
    System.out.println(a==b);
    System.out.println(c==d);
}

乍一看,我们可能会认为,输出的结果要么都是true,要么都是false,但实际的情况却让人大跌眼镜,正确的结果是true和false。

这是为什么呢?原来Integer中有一个静态内部类IntegerCache,在类加载的时候,它会把[-128, 127]之间的值缓存起来,而Integer a = 100这样的赋值方式,会首先调用Integer类中的静态valueOf方法,这个方法会尝试从缓存里取值,如果在这个范围之类就不用重新new一个对象了,它的代码如下:

代码语言:javascript
复制
public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

所以上面的代码就产生了这样奇怪的输出。

3. java注释也能识别unicode。

再看看这段代码,应该输出什么呢?

代码语言:javascript
复制
public static void main(String[] args){
    // \u000d System.out.println("Hello World!");
}

如果你认为,注释后面的代码,当然不会执行,所以上面的代码什么都不会输出,那你就错了,结果恰恰相反,这段代码就像打不死的小强,连注释也不能阻挡它的绽放,最后还是输出了我们最熟悉不过的“Hello World!”

为什么呢?

原来,unicode解码发生在代码编译之前,编译器将\u样式的代码进行文本转义,即使是注释也是这样,然后\u000a被转换成\n换行符,所以println代码得以正常执行。

4. 数组的定义方式灵活多变

定义一个数组,我们经常用如下的方式:

代码语言:javascript
复制
int[] arr;

可能是为了照顾从C语言转到Java的程序员,下面的方式也是没问题的:

代码语言:javascript
复制
int arr[];

大部分程序员会选择第一种方式,毕竟它把数据类型和变量名称分隔得非常清晰。但即使采用第二种方式,理解起来也问题不大,下面这种方式就有点奇怪了:

代码语言:javascript
复制
int[] arr[];

它其实等价于:

代码语言:javascript
复制
int[][] arr;

甚至还有一种更容易让人混淆的方式。还记得变量定义的一种特殊形式吗?就是在一行上定义多个同类型的变量,这个规则对于数组也是适用的,看看下面:

代码语言:javascript
复制
int[] arr, arr2[];

它等价于:

代码语言:javascript
复制
int[] arr;
int[][] arr2;

当然,不建议使用这样的方式。 类似的定义方式也可以用在方法的返回值上面,比如

代码语言:javascript
复制
int[] fuction()[];

就等价于:

代码语言:javascript
复制
int[][] fuction();
5. new String("xyz")创建了两个对象

下面的语句创建了几个对象:

代码语言:javascript
复制
String str = new String("xyz");

这是面试时经常会问起的一个问题。跟其他普通的对象不一样,上面的代码创建了两个对象,一个存放在堆中,一个存放在字符串常量池中。

当然,需要我们注意的是,如果之前常量池中已经存在"xyz"这个字符串,那么,上面的语句就只会在堆中创建一个对象了。

另外,定义一个字符串的时候,我们还可以采用下列的方式:

代码语言:javascript
复制
String str = "xyz";

这样,就只会创建一个存放在字符串常量池中的对象(如果池中不存在这个字符串的话)。

6. JVM指令重排序

在java代码中有先后顺序的代码,在经过编译器处理后,可能会对这些指令进行重排序,噢,听起来有点匪夷所思。

来看一段代码(来自于《Java并发编程实践》):

代码语言:javascript
复制
public class PossibleReordering {
    static int x = 0, y = 0;
    static int a = 0, b = 0;

    public static void main(String[] args) throws InterruptedException {
        Thread one = new Thread(new Runnable() {
            public void run() {
                a = 1;
                x = b;
            }
        });

        Thread other = new Thread(new Runnable() {
            public void run() {
                b = 1;
                y = a;
            }
        });
        one.start();
        other.start();
        one.join();
        other.join();
        System.out.println("(" + x + "," + y + ")");
    }
}

由于线程执行的顺序可能会有先后交叉的情况,所以上面的代码可能会输出(1,0),(0,1),(1,1),这不难理解,然而,它竟然也有可能输出(0,0):

从上图可以看出,编译后的顺序跟代码的顺序不一样了,这看起来确实有些奇怪,背后的原因是,出于性能的考虑,JIT会对没有数据依赖的指令进行重排,所以才会发生上面的情况。

可以学习Java内存模型(JMM),以及as-if-serial语义和happens-before等更多的知识来加深对指令重排的理解。

7. 95%的java代码毫无价值

最后,来一个比较轻松一点(或许是沉重?)的冷知识。据一条网络消息,加州大学戴维斯分校、中国东南大学和伦敦大学学院的研究人员发表了一篇研究报告(PDF),他们分析了1亿行Java项目代码,发现超过95%的代码是没什么价值的。

怎么样,没想到吧,是不是很冷?冷得让人都打了个寒颤,日日夜夜攻坚,精心编写的java代码,竟然绝大部分是没有价值的,着实让人感觉不到温暖了。不过,他们站的角度可能不同,分析的维度可能也有分别,就当是茶余饭后的一个谈资吧,不用太往心里去。

8. 结语

当然,上面提到的这些冷知识,对于基础知识扎实,工作经验丰富的人来讲,一点都不冷,在实际工作中也是运用自如,手到擒来。就像歌曲《生僻字》中的歌词:”茕茕孑立,沆瀣一气,踽踽独行,醍醐灌顶……”,对普通人来说可能会有一些难度,但对于饱读经书、学富五车的学者,就像我们看到“一针见血、春色满园、争先恐后、兴高采烈”这样的成语一样地简单。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 帅地玩编程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. goto是java语言中的关键字。
  • 2. Integer中,-128至127被缓存起来了
  • 3. java注释也能识别unicode。
  • 4. 数组的定义方式灵活多变
  • 5. new String("xyz")创建了两个对象
  • 6. JVM指令重排序
  • 7. 95%的java代码毫无价值
  • 8. 结语
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档