转载

Java冷知识(一)

1.每个Java程序都必须有main方法吗?比如web容器应用

答案:是。即使是web容器也有main方法,比如tomcat的Bootstrap类的main方法。

2.java有无符号(Unsigned)类型吗?

答案:没有。

3.NaN相等问题

double d1 = Double.NaN;
double d3 = d1;
System.out.println("d3 == d1 : " + (d3 == d1));

上面的代码输出true还是false?

答案:false。

double d1 = Double.NaN;
double d2 = Double.NaN;
System.out.println("d1 == d2 : " + (d1 == d2));
System.out.println("Double.NaN == Double.NaN : " + (Double.NaN == Double.NaN));

上面的代码输出true还是false?

答案:false。

总结,java中所有的非数值都是不相等的。

4.如何判断一个数是否是NaN?

答案:使用Double.isNaN(double)或Float.isNaN(float)。其实现是一个数不等于自己,就是NAN:

public static boolean isNaN(double v) {
    return (v != v);
}

5.Java中一个汉字占用几个字符?

答案:两个或四个。在java中char类型用UTF-16描述一个代码单元。常用汉字用一个代码单元表示。有些汉字用两个代码单元表示。一个代码单元code point包含16bit。

6.java8里char类型占有几个字节?使用什么字符集,使用什么编码?可以保存所有汉字吗?

char占用2个字节,使用Unicode字符集,使用UTF-16编码。有些汉字是存储不了的。

7.java8里的String底层是用char[]存储的,那么String是如何存储char放不下的字符的?

其实是Unicode的设计保证的。为了将一个WORD的UTF-16编码与两个WORD的UTF-16编码区分开来,Unicode编码的设计者将0xD800-0xDFFF保留下来,并称为代理区(Surrogate)。

  • D800-DB7F High Surrogates 高位替代
  • DB80-DBFF

High Private Use Surrogates

高位专用替代

  • DC00-DFFF

Low Surrogates

低位替代

8.你知道Unocide代码单元(code unit )和代码点(code point)的区别吗?或者已知" "占用四个字节,你知道下面的代码输出是什么吗?

String s2 = "  ";
System.out.println(s2.getBytes().length);
System.out.println(s2.codePoints().count());
System.out.println(s.length());
System.out.println(s.codePointCount(0, s.length()));

答案:4 、1、 2、1。第一个代表占用多少字节。第二个代表Unicode代码点个数,也就是字符个数。第三个代表需要几个Unicode code units,相当于需要几个char来存储。第四个也代表字符个数。

9.请问下面的变量名合法吗?

int ⅦⅢ齉__8s好;
int αβ;
int IIasdf;
int $as;
int _sdf;
int 9sdf;

答案:除了最后一个不合法,其他都合法。也就是说下划线、美元符、汉字或其他语言中的字母都可以用来命名变量,并且可以作为开头。阿拉伯数字不可以作为开头。

可以使用下面两个方法来检测字符是否可以用来组成变量名或者作为变量名开头。

Character.isJavaIdentifierPart('齉');
Character.isJavaIdentifierStart('9');

10.strictfp关键字的作用

java希望所有的运算在不同的机器上运行结果应该是一样的,即保证可移植性。例如double w = x y / z; 很多Intel的处理器会把x y 的结果保存在80位寄存器中,再除以z,然后把结果截断为64位。这样可以得到一个更精确的结果,而且避免产生溢出。这样的话就与使用64位寄存器的计算结果不一致。JVM最初规定,所有中间结果都需要截断,但是遭到数值计算团体的反对。因为截断不仅浪费时间,而且可能导致溢出。最终JVM的设计者,允许中间结果采用扩展的精度。但是对于strictfp关键字标记的方法,必须使用严格的浮点计算,也就是所有中间值都进行截断。

11.java中有带符号左位移(<<<)运算符吗?

答案:没有。只有>>> >> <<。

12.下面两组代码的区别是什么?

