「プロになるJava」 第2部「Javaの基本」の練習問題解答

「プロになるJava」の第2部「Javaの基本」の練習問題の解答です。

「プロになるJava」 第3部「Javaの文法」の練習問題解答 - きしだのHatena
「プロになるJava」 第4部「高度なプログラミング」の練習問題解答 - きしだのHatena

第3章 値と計算

3.2 値と演算

3.2.1 整数

1. 7+2を計算してみましょう
jshell> 7 + 2
$1 ==> 9
2. 7-2を計算してみましょう
jshell> 7 - 2
$2 ==> 5
3. 7×2を計算してみましょう
jshell> 7 * 2
$3 ==> 14
4. 7÷2を計算して整数部分の結果を出してみましょう
jshell> 7 / 2
$4 ==> 3
5. 7を2で割った余りを計算してみましょう
jshell> 7 % 2
$5 ==> 1

3.2.3 実数

  1. 7÷2を小数点以下の結果も出るように計算してみましょう
jshell> 7. / 2
$7 ==> 3.5

3.3 メソッドの呼び出し

3.3.2 文字列の掛け算や引き算?

掛け算の代わりにrepeatメソッド
1. repeatメソッドを使って"test"を4回繰り返してみましょう
jshell> "test".repeat(4)
$8 ==> "testtesttesttest"
引き算の代わりにreplaceメソッド
1. replaceメソッドを使って"test"から"t"を取り除いて"es"が残るようにしてみましょう。
jshell> "test".replace("t", "")
$9 ==> "es"
2. replaceメソッドを使って"test""es""alen"に置き換えて"talent"にしてみましょう。
jshell> "test".replace("es", "alen")
$10 ==> "talent"

3.3.4 メソッドの使い方がわからないとき

1. 文字列の長さを返すメソッドがあります。Javadocから探して試しに呼び出してみましょう。
jshell> "test".length()
$11 ==> 4
2. 文字列の一部を返すメソッドがあります。Javadocから探して「"test"」の2文字目以降を取り出して"est"を表示されるようにしてみましょう。
jshell> "test".substring(1)
$12 ==> "est"

第4章 変数と型

4.1 変数

1. varをつけて変数sを使えるようにしてみましょう。
jshell> var s = "site"
s ==> "site"

4.2 型

4.2.3 変数の型を指定する

1. 「var c = 5」をvarを使わずintを使って書いてみましょう。
jshell> int c = 5
c ==> 5
2. 「var u = "UFO"」をvarを使わずStringを使って書いてみましょう。
jshell> String u = "UFO"
u ==> "UFO"
3. 「var w = "watch"」をvarを使わずintStringのどちらかを使って書いてみましょう。
jshell> String w = "watch"
w ==> "watch"
4. 「var d = 12」をvarを使わずintStringのどちらかを使って書いてみましょう。
jshell> int d = 12
d ==> 12

第5章 標準API

5.1 日付時刻

5.1.3 パッケージとimport

1. パッケージ名を省略して現在の日付を表示させてみましょう。
jshell> LocalDate.now()
$2 ==> 2022-03-27
2. パッケージ名を省略して現在の時刻を表示させてみましょう。
jshell> LocalTime.now()
$3 ==> 21:00:36.528563700

5.1.4 日付時刻の操作

1. LocalDateクラスを使って明日の日付を求めてみましょう
jshell> LocalDate.now().plusDays(1)
$7 ==> 2022-03-28
2. LocalDateクラスを使って2週間後の日付を求めてみましょう
jshell> LocalDate.now().plusWeeks(2)
$8 ==> 2022-04-10

5.1.6 日付時刻の整形

1. java17date変数に用意したJava17のリリース日を2021年09月14日という形式で表示してみましょう。
jshell> "%tY年%<tm月%<td日".formatted(java17date)
$11 ==> "2021年09月14日"
2. java17dateTime変数に用意したJava17のリリース日時を2021年09月14日 14時30分という形式で表示してみましょう。
jshell> "%tY年%<tm月%<td日 %<tH時%<tM分".formatted(java17dateTime)
$13 ==> "2021年09月14日 14時30分"

5.1.7 staticメソッドとインスタンスメソッド

