はじめに
普段PHPを業務で使っているエンジニアがJavaを勉強するために
プロになるJavaを読んで、その中でもデータ構造や型の部分で個人的にPHPと違うなと思った個所や特に覚えておいた方がいいなと思った個所をまとめました。
4.2.2 基本型と参照型
String型だけ大文字で始まっていて、他の型は小文字で始まっています。
int型やdouble型など小文字で始まっている型を基本型 (またはプリミティブ型)といいます。
全部で8つありますが、ここに挙げた4つは必ず押さえておきましょう。
では基本型ではないString型は何になるかというと、クラスというものになります。
クラスはJavaで機能をまとめるための基本的な仕組みです。クラス以外にも基本型ではない型はありますが、そういった基本型ではない型を参照型といいます。
クラスであるString型の値には、toUpperCaseメソッドなどのメソッドを呼び出すことが出来ました。
参照型にはメソッドを持ちますが、基本型にはメソッドはありません。
今まで触ってきたPHPは静的型付け言語なので、Javaの型の概念はしっかり覚えておきたい。
8.1.1 List
jshell> /v names
| List<String> names = [yamato, kis, sugiyama]
これはString型の値を格納するListということを表します。このように、扱う型を「<」と[>]で囲んで指定する書き方はジェネリクスというもので、詳しくは後程解説します。データ構造の型では、このようにジェネリクスによってそのデータ構造で扱う型を指定します。
ふむふむ
8.1.5 ラッパークラス
ジェネリクスではint型などの基本型を指定できません。int型を扱うListの変数を定義しようとすると次のようなエラーになってしまいます。
jshell> List<int> points
|エラー:
|予期しない型
| 期待値: 参照
| 検出値: int
|List<int> points;
| ^-^
参照型を期待したのにint型が来た、というエラーです。ジェネリクスには参照型、つまりオブジェクトの型を指定する必要があります。しかしながら、整数などの基本型を扱いたい場合はよくあります。そこでラッパークラスとして、基本型の値を参照型として扱うためのクラスが用意されています。ラッパークラスの名前は、対応する基本型の名前を大文字で初めて省略しない名前になっています。
基本型 | ラッパークラス |
---|---|
int | Integer |
double | Double |
boolean | Boolean |
char | Character |
また、基本型はメソッドを持てないので、基本型に関するメソッドもラッパークラスに用意されています。例えば、文字列を解析して数値を得るような処理です。
jshell> Integer.parseInt("123")
$20 ==> 123
8.2 配列
Javaのデータ構造として言語に含まれているものに配列があります。配列もListと同様に型の値をまとめて扱う仕組みですが、Javaの言語に組み込まれているため、特別な記述が用意されています。また、Listでは扱えなかった基本型も直接扱えます。ArrayListの「Array」は配列を表す英単語で、内部では配列を扱って値を格納しています。
読んでいて思ったのですが、List使わずに配列でいいような気がしてきました...
おそらくそんな事でもないのでしょう。
8.3 レコードで違う種類の値を組み合わせる
ここまで出てきたListや配列では、同じ種類の値をまとめてあつかうことができました。ここでは違う種類の値をまとめて扱うレコードについて見ていきます。
ほう。さっそくさきほどの疑問が解消されそう。
8.3.1 違う種類の値をListにまとめて扱う
まずはString型の受験者名と科目名、int型の点数をListでまとめて扱ってみましょう
jshell> var exam = List.of("kis", "math", 80)
| student ==> [kis, math, 80]
おー。なるほどもしかしてListは要素ごとに異なる型の値を代入できるけど、配列はできないのかな。
jshell> int[] exam = {"kis", "math", 80}
| Error:
| incompatible types: java.lang.String cannot be converted to int
| int[] exam = {"kis", "math", 80};
| ^---^
| Error:
| incompatible types: java.lang.String cannot be converted to int
| int[] exam = {"kis", "math", 80};
|
そうっぽい。というか、宣言するのに型指定がいるからそりゃそうか。
8.3.2 違う種類の値をまとめて扱うレコードを定義する
項目に名前を付けて型を指定して扱えると便利です。こういった場合に使えるのがJava 16から正式導入されたレコードです。それではString型の受験者名と科目、int型の点数を扱うためのレコードを作成してみましょう。最後の中カッコを忘れないでください。
jshell> record Exam(String name, String subject, int score) {}
| 次を作成しました。: レコードExam
うおおお!これですよこれ!
これが欲しかったんです。PHPだと同じ事をしようとすると一々クラス作ってあげる必要があったから(自信ない)これはめちゃくちゃうれしい。
8.3.3 レコードのオブジェクトを生成する
それではExamレコードのデータを作ってみましょう。
jshell> var e1 = newExam("kis", "math", 80)
e1 ==> Exam(name=kis, subject=math, score=80)
これでExamのレコードが出来ました。レコードのデータもオブジェクトになります。
~~ 割愛 ~~
レコードオブジェクトからコンポーネントの値を取ってくるには、コンポーネント名のメソッドを呼び出します。nameコンポーネントの値を取ってくるには次のようにします。
jshell> e1.name()
$32 ==> "kis"
あーーーーすごい(語彙)これですこれ。気持ちい~~~~
そして、それぞれのコンポーネントに型を指定しているので、そのまま適切なメソッドを呼び出せます。
jshell> e1.name().toUpperCase()
$34 ==> "KIS"
ああ...(昇天)
なんで今までJavaを使わなかったんでしょうか。。
8.4.1 Map
Mapはキーと値を結びつけるデータ構造です。例えば「apple」に対して「りんご」、「grape」に対して「ぶどう」を結びつけるといった具合です。
~ 割愛 ~
それではMapを使って「apple」や「grape」の紐づけを再現してみましょう。Map.ofメソッドでキーと値を設定したMapを作ることが出来ます。
jshell> var fruits = Map.of("apple", "りんご", "grape", "ぶどう")
fruits ==> (grape=ぶどう, apple=りんご)
getメソッドでキーを指定して値を取れます。
jshell> fruits.get("grape")
$36 ==> "ぶどう"
おーー。PHPだと連想配列使ったり、array_map使ったりしますよね。
まとめ
やっぱりJavaは静的型付け言語なだけあって何か定義するにしても必ず型を意識しないといけないようになっていて、素晴らしいと思いました。