源码浅谈(一):java中的 toString()方法
前言:
toString()方法 相信大家都用到过,一般用于以字符串的形式返回对象的相关数据。
最近项目中需要对一个ArrayList<ArrayList<Integer>> datas 形式的集合处理。
处理要求把集合数据转换成字符串形式,格式为 :子集合1数据+"#"+子集合2数据+"#"+....+子集合n数据。
举例: 集合数据 :[[1,2,3],[2,3,5]] 要求转成为 "[1,2,3]#[2,3,5]" 形式的字符串
第一次是这样处理的:
ArrayList<ArrayList<Object>> a = new ArrayList<>(); // 打造这样一个数据的集合 [[1,2],[2,3]] 要求 生成字符串 [1,2]#[2,3]
for (int i = ; i < ; i++) {
ArrayList<Object> c = new ArrayList<>();
c.add(i+);
c.add(i+);
a.add(c);
//打印单个子集合的字符串形式数据
Log.i("myinfo",c.toString());
}
StringBuilder builder = new StringBuilder();
builder.append(a.get().toString()+"#"+a.get().toString());
//打印该集合的字符串形式数据
Log.i("myinfo",builder.toString());
然后看该处理下的Log日志:
- ::18.485 -/com.xxx.aaa I/myinfo: [, ]
- ::18.485 -/com.xxx.aaa I/myinfo: [, ]
- ::18.495 -/com.xxx.aaa I/myinfo: [, ]#[, ]
我们会发现我们想要的是[1,2]#[2,3]形式的字符串,但是结果是[1, 2]#[2, 3] ,在第二个值开始往后,前面都多了一个空格。
接下来我们查看 集合下的.toString()方法的源码:
翻译一下官方解释:
1、返回这个Collection类(Set和List的父类) 的字符串表现形式
2、这个表现形式有一个规定的格式,被矩形括号"[]"包含
3、里面的子元素被“, ”(逗号和空格)分割 (这是重点)
/**
* Returns the string representation of this {@code Collection}. The presentation
* has a specific format. It is enclosed by square brackets ("[]"). Elements
* are separated by ', ' (comma and space).
*
* @return the string representation of this {@code Collection}.
*/
@Override
public String toString() {
if (isEmpty()) {
return "[]";
} StringBuilder buffer = new StringBuilder(size() * );
buffer.append('[');
Iterator<?> it = iterator();
while (it.hasNext()) {
Object next = it.next();
if (next != this) {
buffer.append(next);
} else {
buffer.append("(this Collection)");
}
if (it.hasNext()) {
buffer.append(", ");
}
}
buffer.append(']');
return buffer.toString();
}
分析这个Collection下的.toString()方法源码,分为几个部分:
1、判断集合是不是空(empty),即集合内有没有数据。如果是空值(没有数据)的话,直接返回字符串 "[]"
2、如果集合不是空值,说明有数据
①、迭代取下一个子元素(Object next = it.next()),如果这个子元素是集合本身,添加"(this Collection)"到StringBuffer类的buffer对象中
②、如果这个子元素不是集合本身,添加到buffer对象中
③、如果这个子元素下面还有子元素,则添加", "到buffer对象中去,用于分割两个相邻子元素
3、返回StringBuffer.toString()字符串
由此可见,返回[1, 2]#[2, 3]是官方正确的返回形式,那么对于这个问题,其实在改不了源码的情况下 给得到的字符串后面使用.replaceAll(" ",""); 把字符串中的空格都去掉
注意:源码中有一段代码:
if (next != this) {
buffer.append(next);
} else {
buffer.append("(this Collection)");
}
这里可能有些同学看不懂,这里举个例子,还是上面的那个,我们在子集合里面 添加代码 c.add(c); 将集合本身添加到集合中去,看看打印结果
ArrayList<ArrayList<Object>> a = new ArrayList<>();
for (int i = ; i < ; i++) {
ArrayList<Object> c = new ArrayList<>();
c.add(i+);
c.add(i+);
c.add(c);
//打印单个子集合的字符串形式数据
Log.i("myinfo",c.toString());
} 看日志结果中红色部分,是不是看懂了,如果集合中的子元素是集合本身,就将"(this Collection)" 添加到返回集合中
05-12 10:58:00.615 8424-8424/com.maiji.magkarepatient I/myinfo: [1, 2, (this Collection)]
05-12 10:58:00.615 8424-8424/com.maiji.magkarepatient I/myinfo: [2, 3, (this Collection)]
至此,上面这个问题解决了,下面我们看下其他类下的.toString()源码。
---------------------------------------------------------------------------------------------------------------
一、Object
/**
* Returns a string containing a concise, human-readable description of this
* object. Subclasses are encouraged to override this method and provide an
* implementation that takes into account the object's type and data. The
* default implementation is equivalent to the following expression:
* <pre>
* getClass().getName() + '@' + Integer.toHexString(hashCode())</pre>
* <p>See <a href="{@docRoot}reference/java/lang/Object.html#writing_toString">Writing a useful
* {@code toString} method</a>
* if you intend implementing your own {@code toString} method.
*
* @return a printable representation of this object.
*/
public String toString() {
return getClass().getName() + '@' + Integer.toHexString(hashCode());
}
翻译一下官方解释:
1、返回一个对于这个Object 简明的、可读的 的字符串
2、Object类的子类被鼓励去重写这个方法来提供一个实现用于描述对象的类型和数据
3、默认的执行形式和下面这个例子一致
getClass().getName() + '@' + Integer.toHexString(hashCode())</pre>
综上:当你的一个类中没有重写.toString()方法的时候就会执行根类Object的这个.toString()方法。
返回形式:对象的类名+@+哈希值的16进制
getClass().getName()返回对象所属类的类名
hashCode()返回该对象的哈希值
Integer.toHexString(hashCode())将对象的哈希值用16进制表示
举例:
Object d = new Object();
Log.i("myinfo",d.toString()); - ::00.758 -/com.maiji.magkarepatient I/myinfo: java.lang.Object@e23e786
二、String,StringBuilder,StringBuffer
三个都是字符串的表现形式,但是有区别的
①、String.toString() , 直接返回本身
/**
* Returns this string.
*/
@Override
public String toString() {
return this;
}
②、StringBuilder
官方解释:以字符串的形式 返回这个builder对象的内容
/**
* Returns the contents of this builder.
*
* @return the string representation of the data in this builder.
*/
@Override
public String toString() {
/* Note: This method is required to workaround a compiler bug
* in the RI javac (at least in 1.5.0_06) that will generate a
* reference to the non-public AbstractStringBuilder if we don't
* override it here.
*/
return super.toString();
}
追溯到super.toString()实现
/**
* Returns the current String representation.
*
* @return a String containing the characters in this instance.
*/
@Override
public String toString() {
if (count == ) {
return "";
}
return StringFactory.newStringFromChars(, count, value);
}
③、StringBuffer
@Override
public synchronized String toString() {
return super.toString();
}
追溯到super.toString()
/**
* Returns the current String representation.
*
* @return a String containing the characters in this instance.
*/
@Override
public String toString() {
if (count == 0) {
return "";
}
return StringFactory.newStringFromChars(0, count, value);
}
综上我们发现,StringBuffer和StringBuilder最终都调用了父级 “AbstractStringBuilder” 中的toString()方法
但是他们本身的toString()却有所不同,我们由此可以总结
1、StringBuilder:线程非安全的
StringBuffer:线程安全的
2、StringBuilder 处理速度要比 StringBudiler 快的多
3、单线程大量数据操作,用StringBuilder ,因为 StringBuilder速度快 , 因为单线程所以不考虑安全性
多线程大量数据操作,用StringBuffer , 因为StringBuffer安全
三、Map
先看源码:
可以看到返回的形式是{key1=value1, key2=value2}
注意 1、当Map集合中没有数据的时候 返回{}
2、每两个数据之前用", "分割,和Collection一致,一个逗号、一个空格
3、当键值是集合本身的时候,添加 (this Map)
public String toString() {
Iterator<Entry<K,V>> i = entrySet().iterator();
if (! i.hasNext())
return "{}";
StringBuilder sb = new StringBuilder();
sb.append('{');
for (;;) {
Entry<K,V> e = i.next();
K key = e.getKey();
V value = e.getValue();
sb.append(key == this ? "(this Map)" : key);
sb.append('=');
sb.append(value == this ? "(this Map)" : value);
if (! i.hasNext())
return sb.append('}').toString();
sb.append(',').append(' ');
}
}
举例:
Map<String,String> map = new HashMap<>();
map.put("keyA","valueA");
map.put("keyB","valueB");
map.put("keyC","valueC");
Log.i("myinfo",map.toString()); 打印结果: 05-12 11:41:30.898 4490-4490/com.maiji.magkarepatient I/myinfo: {keyA=valueA, keyB=valueB, keyC=valueC}
源码浅谈(一):java中的 toString()方法的更多相关文章
- Java中的toString()方法
Java中的toString()方法 目录 Java中的toString()方法 1. 对象的toString方法 2. 基本类型的toString方法 3. 数组的toString ...
- Java中的 toString 方法
1. Object 类中定义有 public String toString() 方法,其返回值是 String 类型,描述当前对象的有关信息: 2. 在进行 String 与其它类型数据的连接操作时 ...
- 源码浅谈(二):java中的 Integer.parseInt(String str)方法
这个方法是将字符串转换为整型 一.parseInt方法 ,可以看到默认又调用了parseInt(s,10) , 第二个参数为基数,默认10 ,当然也可以自己设置 public static int ...
- 【Android测试】【第七节】Monkey——源码浅谈
◆版权声明:本文出自胖喵~的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/4713466.html 前言 根据上一篇我们学会了Monke ...
- 【Android测试】【第三节】ADB——源码浅谈
◆版权声明:本文出自carter_dream的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/4651724.html 前言 由于本人精力 ...
- 结合源码浅谈Spring容器与其子容器Spring MVC 冲突问题
容器是整个Spring 框架的核心思想,用来管理Bean的整个生命周期. 一个项目中引入Spring和SpringMVC这两个框架,Spring是父容器,SpringMVC是其子容器,子容器可以看见父 ...
- 浅谈对java中传参问题的理解
之前用的c/c++比较多,在c/c++中对于传参类型,无外乎就是传值.传引用.传指针这几种.但在java中,由于没有指针类型,其传参的方式也发生了相应的变化.在网上找了找,按我之前的理解,java中传 ...
- 从源码和doc揭秘——Java中的Char究竟几个字节,Java与Unicode的关系
#编码与字符编码 (懂编码的建议直接跳过) 在计算机世界中,任何事物都是用二进制图片数字表示的,图片可以编码为JPG,PNG格式的字节流,音频,视频有MP3,MP4格式的字节流.这些JPG,MP3等都 ...
- glibc memcpy() 源码浅谈
其实我本来只是想搞懂为什么memcpy()函数的参数类型是void *的: 我以为会在memcpy()源码中能找到答案,其实并没有,void *只是在传递参数的时候起了作用,可以让memcpy()接受 ...
随机推荐
- ioS开发之CoreLocation(GPS定位)
1.概述 在iOS开发中,要想加入地图和定位功能这2大功能,必须基于2个框架进行开发 (1)Map Kit :用于地图展示 (2)Core Location :用于地理定位 2个热门专业术语: LBS ...
- 安装prometheus+grafana监控mysql redis kubernetes等
1.prometheus安装 wget https://github.com/prometheus/prometheus/releases/download/v1.5.2/prometheus-1.5 ...
- Sublime Text 3常用插件
操作:按下Ctrl+Shift+P调出命令面板 输入install 调出 Install Package 选项并回车,然后在列表中选中要安装的插件. 常用插件: 1---- Bracket Highl ...
- Unity SteamVR插件集成
重要组件 SteamVR_Camera VR摄像机,主要功能是将Unity摄像机的画面进行变化,形成Vive中的成像画面 使用方法: l 在任一个摄像机上增加脚本 l 点击Expand按钮 完成以上操 ...
- js两个判断&&的值与||的值
var value1="val1"; var value2="val2"; alert(value1&&value2); //结果为val ...
- Linux文件管理下
文件操作 对于文件,我们可以读取(read),写入(write)和运行(execute).读取是从已经存在的文件中获得数据.写入是向新的文件或者旧的文件写入数据.如果文件储存的是可执行的二进制码,那么 ...
- CF #401 (Div. 2) E. Hanoi Factory (栈+贪心)
题意:给你一堆汉诺塔的盘子,设内半径为a,设外半径为b,高度为h,如果bj ≤ bi 同时bj > ai 我们就认为i盘子能落在在j盘子上,问你最高能落多高 思路:一看题意我们就能想到贪心,首先 ...
- ngrok把本地主机映射到公网域名
这两天又要搞微信项目,然后我下载了一个QQ浏览器,搜索微信调试工具,我再搜,再搜,搜不出来,问了下客服,暂时下架了,好吧! 我上网搜了一下,就找到了 ngrok 这个东西,它也可以把你本地主机映射到 ...
- 常用SQL_官方文档使用
SQL语句基础理论 SQL是操作和检索关系型数据库的标准语言,标准SQL语句可用于操作关系型数据库. 5大主要类型: ①DQL(Data Query Language,数据查询语言)语句,主要由于se ...
- Vxlan与网卡offload性能
背景 由于数据链路层MTU的限制,发送端TCP/UDP数据在交付到IP层时需要与MTU相匹配,TCP数据不能超过mss,较长的UDP需要分片(Fragmentation)以满足MTU要求:接收端协议栈 ...