mohuneko’s blog

かんばる駆け出しエンジニアのブログです

【Java】Adapterパターン(委譲)【デザインパターン】

駆け出しエンジニアがデザインパターンをもくもく勉強します

 こんな本で勉強しています🌟

目次

Adapterパターンについて

Adapterパターンとは

  • "すでに提供されているもの"がそのまま使えない時に、"必要なもの"とのずれを埋めて、利用できるようにするためのデザインパターンです
  • Wrapper(包む)パターンと呼ばれることもあります
  • クラスによるAdaoterパターン(継承)と、インスタンスによるAdapterパターン(委譲)があります

インスタンスによるAdaoterパターン(委譲)

  • 委譲とは、あるメソッドの処理を他のインスタンスのメソッドに任せることです

サンプルプログラム

  • Adaoterパターンを使って、与えられた文字列を()や*で括る例を取り上げます
  • 各クラスの役割は以下のようになっています
  • ()にACアダプターが交流100Vを直流12Vに変換する例を示しています
名前 役割
Bannerクラス(Adaptee) 提供されているもの (例:交流100V)
PrintBannerクラス(Adapter) 変換装置 (例:アダプター)
Printクラス(Target) 必要なもの (例:直流12V)
Manクラス(Client) 必要なものを使って仕事を行う
(例:直流12Vで動くノートパソコン)

f:id:mohuNeko:20201227110106p:plain

Bannerクラス

  • あらかじめ提供されているクラスです
public class Banner {
    private String string;

    public Banner(String string) {
        this.string = string;
    }
    public void showWithParen() { //文字列を()で括る
        System.out.println("(" + string + ")");
    }
    public void showWithAster() { //文字列を**で括る
        System.out.println("*" + string + "*");
    }
}

Printクラス

  • 必要とされているものを表します
public abstract class Print {
    public abstract void printWeak();
    public abstract void printStrong();
}

PrintBannerクラス

  • 提供されているものと、必要なものの間を埋めるアダプターの役割を担います
  • bannerフィールドでBannerクラスのインスタンスを保持します
    • PrintBannerクラスのコンストラクタで生成しています
  • printWeak、printStringメソッドではbannerフィールドを介してshowWithPare、showWithAsterメソッドを呼びます
  • 継承するのではなく、フィールド経由で呼び出している、ということです
  • printWeakを実行する時に、自分で処理するのではなく、BannerインスタンスのshowWithParenメソッドに委譲しています
public class PrintBanner extends Print {
    private Banner banner;
    public PrintBanner(String string) {
        this.banner = new Banner(string);
    }
    public void printWeak() {
        banner.showWithParen();
    }
    public void printStrong() {
        banner.showWithAster();
    }
}

Mainクラスで動作確認

  • アダプターの役割であるPrintBannerクラスを呼んで文字列を()で括る(=弱く)、**で括る(=強く)操作を行います
  • ここで、Print p = new PrintBanner("Hello");のようにPrintBannerのインスタンスをPrintインターフェース型に代入しています
  • つまり、PrintクラスのprintWeakとprintStrongを使ってプログラミングをしています
public class Main {
    public static void main(String[] args) {
        Print p = new PrintBanner("Hello");
        p.printWeak();
        p.printStrong();
    }
}

Adaoterパターン(委譲)のメリット

  • 既存のクラスに一皮被せて、必要とするクラスを作ることで、必要なメソッドを素早く作ることができます
  • 既存のクラスを修正することなく、必要なクラスを作ることで、再利用し易く、バージョンの互換性を高めることができます
  • 既存のクラスにはバグがないと分かっていれば、Adapterのデバッグに集中して行えば良いため、開発や改修がし易くなります

今日のポイント

  • Adaoterパターン(Wrapperパターン)は、"すでに提供されているもの"がそのまま使えない時に、"必要なもの"とのずれを埋めて、利用できるようにするためのデザインパターンです
  • クラスによるAdaoterパターン(継承)と、インスタンスによるAdapterパターン(委譲)があります
  • 委譲とは、あるメソッドの処理を他のインスタンスのメソッドに任せることです
  • アダプターのフィールドで、提供されている (Bannerクラス) インスタンスを保持することで、提供されているメソッドをフィールド経由で呼びます
  • アダプターのメソッドを実行する時に、自分で処理するのではなく、提供されているメソッドに処理を委譲しています
  • クラスによるAdapterパターンでは、Adapterは継承を使ってAdapteeを利用します
  • インスタンスによるAdapterパターンでは、委譲を使ってAdapteeを利用します

 本日もお疲れ様です😊  

 

 

