Javaを学んでみた

はじめに

JSを学んでいてTSに入る前に静的型言語の理解を深めたく、Javaについて少し学んでみました。

検証はPaizaで!(スッキリわかる本だとDokojavaを使っていますね!)

※7/23追記 Progateで学びました

※7/27追記 スッキリわかるJava入門第3版を購入したので追記しました

✅ゴール
・Javaの理解を深める

✅環境
Windows/XAMPP/MySQL

✅参考教材
Progate

スッキリわかるJava入門 第3版

【初心者向け】Windows10にJavaをインストールする方法
JDKのインストール方法。

ポイント

・Javaはファイルではなくクラスを実行する。また、実行時にmainメソッドを持つクラスしか実行できない(mainメソッドのないクラスは他クラスから呼び出す)。

・「;」セミコロンが必須。JavaScriptは要らなくても処理してくれたりするのでここは注意!

JDKの環境構築

Javaの開発にはコンパイラとインタプリンタを準備する必要がある

JDK(Java Development Kit):開発用
JRE(Java Runtime Environment):稼動用

HelloWorld.java ※ファイル名とクラス名がずれているとコンパイルエラーが出るので注意。

public class HelloWorld{
  public static void main(String[] args){
    System.out.println("こんにちは!!");
  }
}

コンパイルの実行

※この際にHelloWorld.classというファイルが生成される。

javac HelloWorld.java

コンパイルされたJavaを実行

java HelloWorld
>> こんにちは!

Javaの基本

✅Hello World

System.out.println()というのは、「()の中身を出力(表示)せよ」という「命令」※lは小文字のエル

class Main {
  public static void main(String[] args) {
    System.out.println("Hello World");
  }
}

✅Javaの構造

クラス>メソッド>処理部分となる

✅コメント

/* 
  複数行コメント
*/

// 1行コメント

✅変数の定義

型 変数名 = 代入するデータ;で定義。※変数名に使える文字や数字の並びを識別子と呼ぶ。

①データ型を指定する②変数の名前を決める③値更新時は型を付けない④2単語の時はキャメルケース

public class Main{
  public static void main(String[] args){
    final String NAME = "Sato";
    //NAME = "Saito"; // エラー
    System.out.println( NAME + "です" );
    int x = 6;
    x = x * 2;
    System.out.println( x * x ); // 144
    System.out.println("私の好きな記号は二重引用符(\")です");// \はエスケープシーケンス
    int b = 5;
    int a = b = 10; //「=」は右から評価される。結合規則。
    a++;
    System.out.println(a);// 11
  }
}

その他
①変数の定義時に値を代入しなかった場合はデフォルト値が代入される。Stringはnull,intは0,doubleは0.0,booleanはfalse
②名前を使ってはいけない予約語は50語程度。大文字・小文字も区別される。
③final 型 定数名 = 初期値; final付きで宣言された変数は定数と呼ばれる。

✅データ型

int:整数
double,float:少数
String:文字型
boolean:true/false

int型で5/2をすると2になる。
int型とdouble型を合わせて演算すると、自動型変換されてdouble型となる。
キャスト:(変換したいデータ型)値で強制的な型変換ができる。

int number1 = 13;
int number2 = 4;
System.out.println(number1/number2); // 3
System.out.println((double)number1/number2); // 3.25 ※強制型変換でdouble型に変換できる。

Progate Ⅱ

boolean型:真偽値のデータ型

boolean bool = true

自動型変換

public class Main{
  public static void main(String[] args){
    String name = "Sato";
    int ID = 27;
    String nameID = name + ID;
    System.out.println(nameID);// Sato27
    int age = (int)27.6; // 明示的かつ強制的な型変換
    System.out.println(age);// 27
  }
}

キャストによる強制的な型変換も可能。(変数先の型名)式で記述。

✅命令文

public class Main{
  public static void main(String[] args){
    System.out.print("私の名前は");
    System.out.print("Satoです"); // 私の名前はSatoです ※改行されずに出力
    int m = Math.max(2, 4); // 比較して大きい方を出力
    System.out.print(m); // 4
    int r = new java.util.Random().nextInt(50);
    System.out.println(r); // 20
  }
}

System.out.print(); 改行されずに出力

int m = Math.max(1, 2); 大きい方の値を出力

int n = Integer.parseInt(“1”); 文字列を数値に変換する

int r = new java.util.Random().newxtInt(50); 乱数を発生させる。nextInt()の引数には乱数の上限値。

String s = new java.util.Scanner(System.in).nextLine(); キーボードから1行の文字列の入力を受け付ける。Stringをintにすることで数字型にすることも可能。
※どうやらPaizaやDokojavaでは検証できない模様。

✅if/else文

※{}の中身をブロックと呼ぶ。 セミコロン不要。