1. LocalDateクラスを使って2020年2月28日の次の日を求めてみましょう
jshell> LocalDate.of(2020,2,28).plusDays(1)
$14 ==> 2020-02-29
2. LocalDateクラスを使って2020年2月28日の2週間後の日付を求めてみましょう
jshell> LocalDate.of(2020,2,28).plusWeeks(2)
$15 ==> 2020-03-13
文字列整形のformattedメソッドとformatメソッド
1. "%tm月".formatted(today)String.formatを使って書き換えてみましょう。
jshell> String.format("%tm月", today)
$17 ==> "03月"
2. "%sは%d".formatted("two", 2)String.formatを使って書き換えてみましょう。
jshell> String.format("%sは%d", "two", 2)
$18 ==> "twoは2"
3. String.format("%tY年", today)formattedメソッドを使って書き換えてみましょう。
jshell> "%tY年".formatted(today)
$19 ==> "2022年"

5.2 BigDecimal

5.2.2 BigDecimalでの計算

1. BigDecimalクラスを使って119999×0.1を誤差なく計算してみましょう
jshell> BigDecimal.valueOf(119999).multiply(BigDecimal.valueOf(0.1))
$21 ==> 11999.9

5.2.3 newによるBigDecimalオブジェクトの生成

オブジェクト
1. 1.4142135623730950488×1.4142135623730950488を計算してみましょう。同じ数同士を掛けています。
jshell> var root2 = new BigDecimal("1.4142135623730950488")
root2 ==> 1.4142135623730950488

jshell> root2.multiply(root2)
$24 ==> 1.99999999999999999999522356663907438144

第6章 SwingでのGUI

6.1 Swingでのウィンドウ表示

6.1.2 ウィンドウを表示してみる

1. setLocationメソッドを使ってウィンドウを右に動かしてみましょう。
jshell> f.setLocation(300,200)

※ getLocationメソッドで得たx座標より大きい値を最初の引数に指定してください。

6.1.3 入力領域の配置

1. 入力領域に「Hello Swing」を表示してみましょう。
jshell> t.setText("Hello Swing")

6.1.4 ふたつめの入力領域

1. 上側の入力領域に入力された文字列を下側の入力領域に表示してみましょう
jshell> t2.setText(t.getText())

2. 上側の入力領域に入力された文字列の大文字を小文字に変換して下側の入力領域に表示してみましょう
jshell> t2.setText(t.getText().toLowerCase())

6.2 画面に絵を描いてみる

6.2.3 図形の描画

1. 左下から右上に向かって直線を描いてみましょう
jshell> g.drawLine(0, 400, 600, 0)

jshell> label.repaint()
2. g.setColor(Color.BLUE)として色が指定できるようにjava.awt.Colorクラスのimportを行ってみましょう
jshell> import java.awt.Color

3. 青く塗りつぶされた円を描いてみましょう
jshell> g.setColor(Color.BLUE)

jshell> g.fillOval(50, 200, 150, 150)

jshell> label.repaint()

6.3 Javaの基本文法

6.3.1 Javaの文法

名前の付け方のガイドライン
1. 「my bag」をクラス名にするとしたらどうなるか考えてみましょう。

MyBag

2. 「my bag」を変数名にするとしたらどうなるか考えてみましょう。

myBag

3. 「get bag」をメソッド名にするとしたらどうなるか考えてみましょう。

getBag

4. 「画面に絵を描いてみる」でやったことをプログラムにしてみましょう
package projava;

import javax.swing.*;
import java.awt.image.BufferedImage;
import java.awt.Color;

public class Drawing {
    public static void main(String[] args) {

        var f = new JFrame("drawing");
        f.setVisible(true);

        var label = new JLabel("test");
        f.add(label);

        var image = new BufferedImage(600, 400, BufferedImage.TYPE_INT_RGB);
        label.setIcon(new ImageIcon(image));
        f.pack();

        var g = image.createGraphics();
        g.drawLine(0, 0, 600, 400);
        g.setColor(java.awt.Color.RED);
        g.fillRect(300, 200, 150, 100);
        g.drawLine(0, 400, 600, 0);

        g.setColor(Color.BLUE);
        g.fillOval(50, 200, 150, 150);
        label.repaint(); 
    }
}

型理論を理解するためのロードマップ

基本的には少しずつオーバーラップしているはず。
「論理と計算のしくみ」はぜひ読んでほしいです。この本に論理の説明もあるので、先にこれを買って、わからなければさかのぼる感じでいいかも。

論理学に入門する

論理学をもすこし勉強する