【Java】Adapterパターン(継承)【デザインパターン】

駆け出しエンジニアがデザインパターンをもくもく勉強します

 こんな本で勉強しています🌟

目次

Adapterパターンについて

Adapterパターンとは

  • "すでに提供されているもの"がそのまま使えない時に、"必要なもの"とのずれを埋めて、利用できるようにするためのデザインパターンです
  • Wrapper(包む)パターンと呼ばれることもあります
  • クラスによるAdaoterパターン(継承)と、インスタンスによるAdapterパターン(委譲)があります

クラスによるAdaoterパターン(継承)

サンプルプログラム

  • Adaoterパターンを使って、与えられた文字列を()や*で括る例を取り上げます
  • 各クラスとインターフェースの役割は以下のようになっています
  • ()にACアダプターが交流100Vを直流12Vに変換する例を示しています
名前 役割
Bannerクラス 提供されているもの(例:交流100V)
PrintBannerクラス 変換装置(例:アダプター)
Printインターフェース 必要なもの(例:直流12V)

f:id:mohuNeko:20201227101106p:plain

Bannerクラス

  • あらかじめ提供されているクラスです
public class Banner {
    private String string;

    public Banner(String string) {
        this.string = string;
    }
    public void showWithParen() { //文字列を()で括る
        System.out.println("(" + string + ")");
    }
    public void showWithAster() { //文字列を**で括る
        System.out.println("*" + string + "*");
    }
}

Printインターフェース

  • 必要とされているものを表します
public interface Print {
    public abstract void printWeak();
    public abstract void printStrong();
}

PrintBannerクラス

  • 提供されているものと、必要なものの間を埋めるアダプターの役割を担います
  • Bannerクラスのメソッド(showWithParen、showWithAster)を継承し、要求されているPrintインターフェースを実装します(printWeak、printStrong)
public class PrintBanner extends Banner implements Print {

    public PrintBanner(String string) {
        super(string);
    }
    public void printWeak() {
        showWithParen();
    }
    public void printStrong() {
        showWithAster();
    }
}

Mainクラスで動作確認

  • アダプターの役割であるPrintBannerクラスを呼んで文字列を()で括る(=弱く)、**で括る(=強く)操作を行います
  • ここで、Print p = new PrintBanner("Hello");のようにPrintBannerのインスタンスをPrintインターフェース型に代入しています
  • つまり、PrintインターフェースのprintWeakとprintStrongを使ってプログラミングをしています
public class Main {
    public static void main(String[] args) {
        Print p = new PrintBanner("Hello");
        p.printWeak();
        p.printStrong();
    }
}

Adaoterパターン(継承)のメリット

  • MainクラスからはBannerクラス、showWithParen、showWithAsterメソッドは見えなくなっています
  • →MainクラスはPrintBannerクラスがどんな実装をされているかを知らずとも、必要なものが手に入ります
  • →Mainを変更しなくても、PrintBannerクラスの実装を変更できることになります

今日のポイント

  • Adaoterパターン(Wrapperパターン)は、"すでに提供されているもの"がそのまま使えない時に、"必要なもの"とのずれを埋めて、利用できるようにするためのデザインパターンです
  • クラスによるAdaoterパターン(継承)と、インスタンスによるAdapterパターン(委譲)があります
  • ACアダプターが交流100Vを直流12Vに変換する、ようなイメージです
  • Mainクラスからは"提供されているもの"は見えなくなっています
  • Mainを変更しなくても、Adapterの実装を変更できるようになっています

 本日もお疲れ様です😊  

 

 

【Java】Iteratorパターン 【デザインパターン】

駆け出しエンジニアがデザインパターンをもくもく勉強します

 こんな本で勉強しています🌟

目次

Iteratorパターン

Iteratorパターンとは

  • ある集合体の要素を、順番にアクセスする方法を提供するパターンです

f:id:mohuNeko:20201226195051p:plain

サンプルプログラム

  • Iteratorパターンを使って、本棚の中に本を入れ、その本の名前を順番に表示するプログラムを実装します
  • 各クラスとインターフェースの役割は以下のようになっています