int number = 12;
if (number < 10) {
  System.out.println("10より小さい");
} else if (number < 20) {
  System.out.println("10以上、20より小さい");
} else {
  System.out.println("20以上");
}

✅switch文

※breakがないと合致したcaseの処理を行った後、その次のcaseの値を実行してしまうので注意。

int rank = 1;
switch(rank){
  case 1:
    System.out.println("金です");
    break;
  case 2:
    System.out.println("銀です");
    break;
  default:
    System.out.println("メダルを獲得できませんでした");
    break;
}

✅while文

int i = 1;
while(i <= 5){
  System.out.println(i);
  i++;
}

✅for文

※continueはその周の処理だけをスキップすることが可能。

for (int i = 1, i <= 5, i++){
  if (i % 3 == 0){
    continue;
  }
  System.out.println(i);
}
//=> 1 2 4 5 7 8 10

✅配列

配列は型宣言時[]で代入時は{}の中に。混同注意!また、定義時に存在しない要素に代入はできない。

int[] numbers = {1,2,3};
System.out.println("私は"+numbers[0]+"番目です");

✅拡張for文

配列の各要素の値を順に代入。Rubyのeach文、JSのmapメソッド的なやつ。

String[] names = {"Sato", "Saito", "Suzuki"};
for(String name: names){
  System.out.println(name);
}
//=> Sato Saito Suzuki

ProgateⅢ

✅メソッド

Javaのファイルを実行すると自動でmainメソッドが実行される。mainメソッドの処理をメソッドに切り分けると、mainメソッドが各メソッドに支持を出し個々の処理を実行するという構造。

定義は「public static 戻り値の型 メソッド名()」。クラスの中に定義。呼び出しはメソッド名()。

public static void メソッド名() {
  実行する処理;
}
class Main {
  public static void main(String[] args) {
    hello("Sato",7);
    int total = goal(3,8);
    System.out.println("今日は" + total + "時間勉強しよう!")
  }
  public static double goal(int a, int b){
    int total = add(a, b);
    return (double)total / 2;
  }
  public static void hello(String name, int time) {
    System.out.println(name + "さんおはよう!"+ time + "時です。");
  }
  public static int add(int a, int b){
    return a + b;
  }
}
//=> Satoさんおはよう!7時です。 今日は5.5時間勉強しよう!

※argsは「arguments」の略で、意味は「引数」。voidは戻り値がないという意味でreturnがないメソッドにはvoidを指定する。

※同名のメソッドは基本定義できないが、引数の方や個数が違う場合はオーバーロードされる。

✅クラス

クラスの定義は「class クラス名」とする。また、頭文字は大文字。ファイル名は「クラス名.java」にしないといけない。
インスタンスの設計図になる。

Javaはファイルではなくクラスを実行する。また、実行時にmainメソッドを持つクラスしか実行できない(mainメソッドのないクラスは他クラスから呼び出す)。

※Main.java

class Main {
  public static void main(String[] args) {
    Person.hello(); // クラス名.メソッド名
  }
}

※Person.java

class Person {
  public static void hello() {
    System.out.println("Hello Java");
  }
}

🙄JavaScriptと違ってクラスとファイルに命名規則があるので、export,import(外部ライブラリに使用)しなくてもファイル間でデータが読み込める。

✅外部ライブラリのimport

※java.langの部分はMathクラスの場所を示す。maxメソッドは引数の大きい方を返す。
※java.lang.クラス名は厳密にはimportしなくとも自動で読み込まれる。=グローバルクラス

import java.lang.Math;
class Main {
  public static void main (String[] args) {
    int max = Math.max(3, 8);
    System.out.println("最大値は" + max + "です");
  }
}
#=> 最大値は8です

入力を受け取る

import java.util.Scanner;

ProgateⅣ ※ここからオブジェクト指向的内容

✅インスタンスの生成

クラス型 変数名 = new クラス名()」で生成。インスタンスは変数に代入、クラス名がそのままクラス型となる。
インスタンスフィールド(インスタンスが持つ情報)の変数は「public データ型 変数名 = 値」で定義。
インスタンスメソッド内でインスタンスフィールドにアクセスするためには「this」を用いる。※クラス内のメソッドの定義の中でのみ使用可能。
コンストラクタ(クラス名と同じにする。)はnewを使ってインスタンスを生成した直後に自動で呼び出される特別なメソッド。

クラスフィールドは「public static データ型 変数名」で定義。「クラス名.クラスフィールド名」でアクセス可能。
同様にメソッドもstaticがついているものはクラスメソッドなので「クラス名.メソッド名()」でインスタンス生成せずに呼び出しも可能。

※Main.java

