Java 中的 System 类是一个 final 类, 构造方法是 private 权限的, 因此不能够被外部类实例化(不考虑反射等手段)。

System 类对外提供的是一些类方法、类属性的访问, 常用的有:

 

1> System.out

标准输出流, 一般在测试和调试等情况下用的比较多, System.out 返回的是一个 PrintStream 对象, PrintStream 类里面对 print、println 方法

进行了多次的重载, 来使得它们可以接受任何类型的参数, 用于将参数信息打印输出到控制台。

 

2> System.in

标准输入流, 经常结合 java.util.Scanner 来使用:

1 public void scan(int[] param, int i){
2     Scanner scanner = new Scanner(System.in);
3     while(scanner.hasNextInt()){
4         //can check the array bound in here
5         param[i++] = scanner.nextInt();
6     }
7     scanner.close();
8 }

 

3> System.currentTimeMillis() 返回以毫秒为单位的当前时间。

 

4> arraycopy(Object src, int srcPos, Object dest, int destPos, int length)

快速拷贝数组。src 为原数组, srcPos 为原数组的起始拷贝下标, dest 为目标数组, destPos 为目标数组的起始填充下标, length 为总共要拷贝的长度:

1 public void app(){
2     int[] src = {0, 1, 3, 5, 7, 9};
3     int[] target = new int[4];
4     System.arraycopy(src, 1, target, 0, target.length);
5     for(int i = 0; i < target.length; i++){
6         System.out.print(target[i] + "\t");  // 1  3  5  7
7     }
8 }

 

System.arraycopy 是一个 native 方法, 底层不是用 java 类实现的, 接着贴一个自己写的简陋的拷贝数组的方法:

1 public void arrayCopy(int[] src, int srcPos, int[] dest, int destPos, int length){
2     for(int i = 0; i < length; i++){
3         dest[destPos++] = src[srcPos++];
4     }
5 }

 

本人在自己的笔记本电脑上做了一个不可靠的小测试, 分别调自己写的 arrayCopy 方法和 System.arraycopy 方法, 拷贝一个含有 1000000 个元素的数组,

arrayCopy() 方法平均耗时 10ms, 而 System.arraycopy 方法耗时 0ms。并且随着数组元素的增大, System.arraycopy 方法的优势也越加明显。

 

System.arraycopy 拷贝对象:

1 public void app(){
 2     
 3     StringBuilder builder0 = new StringBuilder("builder0");
 4     StringBuilder builder1 = new StringBuilder("builder1");
 5     StringBuilder builder2 = new StringBuilder("builder2");
 6     StringBuilder[] src = {builder0, builder1, builder2};
 7     StringBuilder[] target = new StringBuilder[2];
 8     
 9     System.arraycopy(src, 0, target, 0, target.length);
10 
11     System.out.println(src[0]);     // builder0
12     target[0].append(" + append");
13     System.out.println(src[0]);     // builder0 + append
14     System.out.println(builder0);   // builder0 + append
15     
16 }

上示代码中, 注释的内容是控制台执行输出的结果, 从输出结果来看, 当改变 target[0] 对象的内容的时候, src[0] 和 builder0 都受到了影响。

这是因为, 当拷贝的是对象的时候, 实际上并不是真的去拷贝对象本身, 而只是拷贝对象的引用, 如果使用打印语句输出 :

target[0] == builder0、target[0] == src[0] 会看到控制台打印输出的结果都为 true。

因此使用 src[0]、target[0]、builder0 中的任何一个来操作对象, 最终所达到的效果是等效的。这点是在拷贝对象的时候需要注意的。

 

5> identityHashCode(Object x)

该方法返回的是与默认的 hashCode() 方法返回的哈希码值是一样, 而不管参数对象的类是否重写了 hashCode() 方法。如果 x 为 null 则返回 0。

1 public void app(){
 2     
 3     String str = "min-snail";
 4     System.out.println(str.hashCode());                // -893502002
 5     System.out.println(System.identityHashCode(str));  // 1569228633
 6     
 7     StringBuilder builder = new StringBuilder("min-snail");
 8     System.out.println(builder.hashCode());               // 778966024
 9     System.out.println(System.identityHashCode(builder)); // 778966024
10     
11 }

从输出的结果来看, str 的 hashCode 值与 identityHashCode 的值不一致, 而 builder 的却一致。

原因是, identityHashCode(x) 方法返回的是值与 Object 类的 hashCode() 返回值总是一致的, 与 x 类是否重写了 Object 的 hashCode() 方法无关。

因为 String 类重写了 Object 类的 hashCode() 方法, 而 StringBuilder 类没有重写 Object 的 hashCode() 方法,

因此, str 的 hashCode 值与 identityHashCode 的值是不一致的, 而 builder 却刚好是一致的。