名前 役割
Aggregate 集合体を表すインターフェース
Iterator 数え上げ、スキャンを行うインターフェース
Book 本を表すクラス
BookShelf 本棚を表すクラス(ConcreteAggregate)
BookShelfIterator 本棚をスキャンするクラス(ConcreteIterator)

Aggregateインターフェース

  • iteratorメソッドの宣言のみ行います
  • このメソッドはIteratorを作成するためのものです
  • 集合体を数え上げたい時に、このiteratorメソッドを使って、Iteratorインターフェース実装クラスのインスタンスを生成します
  • iteratorメソッドはBookShelfクラスで実装します
public interface Aggregate {
    public abstract Iterator iterator();
}

Iteratorインターフェース

  • 次の要素が存在するかどうかを調べるhasNextメソッドと、次の要素を得るnextメソッドを宣言します
  • nextメソッドの戻り値はObject 型です。集合体の要素を一個返すようにBookShelfIteratorクラスで実装します
public interface Iterator {
    public abstract boolean hasNext();
    public abstract Object next();
}

Bookクラス

  • 本の名前を得るgetNameメソッドを宣言します
  • 本の名前は、コンストラクタでインスタンス初期化時に引数で指定しています
public class Book {
    private String name;
    public Book(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}

BookShelfクラス

  • 本棚を表現するクラスです
  • このクラスを集合体として扱う為に、Aggregateインターフェースを実装し、iteratorメソッドの実体を記述します
    • return new BookShelfIterator(this); でBookShelfIteratorクラスのインスタンスを生成して返します
  • Bookクラスのbooksという配列をフィールドに持ちます
public class BookShelf implements Aggregate {
    private Book[] books;
    private int last = 0;

    public BookShelf(int maxsize) {
        this.books = new Book[maxsize];
    }

    public Book getBookAt(int index) {
        return books[index];
    }

    public void appendBook(Book book) {
        this.books[last] = book;
        last++;
    }

    public int getLength() {
        return last;
    }

    public Iterator iterator() {
        return new BookShelfIterator(this);
    }
}

BookShelfIteratorクラス

  • 本棚のスキャンを行います
  • Iteratorとして扱う為、Iteratorインターフェースを実装します
  • nextメソッドでindexを++することで、ループ変数を次に進めます
  • BookShelfクラスのインスタンスbookShelfフィールドに保存します
  • 注目している本をindexフィールドに保存します
public class BookShelfIterator implements Iterator {
    private BookShelf bookShelf;
    private int index;

    public BookShelfIterator(BookShelf bookShelf) {
        this.bookShelf = bookShelf;
        this.index = 0;
    }

    public boolean hasNext() {
        if (index < bookShelf.getLength()) {
            return true;
        } else {
            return false;
        }
    }

    public Object next() {
        Book book = bookShelf.getBookAt(index);
        index++;
        return book;
    }
}

Mainクラスで本棚のスキャンを実行します

  • Iterator it = bookShelf.iterator();では、BookShelfIterator型の変数ではなく、Iterator型の変数に代入しています
import java.util.*;

public class Main {
    public static void main(String[] args) {
        BookShelf bookShelf = new BookShelf(4);  //4冊入る本棚を作成
        bookShelf.appendBook(new Book("Java言語で学ぶデザインパターン入門"));
        bookShelf.appendBook(new Book("独習Java"));
        bookShelf.appendBook(new Book("徹底攻略Java SE 11 Silver問題集"));
        bookShelf.appendBook(new Book("Spring解体新書"));
        Iterator it = bookShelf.iterator(); //本棚をスキャンするためのIteratorインスタンス生成
        while (it.hasNext()) {                    //次の本があるか確認
            Book book = (Book)it.next();  //本を一つずつ調査
            System.out.println(book.getName());
        }
    }
}

Iteratorパターンを使うメリット

  • Main関数のwhileで呼び出すのは、hasNext、nextのIteratorメソッドのみで、BookShelfメソッドは呼び出していません
  • つまり、whileループはBookShelfの実装に依存しない、ことになります
  • よって、BookShelfの実装を変更しても、iteratorメソッドを持っていてhasNextとnextを実装しているインスタンスを返してくれたら(正しくIteratorを返しているので)、Mainメソッドのwhileループは変更しなくても動作する!のです
  • こうすることで、結合度を下げ、クラスを部品として再利用しやすくすることができます

今日のポイント