計算とつなげる

プログラミング言語を学ぶ

壁にたちむかう
これは、「プログラミング言語の基礎概念」で ものたりないって思ったときだけ手を出すくらいでいいです。

教えるということ - 漂流開発者の日記(WEB+DB PRESS VOL.20, 2004-3-26)

2004年のWEB+DB PRESS VOL.20に掲載された記事です。絵もかいてます。

開発してない

開発者の日記といいながら、最近とんと開発してないことに気付きました。
じゃあ何してるかというと、絵を描いたり、プログラムを教えたりしてます。
教えるのも楽しいんですけど、開発してないと、実際のプログラムの話がしにくくなるんですよね。
教えるときに絵がうまく描けると評判がいいですけど。

あの人が先生?

教えるときにスーツを着てないこともあって、「え、あの人が先生?」と言われることがよくあります。髪の色がすごいことなってることも多いですからね。
最初は話の調子も悪いですし。
もちろん、いきなり言われるんじゃなくて、全部の過程が終わったあとの飲み会とかで「実は最初はどうなるかと思った」という話を聞くわけですね。まぁ、最終的にそういう話ができるようになっているので、ヨシとしましょう。
それより、苦手なのは「先生」と呼ばれることです。いまでこそ慣れましたけど、最初は講義中にそう呼ばれるのもなんだかくすぐったいものがありました。
すでにかなり前に教える期間が終わった人たちから「先生」と呼ばれるのは、いまだに慣れませんね。年上の人が多いのに。「先生」で馴染んでるのでしかたないと思いますけど。
飲み屋の店員さんに「あの人が先生?」と思われてそうで、それが一番こっぱずかしいです。

はじめてのプログラム

ぼくが教えてる人たちは、プログラムの勉強が初めてのことが多いです。
で、そんな人たちにJavaを教えるのですが、最初はコマンドプロンプトからjavacコマンドでコンパイルしてjavaコマンドで実行、ということをやってもらってたわけです。エディタでプログラムを入力してもらって。
ところがあるとき受講生の人数が多くて、コマンドプロンプトじゃやってられなくなってForteというツールを使うことにしました。今はSun Java Studioっていう名前になってて、NetBeansというオープンソース版も出てるツールです。
最初だけはやっぱりコマンドプロンプトHello worldプログラムをやってもらって、それからForteを使って、ウィンドウ上のボタンを押したらメッセージを出すプログラムを作ってもらうようにしました。
そしたら受講生のひとりが、ウィンドウ出すプログラムが動いたときに「あ、プログラムが作れた気がする」って言うんですよ。「えっ」と思いましたね。だってHello worldの時点で一応プログラム作ってるわけですから。

やっぱりWindowsからパソコンをさわった人にとっては、プログラムっていうのはウィンドウが出てナンボということを実感しました。
それ以来、サンプルプログラムは動きを見て何をしてるものかがわかるようにしています。
なんにしても、そうやってプログラム初体験だった人たちが、ソフトウェア関係の仕事に就いたという話を聞くと、うれしくなります。仕事じゃないにしても、プログラムを作ってみた、という話を聞くのもうれしいですね。
もっとプログラムの楽しさを伝えれるようになりたいものです。

プログラミングの最初の壁は逐次実行 #projava

プログラミングの入門書で、変数だとかfor文なんかは丁寧に例えなどを使って説明されていることが多いのですけど、逐次実行はほとんど説明されていることがありません。
入門書を書く人にとって、逐次実行は自明であって説明が必要なものではないという認識があると思います。

プログラムに慣れた人にとって、プログラムが上から順に実行されるというのは当たり前で学習が必要なことには思えないと思います。
「見たままやん」
となるのではないかと。

けど、実際には上から順に動くというのがよくわからないようです。
「あ、プログラムって上から順番に実行されるんですね、わかってなかった」
と言われたことがあります。そういうふうに言ってくれる人がいるということは、言わないけどわかってなかったという人が何倍もいるはずです。

通常の文章というのは、基本的には一定の状態を仮定して書かれていて、前部と後部で表す状態が違うということはありません。文章の順番を入れ替えても、表したい内容には違いがありません。物語は状態が変わっていくように見えますが、実は冒頭から、結末の状態を書き記しているだけだったりします。読み込みの遅さを利用して結末の状態が徐々に明らかになることで物語が進行します。
数学で複数の式が提示されても、それはすべての式が同時に常になりたつ関係式で、式を評価するごとに関係がかわるということはないです。
つまり、文章にしろ数学の式にしろ、一行ずつ処理が進んで状態が変わる、ということに慣れていないわけです。

