源码浅谈(一):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()接受 ...
随机推荐
- (转)centos6.5安装VNC
在Linux下用VNC远程桌面是个很不错的玩意.但在CentOS中默认没有安装VNC的.可以用下面语句查询,如果出现下面情况说明没有安装vnc #rpm -q tigervnc tigervnc-se ...
- 数据库DDL操作
DDL1. 数据库* 查看所有数据库:SHOW DATABASES* 切换(选择要操作的)数据库:USE 数据库名* 创建数据库:CREATE DATABASE [IF NOT EXISTS] myd ...
- centOS下调整swap
[root@localhost /]# mkdir swap [root@localhost /]# cd swap [root@localhost swap]# dd if=/dev/zero of ...
- 微服务架构的简单实现-Stardust
微服务架构,一个当下比较火的概念了.以前也只是了解过这方面的概念,没有尝试过.想找找.NET生态下面是否有现成的实现,可是没找到,就花了大半个月的闲暇时间,遵循着易用和简单,实现了一个微服务框架,我叫 ...
- win7下nsis打包exe安装程序教程
下载软件包: NSIS中文版 :https://pan.baidu.com/s/1mitSQU0 装好之后会出现两个软件:Nullsoft Install System 和 VNISEdit 编译环境 ...
- 【转】AS3画板工具类,可直接套用
原文链接:http://bbs.9ria.com/thread-212711-1-16.html 今天项目需求做一个画板,要有橡皮擦.自己懒不想写,在网上搜了半天都是习作,没有拿来就能用的又不爱看.只 ...
- sleep()和wait()的区别 --- 快入睡了,突然想起一个知识点,搞完就睡
自从开了博客之后,大部分是转发的,不断的ctrl+c和ctrl+v,知识是越屯越多,吸收的却很少,后来越来越懒,直接保存链接了. 我已经认识到了自己的错误,自己查询到的这些知识,以后还是会定期保存的, ...
- SpringMVC基础学习(一)—初识SpringMVC
一.HelloWorld 1.导入SpringMVC所需的jar包 2.配置web.xml 配置DispatcherServlet.DispatcherServlet默认加载/ ...
- JavaScript学习总结 之对象
JavaScript学习总结(二) ---- 对象 在JavaScript中,几乎用到的每个js都离不开它的对象.下面我们深入了解一下js对象. js中对象的分类跟之前我们学过的语言中函数的分类一样, ...
- Java在Debug的时候,有些变量能无限展开(循环了)?
抛异常的时候,Java Debug 时,有些变量能无限展开,怎么做到的? 先来一个报错的例子: Exception in thread "main" java.lang.Stack ...