  • Iteratorパターンは、ある集合体の要素を、順番にアクセスする方法を提供するパターンです
  • 動作を実行するMain関数のwhileループで呼び出すのは、Iteratorメソッドのみで、BookShelfメソッドは呼び出していません
  • これにより、結合度を下げ、クラスを部品として再利用しやすくすることができます

 本日もお疲れ様です😊  

 

 

【Java】UMLについて【デザインパターン】

駆け出しエンジニアがデザインパターンをもくもく勉強します

 こんな本で勉強しています🌟



目次

UMLについて

UMLとは

  • Unified Modeling Languageの略称で、ソフトウェアを形式化するための統一されたモデリング言語です
  • システムを視覚化したり、使用や設計を文章化するために使用します
  • デザインパターンに登場するクラスやインスタンスの関係を表現するためにUMLを使いますので、UMLの基本から勉強します

UMLのクラス図

  • クラス図とは、UMLの一つで、システムの静的な構造・関係性を視覚的に表現するための図です
  • クラス、インスタンス、インターフェースの関係をグラフィカルに表現することができます

例1:継承の関係

f:id:mohuNeko:20201226144433p:plain

  • クラス図では、長方形でクラスを表現します
  • 上から線で区切り、クラス名、フィールド名、メソッド名を書きます
  • 白抜きの矢印はサブクラスからスーパークラスを指定します

例2:実装の関係

f:id:mohuNeko:20201226151730p:plain

  • 白抜き破線の矢印は、実装クラスからインターフェースを指定します
    • この場合、PrintableインターフェースをPrintClassが実装しています

例3:集約の関係

f:id:mohuNeko:20201226151722p:plain

  • 白抜きのひし形矢印は、集約を表します
  • 集約(aggregation)とは、あるクラスの機能を持つクラスのことです
    • あるクラスの機能を、他のクラスにも持たせたい場合に、フィールドとしてそのクラスを持ち、そのクラスのメソッドを呼び出すメソッドを実装します
  • 例えば、上の関係は"家の中に猫が数匹いて、それぞれ色がついている" という関係を表しています。つまり、以下のような関係です

例4:アクセス制御

f:id:mohuNeko:20201226153033p:plain * 上の例は、アクセス制御を明示したクラス図です

表記 意味
+ public:どこからでもアクセス可能
# protected:クラス内および派生したクラスからアクセス可能
- private:クラス内でのみアクセス可能
~ package:パッケージ内でアクセス可能
  • 以下の順番で記述します
    • フィールド:アクセス制御 名前:型 = 初期値
    • メソッド:アクセス制御 名前(引数リスト):返り値
    • 引数リスト:アクセス制御:型 をコンマで区切る*

例5:クラスの関連

f:id:mohuNeko:20201226154227p:plain

  • 関連の名前に▶︎をつけて表記することができます
    • 1番目の図は、ClientがTargetを使用する
    • 2番目の図は、FactoryがPriductを生成する

シーケンス図

f:id:mohuNeko:20201226160549p:plain

  • シーケンス図はUMLの一つで、クラスやオブジェクト間のやりとりを時間軸に沿って表現する図です
  • クラス図が時間によって変化しない静的な関係を表していたのに対し、シーケンス図は、時間によって変化する動的な振る舞いを表します

ライフライン

メソッドの呼び出しとreturn

  • 横方向の黒矢印は、メソッドの呼び出しを表します
    • ここではclientがserverのopenメソッドを呼び出しているということです
  • 横方向の黒破線矢印は、メソッドの戻りを表します
    • ここでは、制御がserverに戻ったことを示しています

今日のポイント

  • UMLとは、ソフトウェアを形式化するための統一されたモデリング言語です
  • クラス図とは、UMLの一つで、システムの静的な構造・関係性を視覚的に表現するための図です
    • クラス、インスタンス、インターフェースの関係をグラフィカルに表現することができます
  • シーケンス図はUMLの一つで、クラスやオブジェクト間のやりとりを時間軸に沿って表現する図です
    • クラス図が時間によって変化しない静的な関係を表していたのに対し、シーケンス図は、時間によって変化する動的な振る舞いを表します
  • シーケンス図では、ライフラインを辿りながら上から順に読んでいきます

