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 却刚好是一致的。