boolean cond1 = somemethod1();
boolean cond2 = somemethod2()
// 第一组
if(cond1 && cond2){
    ...
}
// 第二组
if(cond1 & cond2){
    ...
}

答案:第一组有阻断功能;第二组没有阻断功能。

13.Math类与StrictMath类的区别?

答案:Math类中有些方法并不是严格的浮点计算,但是效率较高。StrictMath中都是严格的浮点计算。“严格”的含义,参考上文中 ++strictfp关键字的作用++ 。

14.byte类型+short类型,得到的是什么类型?

下面的代码有问题吗?

byte b = 1;
short s = b;
short s1 = s + b;

答案:byte类型+short类型,得到的是int类型。所以第三行代码报错。但是可以自动将byte转换成short,所以第二行代码是可以的。

15.请问下面s1和s2的字符串会保存在字符串池中吗?

String s1 = "asd" + "qwe";

String s2 = s1.substring(1);

答案:不会。因为只有字符串常量才会放到字符串池中,而+或substring等操作产生的结果并不会放到字符串池。

16.字符串池里的字符串再不使用时,是否会GC回收?其底层存储是什么?

  • 在jdk7以前,string pool 在Perm Gen空间,且不能被GC回收,只能调大Perm Gen大小。
  • 在jdk7中,移到了堆中,并且没有被引用的字符串会被gc掉,减少了内存泄漏的风险。字符串池是用类似HashMap的结构实现的。
  • 直到java8,string类型底层还是使用char数组进行存储,编码使用utf-16,以便于每个字符可以在内存里面使用2个byte。
  • 在java9里面提出来compact string的理念,并在一些情况下可以采用byte数组直接存储字符串,从而节约内存的使用,具体什么时候用char数组什么时候用byte数组,依赖于你存储的内容。

17.goto标签是否可以用于if语句或者块语句?

public class Goto_Demo {

    public static void main(String[] args) {

        inIfBlock(true);
        System.out.println("----------分隔符----");
        inBlock(true);
    }

    private static void inIfBlock(boolean bool){

        结束:
        if(bool){

            System.out.println("in ");
            if(bool){
                break 结束;
            }
            System.out.println("after ");
        } 

        System.out.println("out ");
    }

    private static void inBlock(boolean bool){

        结束:
        {
            System.out.println("in ");
            if(bool){
                break 结束;
            }
            System.out.println("after ");
        }

        System.out.println("out ");
    }
}

以上代码哪个方法可以输出“after”?

答案:goto标签可以用于if语句或块语句。上面代码都不会输出“after”。

18.数组的初始化时长度是否需要给定?长度可以是变量吗?长度是否可以为0?

答案:数组初始化时,“最外围的”数组长度必须给定(比如二维数组的最外围就是行)。长度可以是变量。长度可以为0。注意数组长度为0与null是不同的概念。

int[] arr = new int[2];
int[][] arr2 = new int[2][];
int[] arr3 = new int[0];

19.Arrays的binarySearch(type[] a, type v)的返回值r代表什么含义?

答案:如果返回值 r>=0,表示找到相应元素,返回的是数组下标值。如果返回值 r<0,则(-r-1)就是插入v元素时,为保持数组a有序,应该插入的位置。

20.Java支持不规则数组吗?比如下面代码报错吗?

int[][] arr = {{1, 2, 3}, {4, 5}}

答案:支持,不报错。因为Java实际上是没有多维数组,只有一维数组。多维数组被解释成数组的数组。比如,二维数组的每一行是一个一维数组的引用,我们可以实现行的互换。

21.使用Thread和Math类需要import吗?

不用,凡是在java.lang包下的java预定义类,在使用时都不需要import!

Java语言中的java.lang包是由编译器直接自动导入的,因此,编程时使用该包中的类,可省去 import导入。使用其他包中的类,必须用import导入

原文  https://segmentfault.com/a/1190000021101318
正文到此结束
Loading...