Java中的每个类从根本上都是继承Object,标准容器类自然也不。因此容器类都有toString()方法,并且覆写了这个方法,使得它生成的String结果能够表达容器自身,以及容器所包含的对象。例如ArrayList.toString(),它会遍历ArrayList中包含的所有对象,调用每个元素上的toString()方法:
Generator接口:
package com.jxs.chapeter13;
/**
* Created by jiangxs on 2018/4/8.
*/
public interface Generator<T> {
T next();
}
Coffee.java
package com.jxs.chapeter13;
/**
* Created by jiangxs on 2018/4/8.
*/
public class Coffee {
private static long counter = 0;
private final long id = counter++;
@Override
public String toString() {
return getClass().getSimpleName() + " " + id;
}
}
class Latte extends Coffee {
}
class Mocha extends Coffee {
}
class Cappuccino extends Coffee {
}
class Americano extends Coffee {
}
class Breve extends Coffee {
}
CoffeeGenerator.java
package com.jxs.chapeter13;
import java.util.Iterator;
import java.util.Random;
/**
* Created by jiangxs on 2018/4/8.
*/
public class CoffeeGenerator implements Generator<Coffee>,Iterable<Coffee> {
private Class[] types = {Latte.class, Mocha.class,
Cappuccino.class, Americano.class, Breve.class};
private static Random random = new Random(47);
public CoffeeGenerator() {
}
private int size;
public CoffeeGenerator(int size) {
this.size = size;
}
@Override
public Coffee next() {
try {
return (Coffee) types[random.nextInt(types.length)].newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
class CoffeeIterator implements Iterator<Coffee> {
int count = size;
@Override
public boolean hasNext() {
return count > 0;
}
@Override
public Coffee next() {
count--;
return CoffeeGenerator.this.next();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
@Override
public Iterator<Coffee> 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);
}
}
}
ArrayListDisplay.java
package com.jxs.chapeter13;
import java.util.ArrayList;
/**
* Created by jiangxs on 2018/4/8.
*/
public class ArrayListDisplay {
public static void main(String[] args) {
ArrayList<Coffee> coffees = new ArrayList<>();
for (Coffee coffee : new CoffeeGenerator(10)) {
coffees.add(coffee);
}
System.out.println(coffees);
}
}
输出结果:
[Americano 0, Latte 1, Americano 2, Mocha 3, Mocha 4, Breve 5, Americano 6, Latte 7, Cappuccino 8, Cappuccino 9]
Process finished with exit code 0
如果你需要toString()方法打印出对象的内存地址,也许你会考虑使用this这个关键字:
InfiniteRecursion.java
package com.jxs.chapeter13;
import java.util.ArrayList;
import java.util.List;
/**
* Created by jiangxs on 2018/4/8.
*/
public class InfiniteRecursion {
@Override
public String toString() {
return " InfiniteRecursion address: " + this + "\n";
}
public static void main(String[] args) {
List<InfiniteRecursion> v = new ArrayList<>();
for (int i=0;i<10;i++) {
v.add(new InfiniteRecursion());
}
System.out.println(v);
}
}
当你创建了InfiniteRecursion对象,并将其打印出来的时候,你会得到一串非常长的异常。如果你将该InfiniteRecursion对象存入一个ArrayList中,然后打印该ArrayList,你也会得到同样的异常:
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 com.jxs.chapeter13.InfiniteRecursion.toString(InfiniteRecursion.java:13)
at java.lang.String.valueOf(String.java:2994)
···
其实,当代码运行时:
"InfiniteRecursion address: " + this
这里发生了自动类型转换,由InfiniteRecursion类型转换成String类型。因为编译器看到一个String对象后面跟着一个”+”,而后面的对象不是String,于是编译器试着将this转换成一个String。它怎么转换呢,正是通过调用this上的toString()方法,于是就发生了递归调用。
如果你真的想要打印出对象的内存地址,应该调用Object.toString()方法,这才是负责此任务的方法。所以,你不该使用this,而是应该调用super.toString()方法。
如下InfiniteRecursionModify.java所示:
package com.jxs.chapeter13;
import java.util.ArrayList;
import java.util.List;
/**
* Created by jiangxs on 2018/4/8.
*/
public class InfiniteRecursionModify {
@Override
public String toString() {
return " InfiniteRecursion address: " + super.toString() + "\n";
}
public static void main(String[] args) {
List<InfiniteRecursionModify> v = new ArrayList<>();
for (int i=0;i<10;i++) {
v.add(new InfiniteRecursionModify());
}
System.out.println(v);
}
}
输出结果:
[ InfiniteRecursion address: com.jxs.chapeter13.InfiniteRecursionModify@1540e19d
, InfiniteRecursion address: com.jxs.chapeter13.InfiniteRecursionModify@677327b6
, InfiniteRecursion address: com.jxs.chapeter13.InfiniteRecursionModify@14ae5a5
, InfiniteRecursion address: com.jxs.chapeter13.InfiniteRecursionModify@7f31245a
, InfiniteRecursion address: com.jxs.chapeter13.InfiniteRecursionModify@6d6f6e28
, InfiniteRecursion address: com.jxs.chapeter13.InfiniteRecursionModify@135fbaa4
, InfiniteRecursion address: com.jxs.chapeter13.InfiniteRecursionModify@45ee12a7
, InfiniteRecursion address: com.jxs.chapeter13.InfiniteRecursionModify@330bedb4
, InfiniteRecursion address: com.jxs.chapeter13.InfiniteRecursionModify@2503dbd3
, InfiniteRecursion address: com.jxs.chapeter13.InfiniteRecursionModify@4b67cf4d
]
Process finished with exit code 0
参考:《Java编程思想》