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

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

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

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

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被缓存起来了

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

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一个对象了,它的代码如下:

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。

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

public static void main(String[] args){
// \\u000d System.out.println("Hello World!");
}

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

为什么呢?

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

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

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

int[] arr;

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

int arr[];

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

int[] arr[];

它其实等价于:

int[][] arr;

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

int[] arr, arr2[];

它等价于:

int[] arr;
int[][] arr2;

当然,不建议使用这样的方式。

类似的定义方式也可以用在方法的返回值上面,比如

int[] fuction()[];

就等价于:

int[][] fuction();

5. new String("xyz")创建了两个对象

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

String str = new String("xyz");

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

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

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

String str = "xyz";

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

6. JVM指令重排序

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

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

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代码,竟然绝大部分是没有价值的,着实让人感觉不到温暖了。不过,他们站的角度可能不同,分析的维度可能也有分别,就当是茶余饭后的一个谈资吧,不用太往心里去。

Java语言中的这些知识点有没有用过,工作中有没有入过这些坑?的更多相关文章

  1. JAVA语言中的修饰符

    JAVA语言中的修饰符 -----------------------------------------------01--------------------------------------- ...

  2. Java语言中的面向对象特性总结

    Java语言中的面向对象特性 (总结得不错) [课前思考]  1. 什么是对象?什么是类?什么是包?什么是接口?什么是内部类?  2. 面向对象编程的特性有哪三个?它们各自又有哪些特性?  3. 你知 ...

  3. JAVA语言中冒号的用法

    近来由于本人要介入android平台的开发,所以就买了本JAVA语言的书学习.学习一段时间来,我的感觉是谭浩强就是厉害,编写的<C编程语言>系列丛书不愧是经典.书中对C语言的介绍既系统又全 ...

  4. Java语言中的面向对象特性:封装、继承、多态,面向对象的基本思想(总结得不错)

    Java语言中的面向对象特性(总结得不错) [课前思考] 1. 什么是对象?什么是类?什么是包?什么是接口?什么是内部类? 2. 面向对象编程的特性有哪三个?它们各自又有哪些特性? 3. 你知道jav ...

  5. Java语言中的异常处理

    Java语言中的异常处理包括声明异常.抛出异常.捕获异常和处理异常四个环节.   throw用于抛出异常.   throws关键字可以在方法上声明该方法要抛出的异常,然后在方法内部通过throw抛出异 ...

  6. 列举java语言中反射的常用方法

    package review;/*12:43 2019/7/21*/ import model.AnotherClass; import model.OneClassMore; import mode ...

  7. Java语言中的正则表达式

    正则表达式是什么? 正则表达式是一种强大而灵活的文本处理工具.初学正则表达式时,其语法是一个难点,但它确实是一种简洁.动态的语言.正则表达式提供了一种完全通用的方式,能够解决各种字符串处理相关的问题: ...

  8. Java语言中使用OpenMP

    从去年年中,开始学习Java,主要是维护公司用Java编写的服务器软件.目前,该服务器软件遇到一个问题,在下载大文件时,如果同时下载的用户很多, 服务器软件工作会出现异常,有的用户无法下载.服务器硬件 ...

  9. Java语言中的访问权限修饰符

    一个Java应用有很多类,但是有些类,并不希望被其他类使用.每个类中都有数据成员和方法成员,但是并不是每个数据和方法,都允许在其他类中调用.如何能做到访问控制呢?就需要使用访问权限修饰符. Java语 ...

随机推荐

  1. PHP 通用格式化调试函数

    /** * 打印调试函数 * @param $content * @param $is_die */function pre($content, $is_die = true){ header('Co ...

  2. jenkins 下使用ansible 跨服务器控制操作

    例如: A服务器地址:172.16.1.203 B服务器地址:172.16.1.204 当jenkins 在A 服务器并且用户aa,  控制B 服务器的用户bb的操作 (1)B服务器 用ssh-key ...

  3. K8s Scheduler 在调度 pod 过程中遗漏部分节点的问题排查

    问题现象 在TKE控制台上新建版本为v1.18.4(详细版本号 < v1.18.4-tke.5)的独立集群,其中,集群的节点信息如下: 有3个master node和1个worker node, ...

  4. 缓冲流以及JAVA路径相关问题

    缓冲流 缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO 次数,从而提高读写的效率. 字节缓冲流 按字节处理 字符缓冲流 按字符处理 实例练习:文 ...

  5. Spring核心结构及核心思想

    Spring核心结构 基本概念 Spring是⼀个分层⾮常清晰并且依赖关系.职责定位⾮常明确的轻量级框架,主要包括⼏个⼤模块:数据处理模块.Web模块.AOP(Aspect Oriented Prog ...

  6. Spring Cloud Alibaba(10)---Sentinel控制台搭建+整合SpringCloudAlibaba

    上一篇博客讲了Sentinel一些概念性的东西 Spring Cloud Alibaba(9)---Sentinel概述 这篇博客主要讲 Sentinel控制台搭建,和 整合SpringCloudAl ...

  7. Jmeter(四十四) - 从入门到精通高级篇 - Jmeter远程启动(本地运行+远程运行)(详解教程)

    1.简介 这篇文章其实很简单,就是为下一篇文章做一个铺垫,所以宏哥给小伙伴或童鞋们提前热身一下. 2.什么是远程运行? 远程执行,就是脚本放在本地,执行却在另一台电脑上执行,当然,可以是远程多台电脑一 ...

  8. Python批量图片去水印,提高工作效率

    ​平常工作中,有时为了采用网络的一些素材,但这些素材往往被打了水印,如果我们不懂PS就无法去掉水印,或者无法批量去掉水印.这些就很影响我们的工作效率. 今天我们就一起来,用Python + OpenC ...

  9. [Java] 数据分析 -- 回归分析

    线性回归 需求:从文件读取数据对,计算回归函数及系数 实现1:commons.math的SimpleRegression,定义函数getData从文件读取数据返回SimpleRegression类 1 ...

  10. [刷题] 19 Remove Nth Node From End of List

    要求 给定一个链表,删除倒数第n个节点 示例 1->2->3->4->5->NULL , n=2 1->2->3->5 边界 n是从0还是从1计 n不合 ...