考えてみると、上から順に動くという場合にはどの行を実行しているのかというステートの管理が必要です。
プログラミング初心者の場合、そういった自明に思えるステートというのが頭のなかに構築できていません。

そして、重要なステートのひとつには変数があります。
変数の説明のために箱だと例えてみたり、いや箱ではなく場所だと言ってみたり、変数の特性についてあの手この手で説明がされてきました。でも結局のところ、変数がわからないということは、逐次実行がわかっていないことが原因の可能性があります。
少なくとも、逐次実行がわかっていないと、変数の内容が変化していくことがわかりません。

int a;
a = 3;
print(a);
a = 5;
print(a);

のようなコードがわからないというとき、変数のふるまいがわかっていないように見えますが、実際はコードが順に実行されていくということがわかっていない可能性があります。だとすると、変数の特性をいくら説明しても無駄ということになります。

また、逐次実行がわかっていないのであれば、その一部が繰り返されるループも当然わからないということになります。
逐次実行を丁寧に習得させれば、変数やループではつまづきにくくなるかもしれません。

そのため、「プロになるJava」では、まず最初にJShellを使って自分の手でコードを一行ずつ動かすことで、プログラムが一行ずつ実行されて状態が変化していくことを体感してもらうようにしています。
JShellでウィンドウを出すコードを動かしてもらったあとでそのコードをまとめたプログラムを作ってもらって、ソースコードに書いたものは一行ずつ実行されるんだということが実感できるようにしています。

またforループではデバッガを使って処理の動きと変数の値の遷移を追うようにしています。デバッガで処理や変数の動きを追うことも、プログラムや変数の理解には大切なので、プログラミングの学習にIDEが必要だと思っています。

残念ながら「創るJava」と違って、「プロになるJava」の元ネタを使って実際に人に教えてないので、実際のところはこれからほんとの初心者の人が読んだり研修に使われたりすることでわかってくるとは思うのですが、少なくとも今までの、ひとまとめのソースコードを提示して一気に動かして一行ずつ解説するというアプローチよりはうまくいくのではないかなと思っています。

「プロになるJava」はこんな人におすすめ #projava

「プログラミング未経験ですがJavaをやることになりました。いい本ないですか?」
→ JShellを使って動作を1ステップずつ確認しながら進めれる唯一のJava入門書「プロになるJava」をおすすめ

「プログラムの入門書なのに文字ばっかり出してプログラムの作り方の説明がありませんでした。いい本はありませんか?」
→ ウィンドウだしたり絵を描いたりしてプログラム感のあるサンプルもでてきて最後はWebアプリケーションまでつくる「プロになるJava」をおすすめ

「なんかJavaの本って1冊だけじゃ終わらなくて実践編とかサーブレットの本とか必要だから高くないですか?」
→ 一冊でJavaの基本からクラスを使ったプログラム、テストやビルドツール、Spring BootでのWebアプリ、データベースまで解説した「プロになるJava」をおすすめ

「ナントカなJavaという本を終わらせたので次に勉強する本ないですか?」
→きっとその本に書いてない必須知識がたくさんまとめてある「プロになるJava」をおすすめ

「一応Javaでプログラム組めるようになったんだけど、ちょっと複雑な処理になるとどう書いていいかわからないのでいい本ないですか?」
→複雑な処理の書き方を、なぜそれが複雑で難しいのか段階を追って説明している「プロになるJava」をおすすめ

Javaオブジェクト指向がうまくできないんですけど、いい本ないですか?」
オブジェクト指向なんかやらなくていいって教えてくれる「プロになるJava」をおすすめ

「でもクラスとか継承とか使うのにオブジェクト指向が必要なんでしょ?いい本ないですか?」
→継承の使い方をオブジェクト指向という言葉を使わずに解説している「プロになるJava」をおすすめ

hogeという言語を使っててJavaには興味ないんだけど、もうすこしプログラミング能力を高めたいと思ってます。いい本ないですか?」
→ 複雑な処理の書き方の解説もHTTPやHTTPSプロトコルの解説もある「プロになるJava」のサンプルをhoge言語でやっていくのをおすすめ。

