李林超博客
首页
归档
留言
友链
动态
关于
归档
留言
友链
动态
关于
首页
Java
正文
字符串--无意识的递归
Leefs
2019-12-18 AM
3950℃
2条
# 字符串--无意识的递归 ### 前言 本篇讲述《Java编程思想》第13.3小节,无意识的递归 ### 概念 Java中的每个类从根本上都是继承自Object,标准容器类自然也不例外。因此**容器类都有toString()方法,并且覆写了该方法,使得它生成的String结果能够表达容器自身,以及容器所包含的对象**。例如ArrayList.toString(),它会遍历ArrayList中包含的所有对象,调用每个元素上的toString()方法: ```java public class ArrayListDisplay { public static void main(String[] args) { ArrayList
coffees = new ArrayList
(); for(Coffee c : new CoffeeGenerator(10)) coffees.add(c); System.out.println(coffees); } } ``` > 运行结果 ```java [Americano 0, Latte 1, Americano 2, Mocha 3, Mocha 4, Breve 5, Americano 6, Latte 7, Cappuccino 8, Cappuccino 9] ``` > 相关程序 ```java class Coffee { private static long counter = 0; private final long id = counter++; public String toString() { return getClass().getSimpleName() + " " + id; } } class Latte extends Coffee {} class Cappuccino extends Coffee {} class Mocha extends Coffee {} class Americano extends Coffee {} class Breve extends Coffee {} interface Generator
{ T next(); } class CoffeeGenerator implements Generator
, Iterable
{ private Class[] types = { Latte.class, Mocha.class, Cappuccino.class, Americano.class, Breve.class, }; private static Random rand = new Random(47); public CoffeeGenerator() {} // For iteration: private int size = 0; public CoffeeGenerator(int sz) { size = sz; } public Coffee next() { try { return (Coffee) types[rand.nextInt(types.length)].newInstance(); // Report programmer errors at run time: } catch(Exception e) { throw new RuntimeException(e); } } class CoffeeIterator implements Iterator
{ int count = size; public boolean hasNext() { return count > 0; } public Coffee next() { count--; return CoffeeGenerator.this.next(); } public void remove() { // Not implemented throw new UnsupportedOperationException(); } }; public Iterator
iterator() { return new CoffeeIterator(); } public static void main(String[] args) { CoffeeGenerator gen = new CoffeeGenerator(); for(int i = 0; i < 5; i++) System.out.println(gen.next()); for(Coffee c : new CoffeeGenerator(5)) System.out.println(c); } } ``` 如果你希望toString()方法打印出对象的内存地址,也许你会考虑使用this关键字: ```java public class InfiniteRecursion { public String toString(){ return "InfiniteRecursion address:"+this+"\n"; } public static void main(String[] args) { List
v = new ArrayList
(); for(int i=0;i<10;i++){ v.add(new InfiniteRecursion()); } System.out.println(v); } } ``` > 运行异常信息 ```java Exception in thread "main" java.lang.StackOverflowError at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:125) at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:448) at java.lang.StringBuilder.append(StringBuilder.java:136) at ThinkInJava.StringTest.InfiniteRecursion.toString(InfiniteRecursion.java:8) at java.lang.String.valueOf(String.java:2994) at java.lang.StringBuilder.append(StringBuilder.java:131) at ThinkInJava.StringTest.InfiniteRecursion.toString(InfiniteRecursion.java:8) ``` 当创建了InfiniteRecursion对象,并将其打印出来的时候,将会得到一串非常长的异常。如果你将该InfiniteRecursion对象存入一个ArrayList中,然后打印该ArrayList,你也会得到同样的异常。其实,当如下代码运行时: ```java "InfiniteRecursion address:"+this ``` 这里发生了自动类型转换,由InfiniteRecursion类型转换成String类型。因为编译器看到一个String对象后面跟着一个“+”,而再后面的对象不是String,于是编译器试着将this转换成一个String。它怎么转换呢,正是通过调用this上的toString()方法,于是就发生了递归调用。 如果真的想要打印出对象的内存地址,应该调用Object.toString()方法,这才是负责此任务的方法。所以,你不该使用this,而是应该调用super.toString()方法。 > 正常代码 ```java public class InfiniteRecursion { public String toString(){ return "InfiniteRecursion address:"+super.toString()+"\n"; } public static void main(String[] args) { List
v = new ArrayList
(); for(int i=0;i<10;i++){ v.add(new InfiniteRecursion()); } System.out.println(v); } } ``` > 运行结果 ```java [InfiniteRecursion address:ThinkInJava.StringTest.InfiniteRecursion@74a14482 , InfiniteRecursion address:ThinkInJava.StringTest.InfiniteRecursion@1540e19d , InfiniteRecursion address:ThinkInJava.StringTest.InfiniteRecursion@677327b6 , InfiniteRecursion address:ThinkInJava.StringTest.InfiniteRecursion@14ae5a5 , InfiniteRecursion address:ThinkInJava.StringTest.InfiniteRecursion@7f31245a , InfiniteRecursion address:ThinkInJava.StringTest.InfiniteRecursion@6d6f6e28 , InfiniteRecursion address:ThinkInJava.StringTest.InfiniteRecursion@135fbaa4 , InfiniteRecursion address:ThinkInJava.StringTest.InfiniteRecursion@45ee12a7 , InfiniteRecursion address:ThinkInJava.StringTest.InfiniteRecursion@330bedb4 , InfiniteRecursion address:ThinkInJava.StringTest.InfiniteRecursion@2503dbd3 ] ```
标签:
Java
,
Java编程思想
,
JavaSE
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:
https://lilinchao.com/archives/304.html
上一篇
Shiro简介
下一篇
字符串--String上的操作及练习题
评论已关闭
栏目分类
随笔
2
Java
326
大数据
229
工具
31
其它
25
GO
47
NLP
4
标签云
gorm
Docker
Beego
正则表达式
DataWarehouse
Sentinel
JavaWeb
Spark SQL
Stream流
Http
并发线程
Git
字符串
持有对象
排序
散列
Azkaban
Golang基础
Flume
数学
Shiro
Java工具类
Zookeeper
并发编程
Jquery
Hive
Spark Core
随笔
前端
JavaWEB项目搭建
友情链接
申请
范明明
庄严博客
Mx
陶小桃Blog
虫洞
评论已关闭