思考停止するならプログラミングやめた方がいいです。
まず、エラーメッセージぐらいは読みましょう。
Exception in thread "main" java.lang.StringIndexOutOfBoundsException:
String index out of range: 3
[訳]
mainメソッドにて例外発生っす。
java.lang.StringIndexOutOfBoundsException
ってやつっす。
文字列のインデックス(添え字)が範囲外を指しているっす。3番目っすね…
っていう感じでしょうか。
このjava.lang.StringIndexOutOfBoundsExceptionは公式リファレンスで調べると、
String メソッドによりスローされ、インデックスが負または文字列のサイズより大きいことを示します。charAt などのいくつかのメソッドでは、インデックスが文字列のサイズと等しい場合にも、この例外がスローされます。
とあります。つまり、簡単に言えば、『範囲外系例外』ってところです。
文字列はプログラマ的にはJavaを使っている場合は単なる変数に入れているように見えますが、おそらく内部では配列として保持しているはずです。C言語みたいに。ただ、わかりづらいのであえて意識させない作りになっているのだと思います。
つまり、要素数10の配列を arr[100]のようにアクセスしたりしているような状態です。
5階建ての建物に15階に行こうとしているような状態です。無理ですから。
つまり、『アクセスできないところを参照している』みたいな感じです。
[今後気をつけるべきこと]
1. エラーメッセージを読もう
2. 情報を省くな
3. 思考停止するな
4. 自分なりに調べよ
5. 試したことを書くべき
ーーー
[追記1]
当たり前でしょ…
そもそもプログラミングってのは『すでにあるコードを切り貼りして作ること』ではありません。
ロジックを書くのです。数学の証明を自力で考えるようなものです。
とりあえず、コードを読みましょう。
コードを読むコツは『一行レベルで、その行が何をしているかを考えながら読む』です。
まずはmainメソッドから読んでみましょう。
Java
1class Sample {
2 public static void main(String[] args) {
3 // Sortクラスをインスタンス化
4 Sort s = new Sort();
5 // 生成したオブジェクトのAACメソッドを呼び出す
6 s.asc();
7 // sが持つgetAryメソッドを呼び出す
8 s.getAry();
9 // iの初期値: 0, i が sのgetIdxメソッドが返すものより大きい間, 増加しながら繰り返す
10 for (int i = 0; i < s.getIdx(); i++) {
11 // sのgetAryメソッドを呼び出してその返ってきたやつのi番目にアクセスして出力
12 System.out.println(s.getAry()[i]);
13 }
14 }
15}
これを手作業でやると考えてみてください。数学の手順とかでもいいです。とにかくシミュレーションしてください。
そうすると、三行目の『sが持つgetAryメソッドを呼び出す』がちょっと意味わかりませんね。
名前から察するに『オブジェクトが持つ配列を取得する』ってところでしょうけど、何も受け取っていません。
だったら呼び出す必要なくない?
さらに、今までに呼び出されたメソッドやコンストラクタ内も同様にやる。
コンストラクタはデフォルトのやつ(デフォルトコンストラクタ)のようなのでスルー。
getAryメソッドは名前通り、単にフィールドとして持っている配列を取得するだけ。getIdxメソッドは意味不明(名前と処理が合っていない)ですが、処理内容を見ると単に要素数を返しているだけですね。
なので ascメソッドを読んでみましょう。
Java
1 public void asc() {
2 // iについて、要素数分ループ(先端から末端へ)
3 for (int i = 0; i < ary.length; i++) {
4 // jについて、同上
5 for (int j = 0; j < ary.length; j++) {
6 // (j,j)の位置データと(i,i)の位置のデータを比較し、(j,j)が大きければ
7 if ((int) ary[j].charAt(j) > (int) ary[i].charAt(i)) {
8 // 交換アルゴリズムによる交換
9 String tmp = ary[i];
10 ary[i] = ary[j];
11 ary[j] = tmp;
12 // メソッド終了!
13 return;
14 }
15 }
16 }
17 }
これを疑似コードとして書きだす。
pseudo
1[疑似コード]
2
31. iについて、要素数分、以下をループ(先端から末端へ) ( i = 1, 2, 3, ... )
4 1.1. jについて、要素数分、以下をループ(先端から末端へ) ( j = 1, 2, 3, ... )
5 1.1.1. (j,j)の位置データと(i,i)の位置のデータを比較し、(j,j)が大きければ
6 1.1.1.1. 交換アルゴリズムによる交換
7 1.1.1.2. メソッドの終了!
これを実際にシミュレーションしてみてください。実際にi,j,ary等にデータを入れて計算してみるとか。
そうすると、まず (1)で i = 0 となります。(1.1)では j = 0 となり、i = 0, j = 0
となる。
(1.1.1)で (0,0) と (0,0) を比較。つまり、Excelの表みたいに見て、0行0列のデータを比較するのです。
同じ場所を比較しているので大きいも小さいもありません。なので(1.1)に戻る。
(1.1)で j を進ませる。つまり、i = 0, j = 1
となる。そのまま(j,j) > (i,i)を比較。
(1,1) > (0,0) なのですが、対象となっている配列はString[] ary = { "b", "a", "c" };
のようです。要素数はそれぞれ1で、配列は0番目から始まるので 0~(n-1)番目 までしかアクセスできません。
つまり、1行目は "a"ですが、1列目は無いです。'a' が 0番目なので。
そうなると、「んなもんねーよ!!!」となってしまいますね。
101番目までしかないコインロッカーを『109番目から取り出して来い』と言われているようなものです。無理でしょ…
そもそも無理なので、「おーーーい、そんな場所ないぞ?」という例外が投げられているだけです。
それと他の方も仰っているように、デバッグしましょう。
大雑把なやり方は上記での「コードを読む」と大体一緒です。単にデバッガを使うのか、いわゆるprintfデバッグでやるのか、コードのみでやるのかとかの違いだけです。