【Java】toString()を使ってArrayListの全要素を文字列として取得する

またまたUdacity Introduction to Programmingで詰まった箇所があったので覚え書き。 friendを追加したりfriends (PersonのArrayList) のリストを取得したりできるPersonというクラスなのだけど、この中のgetFriends()メソッドがよく理解できず詰まっていた。

import java.util.ArrayList;

class Person
{
    // テストコード
    public static void main(String args[]) {
        Person test1 = new Person("test1");
        Person test2 = new Person("test2");
        Person test3 = new Person("test3");
        test1.addFriend(test2);
        test1.addFriend(test3);
        System.out.println(test1.getFriends());
    }
    
    private String name;
    private ArrayList<Person> friends;

    public Person(String name)
    {
        this.name = name;
        friends = new ArrayList<Person>();
    }

    /**
     * Adds the given friend to this Person's friends list.
     * @param friend the friend to add.
     */
    public void addFriend(Person friend)
    {
        friends.add(friend);
    }

    /**
     * Gets a list of all of this Person's friends.
     * @return the names of the friends separated by a comma and a space.
     *     e.g. "Sara, Cheng-Han, Cay"
     */
    public String getFriends()
    {
        String withBrackets = friends.toString();
        return withBrackets.substring(1, withBrackets.length() - 1);
    }

    public String toString()
    {
        return name;
    }
}

よくわからなかったのは下の部分。

    public String toString()
    {
        return name;
    }

return name;ってなんだ???friendsでreturn name;したら何が返ってくるんだ?ArrayListだと特別に各要素の変数をリストにしたものを返すのか?と悩み続けていた。
解ってみればなんてことはないのだけど、toString()をオーバーライドしたのはArrayListのものではなくPersonクラスのものだという当たり前のことを履き違えていた。ArrayListのtoString()で呼び出される各Person要素でさらにオーバーライドしたtoString()が呼び出されているという二重の構造になっているということに気づけなかった。friendsで呼び出しているのがtoString()なので、てっきりそっちがオーバーライドされているものと思い込んでしまったのが原因。
参照:I Don't Understand the toString() Method In This Example - Udacity Forums

ちなみにこのtoString()はIntegerクラスで数値を文字列に変換といった使い方の他、System.out.print(friends);のように参照型変数だけを書いた時にも呼び出されるようになっているみたい。なかなか便利そう。
参照:toStringメソッドのオーバーライドの勧め① « ゆめばく5