class Main {
  public static void main(String[] args) {
    Person person1 = new Person("Masaru", "Sato"); // 一人目のオブジェクトを作る。
    person1.hello(); //=> こんにちは、私はSatoMasaruです!
    Person person2 = new Person("Suzuki");
    person2.hello();
  }
}

※Person.java

class Person {
  public static int count = 0; // クラスフィールド。インスタンスの生成回数をカウント
  public String firstName;
  public String lastName;
  Person(String firstName, String lastName) { // クラス名と同じメソッド名にするとコンストラクタになる。
    Person.count++;
    this.firstName = firstName;
    this.lastName = lastName;
  }
  public String fullName() {
    return this.firstName + this.lastName;
  }
  public void hello() {
    String fullName = this.fullName();
    System.out.println("こんにちは、私は" + fullName + "です!");
  }
}

※上記に記載していないがコンストラクタは引数の型や数が違えばメソッド同様定義できる。Javaは渡された引数に合わせて適切なコンストラクタを呼び出し可能。

※this()でコンストラクタからほかのコンストラクタを呼び出し可能(コンストラクタの先頭でしか呼び出し不可)。jsやRubyのsuper()的な奴ですね。

✅カプセル化

使い手に必要ないものを隠してしまうこと。フィールドとメソッドへのアクセスを制限する。

クラスの外部からアクセスできるようにするには「public」を、アクセスできないようにするには「private」を用いて定義(クラス内ではアクセス可能)。

ゲッターは「getフィールド名」で定義。フィールドをprivateにしたうえでクラス外から安全にフィールドの値を取得できるよう値を返すだけのメソッド。
逆にフィールドの値を変更するメソッドをセッターと呼び、「setフィールド名」で定義。

class Main {
  public static void main(String[] args){
    Person person = new Person("Kate",~~~);
    person.setMiddleName("Woody");
    System.out.println(person.getMiddleName()); //=> Woody
  }
}

class Person {
  private String middleName;
  public String getMiddleName(){
    return this.middleName;
  }
  public void setMiddleName(String middleName){
    this.middleName = middleName;
  }
}

ProgateⅤ

✅継承

既存のクラスのフィールドやメソッドを別のクラスに引き継ぐ機能。
継承されるクラスを「スーパークラス」、継承してできる新しいクラスを「サブクラス」と呼ぶ。
class サブクラス名 extends スーパークラス名」として定義(サブクラスでコンストラクタを定義する場合は、スーパークラスのコンストラクタを呼び出さないといけない)。

class Main {
  public static void main(String[] args){
    Computer computer = new Computer(1); //=> スーパークラスのコンストラクタ サブクラスのコンストラクタとprotected
  }
}

class Product {
  private int id;
  protected string memo = "とprotected"
  Product(int id) {
    System.out.println("スーパークラスのコンストラクタ")
    this.id = id
  }
  private Computer owner; // Computer型のownerフィールドを追加。フィールドにインスタンスを持つことが可能。
  public Computer getOwner() { // ゲッターで戻り値がComputer型
    return this.owner;
  }
  public void setOwner(Computer owner){ // セッターでComputer型の引数を受け取る
    this.owner = owner;
  }
}

class Computer extends Product {
  Computer(int id) {
    super(id);
    System.out.println("サブクラスのコンストラクタ" + this.memo)
  }
}

同名のメソッドをサブクラスで定義するとオーバーライドされる。
また、カプセル化は適用されるのでスーパークラスでprivateになっているものにはアクセスできない。要ゲッター/セッター定義。

super.メソッド名()とすることでサブクラスのインスタンスメソッドからスーパークラスのインスタンスメソッドを呼び出し可能。(JSやRubyと同じ。)

ゲッター/セッターを使う代わりにprotectedを用いるとクラス内とサブクラス内からのみアクセスを許すフィールドを作ることが可能。

・抽象メソッド:処理が未定のメソッドを定義するには、メソッドの先頭にabstractをつけて定義。
→サブクラス側でオーバーライドしていない場合、エラーになるのでそのメソッドの定義を強制することができる。
また抽象メソッドを持つクラスを抽象クラスと呼び、クラス名の前にabstractを付ける必要がある。

abstract class Product {
  abstract public void run(int distance); // 処理内容を書かない
}

・多態勢:サブクラスのインスタンスを、スーパークラスのクラス型変数に代入すること

this()とsuper()がこんがらがりそうなので注意!!また、多態性に関しては要深掘り。

躓いた点

・日本語の文字化け 参考

日本語表記はSJISに変更して出力してあげる。

・大文字と小文字は区別される。

おわりに

2時間ほどでJavaの基本的な部分をさらってみました。

ファイル名にも命名規則があったり、静的型言語ということで、大規模な開発の案件に多い理由とTypeScriptが当たり前のように使われてきている理由が少しわかりました。

その他参考

++1と1++の違い

 

 

コメントを残す