 本日もお疲れ様です😊  

 

 

【Java Silver】演算子【初心者】

駆け出しエンジニアがJava Silverに挑戦するためにもくもく勉強します
Java Silverのテストにも出題される内容をまとめていますので、同じような境遇の方の参考になれば幸いです^^


Qiitaの方でも0からアプリケーション実装をしているので、
もし良かったら参考にしてください^^

qiita.com

 こんな本で勉強しています🌟

目次

演算子について

全体的な文法についてはQiitaにまとめていますので参考にしてください

qiita.com

演算子の使い方・注意点

+ 演算子

  • +はオペラントの型によって動作が変化します
  • オペランドいづれかが文字列の場合、+は文字列として結合し
  • 片方がオブジェクト以外の場合、toStringメソッドで文字列に変換して結合します
import java.time.LocalDateTime;

public class Main {
    public static void main(String[] args) throws Exception {
    System.out.println("a"+LocalDateTime.now()); //a2020-10-29T…
    }
} 

- 演算子

  • 左オペラントから右オペラントの値を減算する二項演算子と、正負の値を反転させる単項演算子があります
int num = -5; 
System.out.println(10 * -num); //50

除算と剰余

  • / :除算 (6 / 3 = 2)
  • % : 剰余 ( 10 % 4 = 2)
//NG **整数同士の計算なので結果も整数**
System.out.println( 3 / 4 ); //0

//NG **整数化されるのは演算のタイミング!**
double result = 3 / 4 ;
System.out.println(result); //0.0

//OK **オペラントのいづれかを明示的にdoubleにする
System.out.println( 3d / 4 ); //0.75

型キャスト(型変換)

明示的型キャスト

  • 大きな範囲の値を小さな変数に代入する時は明示的な型キャストが必要です
    • 例:int( -2147483648 〜 2147483647)からbyteやshort(-32768~32767)に代入する場合など
int a = 10;
short b = (short) a; //明示的キャスト
  • 整数の数値リテラルはデフォルトでint型
  • 浮動小点の数値リテラルはデフォルトでdouble型
  • なので、以下の式は本来キャストが必要、、
byte a = 127; //int型をbyte型に代入しようとしてる
  • ですがこの場合、代入値がその型の範囲内であれば、コンパイルエラーになりません
  • 以下の場合ではbyteの範囲 (-128~127) 外にねじ込もうとしていますので、コンパイルエラーです
byte a = 128; //コンパイルエラー

暗黙的キャスト

  • 小さい範囲の値を大きい範囲の変数に代入する時は、Javaが勝手にキャストしてくれます
    • 例:byte 型の変数の値を int 型の変数に代入するなど
  • 数値演算で、演算子の両側のオペラントが同じ型でない場合は、小さい方の型が大きい方の型に自動的に変換されます
int a = 10;
long b = 10;
long c = a + b; //20

今日のポイント

  • 大きな範囲の値を小さな変数に代入する時は明示的型キャストが必要
    • short(-32768~32767)
    • byte (-128~127)
  • 数値演算では、演算子の両側のオペラントが同じ型である必要
  • 両側のオペラントが同じ型でない場合は、小さい方の型が大きい方の型に自動的に変換されます

今日の問題

次のうち、コンパイルエラーになるものはどれでしょうか

int c = 2 * 3L;
② float d = 10.0;
③ short b = 128 + 128; 
  • 正解は①②でした!
  • ①は右オペラントにlong型の接尾子(L)がついているので、左オペラントがlong型に変換されて計算され、
int c = 6L
  • ということになります。よってコンパイルエラーです
  • ②は浮動小数点のデフォルトはdoubleなので、doubleを範囲の狭いfloatにねじ込もうとしています。よってコンパイルエラーです

 本日もお疲れ様です😊  

 

 

【Java Silver】基本データ型・文字列操作2【初心者】

駆け出しエンジニアがJava Silverに挑戦するためにもくもく勉強します
Java Silverのテストにも出題される内容をまとめていますので、同じような境遇の方の参考になれば幸いです^^


Qiitaの方でも0からアプリケーション実装をしているので、
もし良かったら参考にしてください^^

qiita.com