「なんかヒマなんだけど時間つぶしにいい本ないですか?」 → このブログ程度の読みやすい文章で進めれる「プロになるJava」をおすすめ。ついでにJavaがわかっちゃう

このブログにたどりつきましたね?「プロになるJava」をおすすめ

オブジェクト指向は差分プログラミングとデータ分類をまとめて扱おうとしたのが弱点

オブジェクト指向の最大の特徴は、モジュールと型を一体に扱ったことです。
メイヤーの本では次のような「オブジェクト指向の基準」があげられています。

  • クラスが唯一のモジュールでなければならない
  • すべての型はクラスに基づいていなければならない

つまり、クラスはモジュールであり型であるということです。
ここで、モジュールにとって必要な、クラスで実現できる機能は、モジュール間で異なる部分だけをそのモジュールで実装するという差分プログラミングです。
型に求められるのは、データの分類です。
ということは、オブジェクト指向は差分プログラミングとデータの分類を同時に扱おうとしていたということになります。

けれども、データの分類と差分プログラミングを同時に行うのは大変です。
「できらぁ!データの分類と同時に差分プログラミングして、いいソフトウェアができるっていったんだよ!!」
というのがオブジェクト指向だったのですが、いざこうやって改めて「データの分類と同時に差分プログラミングを行ってうまいソフトウェアをつくってもらおう」って言われると
「え!!データ分類と同時に差分プログラミングを!?」
ってなるわけです。

現在のプログラミング言語の型は、オブジェクト指向が流行った時代よりもかなり発展しています。型によるデータの分類は、オブジェクト指向を離れて発展した型理論をもとに考えるほうが、整理され新しい考え方にもついていきやすいです。

差分プログラミングは、クラスと継承をもとに考えてもコーディング作業として煩雑で、またムダな制約も持ち込んでしまいます。 いまや差分プログラミングはラムダ式など関数ベースで行うほうが主流でしょう。

ということで「継承を使って差分プログラミングをすると便利だよー、でもあれれ~ラムダ式でもっと簡単にできちゃったね」という説明したり継承による型の分類を紹介したりする本が3/19に出ますね。

FAQ
Q 電子版はでますか?
A 紙版のあとに出る予定

Q 目次等は?
A もうしばらくお待ちを

あと、メイヤーの本はこちら。

プログラミング言語の入門書はプログラミングの入門書ではないのでプログラミングできるようにならない

(これはPR記事です)
「入門書を読んだけどプログラミングできるようにならない」という話はよく聞きます。

そこで「まあ経験や慣れが必要だからね」みたいな話になり、その後、経験を積んでもできるようにならない人は「センスがなかった」ということになったりします。
じゃあそのセンスっていうのは何かというと、結局のところ「できるようになった人にはセンスがあった」という生存者バイアスなだけで、運とそんなに違いないわけです。

でも、トップレベルを目指すとかではない限り、それなりの知識とトレーニングがあればほとんどの人はプログラミングできるようになるはずです。

で、まあ入門書を読んでプログラミングできるようにならないほは当然で、プログラミング言語の入門書のほとんどは、プログラミング言語の入門書であってプログラミングの入門書ではありません。

変数の説明にしても、箱だったり場所だったりで例えて「それが何であるか」の説明をがんばったりするのだけど、じゃあ実際どう使うかというのは説明してくれません。
プログラムで一番難しいのはループですが、ループの構文の説明があるだけで、ループのコードをどのように考えていく必要があるかというのは説明されてません。
クラスにしてもオブジェクト指向というなにやら壮大な言葉をもってきて、これがオブジェクト指向ですというプログラムを提示するのだけど、じゃあそのコードを実際のプログラミングでどう使うの?っていうのはわかりにくいわけです。「プログラミングはオブジェクト指向でやるから!」みたいにケムにまかれ、でも実際はオブジェクト指向でやらないのでそんなコードは出番がない。

ということで、変数の使い方をちゃんと提示していたり*1 、ループがどのように難しくなるか説明していたり、クラスの使い方を差分プログラミングとデータの分類にわけて説明したりしてる本が3/19に出るわけですね。

FAQ
Q 電子版はでますか?
A 紙版のあとに出る予定

Q 目次等は?
A もうしばらくお待ちを

*1:変数の使い方は、もうすこし整理できればと思ったけど紙面の都合でな・・・提示は している