java中
List list =new ArrayList();
list.add("a");
list.add("b");
System.out.println(list);
上面的代码中,list应该是指向new ArrayList();的地址吗,那我输出list时,应该会输出一个地址值 呀,
为什么会输出 [a b]出来呢,thanks
因为容器类的toString()方法被重写了,只要重写一个类的toString()方法打印一个该类的对象时就按照你重写的方式打印了,Java的只要是new出来的对象都创建在堆中。
java中所有的类都是继承object类,在object类中有toString方法,ArrayList中重写了toString方法,所以会输入里面的元素的值而不是地址。java很多包中的类都重写的toString方法!
public String toString() {
Iterator<E> i = iterator();
if (! i.hasNext())
return "[]";
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
E e = i.next();
sb.append(e == this ? "(this Collection)" : e);
if (! i.hasNext())
return sb.append(']').toString();
sb.append(", ");
}
}
至于new出来的对象 肯定是放在堆里面的。list这个变量是放在栈里面,new出来的东西是在堆里面划分的空间,关于栈和堆的区别可以参考下面的文章
list 这个变量(一个List类型的引用)在栈中,它所指向的对象在堆中,栈中肯定存放的是一个地址,至于这个地址是不是直接指向堆中那个对象的地址,不同的jvm有不同的做法,有的是先指向java堆中的句柄池中的某个地址,然后该地址再指向对象实例;有的是直接指向堆中的对象实例
当用System.out.println 一个变量时,是调用变量的对象的toString方法,如果你定义的类没有重写toString方法,那就用Object类的toString方法,Object的toString方法是用c/c++代码实现的
ArrayList 继承自AbstractList,AbstractList继承自AbstractCollection
AbstractCollection中的toString方法如下:
Java code
public String toString() {
Iterator<E> i = iterator();
if (! i.hasNext())
return "[]";
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
E e = i.next();
sb.append(e == this ? "(this Collection)" : e);
if (! i.hasNext())
return sb.append(']').toString();
sb.append(", "); } }