 こんな本で勉強しています🌟

目次

文字列操作、Stringクラスについて

Stringクラスの全体的な文法についてはQiitaにまとめていますので参考にしてください qiita.com

Stringクラス

  • Striingオブジェクトは不変(immutable)なオブジェクトです

不変(immutable)なオブジェクトの定義

  • 全てのフィールドをprivateで修飾
  • オブジェクト内部状態を変更可能なメソッド(setter)を用意しない
  • クラスをfinel宣言し、メソッドのオーバーライドを禁止
  • 内部の可変なオブジェクトをgetterで提供しない
  • java.lang.Stringクラスやjava.io.FIleクラスのインスタンスはimmutableなオブジェクトであり、生成時に与えられた文字列やファイルへのパスを後から変更できません
  • 🌟Stringはimmutableなオブジェクトで、文字列を変更するには新しくインスタンスを作成する必要があります

Stringクラスのメソッド

  • Stringクラスのメソッドは、新しいStringクラスのインスタンスを作って戻します
  • Stringはimmutableなオブジェクトなので、元の文字列が変更されることはありません

charAtメソッド

  • インスタンスが保持している文字列から、引数で指定された位置の一文字を抜き出してもどします
    • 範囲外にアクセスした場合は"IndexOutOfBoundsException"
var str = "猫もふりたい";
System.out.println(str.substring(1, 4)); //もふり

public static void main(String[] args) {
    var mail = "neko@example.com";
    System.out.println(mail.substring(mail.lastIndexOf("@") + 1)); //example.com
    System.out.println(mail.charAt(0)); //n

    for (var i = 0; i < mail.length(); i++) {
     System.out.println(mail.charAt(i)); //全文字抽出
    }
}

indexOfメソッド

  • 引数で指定した文字(文字列の先頭)がどこに存在するかを調べます
    • 存在しない場合は-1が戻される
public class Main {
  public static void main(String[] args) {
    var str = "にわにはにわにわとりがいる";
    System.out.println(str.indexOf("にわ")); //0
    System.out.println(str.indexOf("にも")); //-1
    System.out.println(str.lastIndexOf("にわ")); //6
    System.out.println(str.indexOf("にわ", 3)); //4
    System.out.println(str.lastIndexOf("にわ", 3)); //0
  }
}

replaceメソッド

  • 第一引数の文字列を第二引数で置き換えます
    • 文字の置き換えは先頭から文字列の最後まで処理されます
public class Main {
    public static void main(String[] args) throws Exception {

        String ppap = "pen pineapple apple pen";
        System.out.println(ppap.replace("apple", "banana")); //pen pinebanana banana pen
    }
}

文字列連結

  • +演算子で文字列を連結できます
  • 左右のオペラントが数値と文字列の時は、数値を文字列に変換して結合します
  • しかし+で文字列を結合すると元の文字列、連結する文字列、結果文字列の3個のString文字列を生成しているのでガベージコレクションの増大になります。。
  • 変更可能な文字列を扱うStringBuilderクラスのappendメソッドを使うと、そのオブジェクトの内容が変更されるだけで、新しいインスタンスを生成しないので、インスタンスの生成・破棄が少ないです!
  • mofuを100000回連結して出力すると、StringBuilderが7msで圧勝でした✨
  • StringBuilderはデフォルトで16文字分のバッファを持っています

(参考)qiita.com

public class Main {
    public static void main(String[] args) throws Exception {
        var builder = new StringBuilder();
        for (var i=0;  i<100000; i++){
            builder.append("mohu");
            //result += "mohu" ; 
            }
        var result = builder.toString();
        System.out.println(result);
    }
}

今日の問題①

以下のコードを実行した結果は何が表示されるでしょうか

public class Main {
    public static void main(String[] args) throws Exception {
        
        String ppap = "pen pineapple apple pen";
        changeApple(ppap);
        System.out.println(ppap); 
    }
    private static void changeApple (String str){
        str.replaceAll("apple", "banana");
    }
}
  • 正解は pen pineapple apple pen でした!
    changeAppleメソッドでは、置換した結果の文字列を持った新たなインスタンスを生成し、そのインスタンスへの参照を渡しますが、 元の文字列ppapを変更しません

今日の問題②

以下のコードを実行した結果は何が表示されるでしょうか

public class Main {
    public static void main(String[] args) throws Exception {
        String str = null;
        str += "null";
        System.out.println(str);
    }
}
  • 正解は nullnull でした!
    左右のオペラントが数値と文字列の時のように、参照を持たないことを示すnullを文字列"null"に変換して結合します

 

今日もお疲れ様でした😊

 

 

【Java Silver】基本データ型・文字列操作【初心者】

初心者エンジニア(の末端)がJava Silverに挑戦するためにもくもく勉強します
Java Silverのテストにも出題される内容をまとめていますので、同じような境遇の方の参考になれば幸いです
Qiitaの方でも0からアプリケーション実装をしているので、
もし良かったら参考にしてください

qiita.com

