修改 JVM 输出数组
2016-03-14 21:00
363 查看
我的网站
前言
Java 比较常见的局限性中,输出数组可以算是其中一个。如果关于如何输出一个数组的回答得到了 1000 以上的赞,那么你就应该好好考虑是否还有一种更简单的方法。在其他的语言中都有简单的方式输出数组,而 Java 为什么没有呢?
不像 JDK 类库中的其他类,数组并没有继承 Object 的 toString() 方法。
输出的类型和地址对吗?
实际上 Java 并没有输出地址,取而代之的是一种比较神秘的输出形势,输出包含了类型的内部表示以及实例的 hashCode() 值。由于所有的数组都是一个对象,因此都会有一个 hashCode()、自己的类型、一个同步锁以及其他 Object 所带的属性和方法,但是没有一个是为数组专门设计的方法。这就是为什么 toString() 对于数组来说还无意义。
数组的输出是怎样的?
输出结果:
这些输出值对于每一位都是熟悉的。J 是 long 内部代码, L 是 Java 类的内部代码,Z 是布尔类型的内部代码。
在上边的程序中我们最终写了一个特殊的 toString 方法来打印 Map.Entry。在整个程序中多次的调用,这种方式在 Java 中相对来说是更简单些,他它们不好调试。
通过更改 JVM ?
我们需要做的就是更改 Object.toString(),这个类是我们唯一能够访问到的数组的父类,数组本身是定义到 JVM 内部的,无法直接接触到相关代码。即没有类似 byte[] 这样的类来定义 byte[] 可访问的方法。
拷贝一份 java.lang.Object 的源码,然后替换掉 toString() :
在 Java <= 8 的版本中我们可以添加下边的命令行,把这个类添加到 bootclasspath 开始的地方
-Xbootclasspath/p:target/classes
运行程序我们得到以下的结果
就像在其他语言里边看到的结果一样。
翻译原文
前言
Java 比较常见的局限性中,输出数组可以算是其中一个。如果关于如何输出一个数组的回答得到了 1000 以上的赞,那么你就应该好好考虑是否还有一种更简单的方法。在其他的语言中都有简单的方式输出数组,而 Java 为什么没有呢?
不像 JDK 类库中的其他类,数组并没有继承 Object 的 toString() 方法。
输出的类型和地址对吗?
实际上 Java 并没有输出地址,取而代之的是一种比较神秘的输出形势,输出包含了类型的内部表示以及实例的 hashCode() 值。由于所有的数组都是一个对象,因此都会有一个 hashCode()、自己的类型、一个同步锁以及其他 Object 所带的属性和方法,但是没有一个是为数组专门设计的方法。这就是为什么 toString() 对于数组来说还无意义。
数组的输出是怎样的?
public class ObjectTest { boolean[] booleans = {true, false}; byte[] bytes = {1, 2, 3}; char[] chars = "Hello World".toCharArray(); short[] shorts = {111, 222, 333}; float[] floats = {1.0f, 2.2f, 3.33f, 44.44f, 55.555f, 666.666f}; int[] ints = {1, 22, 333, 4_444, 55_555, 666_666}; double[] doubles = {Math.PI, Math.E}; long[] longs = {System.currentTimeMillis(), System.nanoTime()}; String[] words = "The quick brown fox jumps over the lazy dog".split(" "); @Test public void testToString() throws IllegalAccessException { Map<String, Object> arrays = new LinkedHashMap<>(); for(Field f : getClass().getDeclaredFields()) arrays.put(f.getName(), f.get(this)); arrays.entrySet().forEach(System.out::println); } }
输出结果:
booleans=[Z@277c0f21 bytes=[B@6073f712 chars=[C@43556938 shorts=[S@3d04a311 floats=[F@7a46a697 ints=[I@5f205aa doubles=[D@6d86b085 longs=[J@75828a0f words=[Ljava.lang.String;@3abfe836
这些输出值对于每一位都是熟悉的。J 是 long 内部代码, L 是 Java 类的内部代码,Z 是布尔类型的内部代码。
在上边的程序中我们最终写了一个特殊的 toString 方法来打印 Map.Entry。在整个程序中多次的调用,这种方式在 Java 中相对来说是更简单些,他它们不好调试。
通过更改 JVM ?
我们需要做的就是更改 Object.toString(),这个类是我们唯一能够访问到的数组的父类,数组本身是定义到 JVM 内部的,无法直接接触到相关代码。即没有类似 byte[] 这样的类来定义 byte[] 可访问的方法。
拷贝一份 java.lang.Object 的源码,然后替换掉 toString() :
public String toString() { if (this instanceof boolean[]) return Arrays.toString((boolean[]) this); if (this instanceof byte[]) return Arrays.toString((byte[]) this); if (this instanceof short[]) return Arrays.toString((short[]) this); if (this instanceof char[]) return Arrays.toString((char[]) this); if (this instanceof int[]) return Arrays.toString((int[]) this); if (this instanceof long[]) return Arrays.toString((long[]) this); if (this instanceof float[]) return Arrays.toString((float[]) this); if (this instanceof double[]) return Arrays.toString((double[]) this); if (this instanceof Object[]) return Arrays.deepToString((Object[]) this); return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
在 Java <= 8 的版本中我们可以添加下边的命令行,把这个类添加到 bootclasspath 开始的地方
-Xbootclasspath/p:target/classes
运行程序我们得到以下的结果
booleans=[true, false] bytes=[1, 2, 3] chars=[H, e, l, l, o, , W, o, r, l, d] shorts=[111, 222, 333] floats=[1.0, 2.2, 3.33, 44.44, 55.555, 666.666] ints=[1, 22, 333, 4444, 55555, 666666] doubles=[3.141592653589793, 2.718281828459045] longs=[1457629893500, 1707696453284240] words=[The, quick, brown, fox, jumps, over, the, lazy, dog]
就像在其他语言里边看到的结果一样。
翻译原文
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序