 こんな本で勉強しています

 

今回は、データ型と文字列操作の内容のトピックです
全体的な文法についてはQiitaにまとめていますので参考にしてください qiita.com

リテラル

整数リテラルのルール

  • 先頭が0bであれば 2進数 (0b0111111)
  • 先頭が0であれば8進数 (0413)
  • 先頭が0xであれば 16進数 (0x10B)
  • 桁数の多い数値を見やすくするためにアンダーバーで区切ることができます
    (注)リテラルの先頭と末尾・記号の前後には記述できません
//NG例
int a = _123_;
float b = 3_.14_F;
int h = 0x_52;

文字リテラルと文字列リテラル

  • 文字リテラル(char型)は、'a'のようにシングルクォーテーションでくくります
  • 文字列リテラルは、"abc"のようにダブルクォーテーションでくくります
  • Unicodeの文字符号化形式を使った場合、\uの後に16進数の4桁をつけて、1文字を表すことができます
  • 🌟char型の変数に代入できるのは、'でくくった文字リテラルUnicode文字、0~65535までの数値
  • nullは代入できません(nullは何も参照しないことを表す)
char c = "\u30A2"; //カタカナのア
char d = 65; //アルファベットのA

識別子

  • 識別子とは、変数やメソッド、クラスの名前のことです

識別子の命名規則

  • 予約語を識別子に使うことはできません (for,void,intなど)
  • 使える記号はアンダーバーと通貨記号($)のみ ※$以外の通貨記号は文字化けの可能性あり
  • 数字から始めてはいけません (1abcなど)
  • 識別子内に{}や.は使えません
//OK例
int $a = 123;
float _0 = 3.14;

//NG例
int ${a} = 123;
float a.b = 3.14;

型推論(var)

  • 変数宣言時にJavaがローカル変数のデータ型をいい感じに推測してくれます
  • 'var a = 1;'のように宣言することで、コンパイル時にコンパイラが代入演算子=の右辺から変数の型を予測し、そのデータ型に置き換えます
  • リテラルのみではなく、メソッドの戻り値を受け取る際に、メソッドの定義から戻り値の型推論を行うことができます  ※ラムダ式では推論できない
  • ジェネリクスのダイアモンド演算子(<>)では変数宣言時の型パラメータを参照します。 もし型情報がなかったら、Object型として型パラメータが与えられます
var e = new ArrayList<>();
var e = new ArrayList<Object>();
  • varの型推論ローカル変数の宣言に使えて、フィールド変数には使えません
public class Main {
    //フィールド変数(メンバ変数)
    private String FieldNeko = "tama";
    
    public static void main(String[] args) throws Exception {

        //クラスをインスタンス化してMethodを呼び出す
         new Main().Neko();
    }
    
    public void Neko(){
        //ローカル変数(このメソッド内でのみ有効)では型推論可能
        var neko = 1;
        
        //フィールド変数はメソッド内からアクセス可(this.valueでもOK)
        System.out.println(FieldNeko); //tama
    }
}
  • 引数の型宣言にも型推論が使えません
//NG
public class Neko{
    public void test(var value) 
        System.out.println(value);
}
  • 🌟varの型推論コンパイル時に実行され、代入演算子の右辺から、変数のデータ型が推論され、そのデータ型に置き換えられます
  • 🌟変数宣言以降の行は考慮されません

今日の問題

次のうち、コンパイルエラーにならないものはどれでしょうか

var a;
var b = null;
var c = () -> {};
var d = {1, 2, 3};
var e = new ArrayList<>();
  • 正解はeでした!(Object型として型パラメータが与えられます)

 本日もお疲れ様です