Java理解度浅めメモ
間違いとかありましたらコメントいただけたらと思います。
Javaの説明
Javaの特徴
処理を複数同時にできる
シングルプロセスとマルチスレッドで並行処理を実現している
並行処理を部分的に制御できる
Javaのソースファイルについて
ソースファイル名
publicで修飾されたクラス、インターフェイス、列拳型名のいずれかと一致させなくてはいけない
publicなクラス
publicなクラス、インタフェイス、列拳型はソースファイルに1つしか記述できない
public以外のアクセス修飾子をもつものならば複数記述できる
クラス名で利用できる名前
Unicode文字(英語,日本語(推奨されない)など)
アンダースコア[_]とドル記号[$]
二文字目からは数字も利用可能
型の種類
■プリミティブ型(基本型)
型 | 説明 | 実際の値 |
---|---|---|
byte | 1バイト整数 | (-128〜127) |
short | 2バイト整数 | -32768〜32767 |
int | 4バイト整数 | -2147483648〜2147483647 |
long | 8バイト整数 | -9223372036854775808〜9223372036854775807) |
float | 4バイト単精度浮動小数点数 | (-128〜127) |
double | 8バイト倍精度浮動小数点数 | (-128〜127) |
char | 2バイト文字データ | (¥u0000〜¥uffff) |
boolean | 論理値 | (trueまたはfalse) |
■参照型
参照型は値そのものを保持するのではなく値が置いてある場所を参照することから
参照型と呼ばれる
黒本の問題ででてきて普通に間違えていたのでメモ
int a[] = {1};
int b[] = a;
b[0] = 2;
System.out.println(a[0]); // => 2を返す
byte、short、int、long、float、double、char、booleanを含む
■オブジェクト型(参照型内にあるので参照型である)
String
Date
■配列型(参照型内にあるので参照型である)
char[]
演算
■演算子
説明 | 書き方 |
---|---|
足し算 | + |
引き算 | - |
掛け算 | * |
割り算 | / |
割り算の余り | % |
■演算子の優先順位
public class Main {
public static void main(String[] args) {
System.out.println((7 + 2) * 2 / (2 - 6));
//()で囲まれている演算子が優先される
//処理順①(7 + 2) ②(7 * 2)の結果9 * 2 ③(2 - 6) ④ 18 / -4
}
}
■浮動点少数を含む演算
3 * 6.0 = 18.0になる
→int + double =
intの型はdoubleに変換されて計算される
※暗黙のなんか?
■インクリメント、デクリメント
++a 「増加」してから「計算」
a++ 「計算」してから「増加」
インクリメント、デクリメントの書く場所によって計算結果が異なる場合があるので注意せよ
a=0;
b=++a;
↑先にaが増加して、bにaを代入します。
aの値は1、bの値は1となります
a=0;
b=a++;
↑先にbにaを代入して、その後aを増加させます。
aの値は1、bの値は0となります。
配列
■配列の宣言
アクセス修飾子は省略できる
(書式)
アクセス修飾子 要素のデータ型(intなど) 変数名[];
(例)int a[];
■配列インスタンスの生成
(書式)
アクセス修飾子 要素のデータ型 変数名[] = new 要素のデータ型[要素数(大きさ)];
(例)int a[] = new int[5]
■要素のぶち込み(初期化)
※newがいらなくてもOKになる
(書式)
アクセス修飾子 要素のデータ型[] 変数名 = {要素のデータ0, 要素のデータ1};
(例)int a[] = int {1, 29, 55, 59};
■配列の要素数を見る(これわりとテストでそう)
(書式)
配列の変数名.length;
int n[] = {18, 29, 36, 12};
System.out.println(n.length);
※代入されていない配列の要素数を使うと実行時エラーとなる
黒本の模擬試験で出た。コンパイルエラーじゃないのかって思った。
配列の要素への代入でintで宣言したものに3.5などの値を入れたときキャストしなければコンパイルエラー
定数の宣言
public class Main {
public static void main(String[] args) {
final int a = 45; //定数の宣言
final int b; //定数の宣言
static変数の宣言
アクセス修飾子 static 型名 変数名;
アクセス修飾子とstaticキーワードの記述が逆になってしまってもOK
static アクセス修飾子 型名 変数名;
■コマンドライン引数
(書式)
java クラス名 文字列0 文字列1
条件式、繰り返し文
比較演算子
比較演算子 | 実際の書き方 | 説明 |
---|---|---|
> | x > y | xがyよりも大きい場合にtrueを返す。 |
>= | x >= y | xがyよりも大きいか等しい場合にtrueを返す。 |
< | x < y | xがyよりも小さい場合にtrueを返す。 |
<= | x <= y | xがyよりも小さいか等しい場合にtrueを返す。 |
== | x == y | xとyが等しい場合にtrueを返す。 |
!= | x != y | xとyが等しくない場合にtrueを返す。 |
論理演算子
&&
a(条件式) && b(条件式)
・説明
a と b が共にtrueの時にtrue(それ以外はfalse)|
||
a(条件式) || b(条件式)
説明
a か b の少なくとも1つがtrueの場合にtrue
!
a がtrueの場合にfalse、a がfalseの場合にtrue
if文、else if else
if(条件式){
条件が合致した時の処理(trueのとき);
}
else if(条件式){
ifの条件が合致しなかった時の処理(trueのとき)
}
else{
if else ifの条件が合致しなかった時の処理(falseのとき);
}
■条件式がfalseの場合
public class Main {
public static void main(String[] args){
if(false)
//falseなので実行結果にはaのみ表示されず
//bcはif文関係なく実行される
System.out.println("a");
System.out.println("b");
System.out.println("c");
}
}
実行結果
bc
■if文で出そうな引掛け問題
public class Main {
public static void main(String[] args) {
int a = 0;
int b = 0;
if(++a > 0 || ++b > 0) {
//++aが1になるとtrueとなり||の結果でもtrueと評価されるので++bは評価されず1加算されない
System.out.println("a = " + a);
System.out.println("b = " + b);
}
}
}
実行結果
a = 1 b = 0
■switch
「変数名」のところで変数を指定し、
その変数の値が「case 値: 処理;」の値と等しければその横の処理が実行されるものです。
double型の変数は利用できない!コンパイルエラーとなってしまう!!!
・利用できるもの
char, byte, short, int, Character, Byte, Short, Integer, String
列拳型を戻す式でなくてはいけない
説明は下記
https://ja.wikipedia.org/wiki/%E5%88%97%E6%8C%99%E5%9E%8B
★switch文では式に一致するcaseラベル以降の処理が実行され続けます。
break、ブロックが終了するまで
switch(変数名){
case 値1: 処理1;
break;
case 値2: 処理2;
break;
case 値3: 処理3;
break;
・
・
・
default: 処理;
break;
}
for文
条件式がfalseを返すまでの間ブロック内の処理と条件式の評価を繰り返す
書式
for (初期化式; 条件式; 反復式) {
//処理
}
■無限ループの例
//条件式を省略すると無限ループを起こす
int i = 0;
for (;;) {
System.out.println(i * 3);
}
■for文を用いて配列の要素を取り出す
int[] array = {0, 1, 2, 3};
for (int i = 0; i < array.length; i++) {
//処理
}
■拡張for文
配列、インスタンスの集合から要素を一つずつ取り出すことができる
JDK5.0から導入されたらしい
(書式)
for (変数宣言 : 式) {
//処理
}
(使用例)
for (int e : array) {
//処理
}
■ネスト構造
for文はif文と同じブロック構造なので,ネスト構造にすることができる
for (int i = 0; i <= 100; i++) {
for (int j = 0; ; j++) {
System.out.println(i * j);
if (j >= 20){
break;
}
}
}
ネスト構造内でbreakを使うときは,抜けられるループは1段階だけという点に注意
この場合,breakで抜けるのはjを使っているfor文のみであり、iを使っているfor文を抜け出すことができない
for文のネスト
2つ目のfor文はfalseになるまで実行される
class Main {
public static void main(String[] args) {
int[] array1 = {1, 2, 3};
int[] array2 = {4, 5};
for (int x = 0; x < array1.length; x++) {
System.out.print(array1[x] + " ");
for (int y = 0; x < array2.length; y++) {
System.out.print(array2[y] + " ");
}
}
}
}
実行結果
145245345
while文
条件式がfalseを返すまでの間ブロック内の処理と条件式の評価を繰り返す
書式
while (i < 5) {
//処理
}
do while
do {
System.out.println("実行される。");
num++;
} while (num > 5);
繰り返し処理の制御
オブジェクト指向系
フィールド(インスタンス変数)
宣言方法
アクセス修飾子 型名 変数名;
→順番が違うとダメ
フィールドへのアクセス方法
Food f = new Food("a food");
f.name = "b food";
フィールドのアクセス修飾子がprivateの場合コンパイルエラーになる
■データ隠蔽
属性の公開範囲を制限する[private]
実装の詳細を隠蔽するのは抽象化して扱ったインスタンスのこと
■カプセル化の維持/実現方法
データを隠蔽しアクセスを拒否することでカプセル化を維持できる
アクセス修飾子をprivateにすることでデータ隠蔽を実現できる
変数はprivate,メソッドはpublic
アクセス修飾子 | 説明 |
---|---|
public | すべてのクラスからアクセス可能 |
protected | 同一パッケージ内のクラスからとサブクラスからアクセス可能 |
なし | 同一パッケージ内のクラスからのみアクセス可能 |
private | 同一クラスからアクセス可能 |
■カプセル化の手順
・関係するデータをひとまとめにする
・まとめたデータを必要とする処理をまとめる
■カプセル化のメリット
・外部に公開する情報を制限することで内部実装による変更発生時に影響範囲がすぐに特定できること
・外部から利用するときに複雑なことを考えなくてもよい
■カプセル化について勘違いしてたこと
公開すべきものと非公開にすべきものを区別するという考え方
これは情報隠ぺいの考え方
■static
アクセス修飾子 static 型名 変数名;
→staticとアクセス修飾子は反対になっても問題ない。アクセス修飾子は省略してもOK
staticはインスタンスを作成しなくても利用できる。
staticは唯一、メモリ上に最初から固有で確保されている孤独な変数/メソッドである。
staticをインスタンス化した場合でも、
生成されたstaticを含むオブジェクトは生成元のオブジェクト固有のものではなく、全てのオブジェクト間で共有される。
■staticフィールドへアクセスする方法
クラス名.staticフィールド名
クラス名はインスタンスの変数名でもOK
static フィールドはすべてのインスタンスで共有される
・static変数へのアクセス
クラス名.変数名;
または
オブジェクト名.変数名
・staticメソッドへのアクセス
クラス名.メソッド名();
または
オブジェクト名.メソッド名()
■コンストラクタ
インスタンスが作られたときに実行される!!!!!
コンストラクタの定義のルール
・コンストラクタ名はクラス名と同じでなければならない
・戻り値型は指定できない(voidは使ってはだめ)
・staticも使えない
・インスタンス生成時しか使えない
(書式)
アクセス修飾子 コンストラクタ名(引数) {
//インスタンスの初期化処理
}
■デフォルトコンストラクタ
コンストラクタを明示的に定義していないので
コンパイル時に自動的にデフォルトコンストラクタが追加される
しかしint型の引数を受け取るコンストラクタが定義してあるため
デフォルトコンストラクタは追加されない
Sampleクラスがインスタンス化されたとき(Sample s = new Sample();)引数なしのコンストラクタを呼び出しているためコンパイルエラーとなる
public class Sample {
private int a;
/**public Sample {
}*/
public Sample(int a) {
this.a = a;
}
public void setA(int a) {
this.a = a;
■this()について
this()はコンストラクタからオーバーロードした別のコンストラクタの
呼び出しをする際に利用する
・注意
this()はコンストラクタブロック内の先頭行のみでしか利用できない
コンパイルエラーとなってしまう
public class Sample {
private int a;
private int b;
public Sample() {
this(10);
//引数なしのコンストラクタブロックからオーバーロードされた
//int型の引数ありのコンストラクタを呼び出す
}
public Sample(int a) {
this.a = a;
//自クラスのインスタンスを指す
this.b = -5;
//自クラスのインスタンスを指す
}
}
■オーバーロード
オーバーロードとは同一クラス内でメソッド名が同一で引数の型、数、並び順が異なるメソッドを複数定義することを言います。
例えば、会員登録を行う機能で、名前と国名を登録させたいとします。国名を入力しなかった会員は国名:日本で登録します。この場合、toroku、torokuJAPANというように別のメソッド名を付けるのではなく、おなじ登録機能であるため、同じメソッド名としたい場合があります。
その際、toroku(String name,String country)、toroku(String name)というように同じ名前のメソッドを引数の数を変えて作成します。Javaはメソッドの引数の型、数、並び順が異なる場合、それぞれを異なるメソッドとして扱います。これがオーバーロードの機能です。
参考:
http://www.javaroad.jp/java_class8.htm
■シグニチャ
・メソッド名と引数のセットのことをシグニチャと呼ぶ
シグニチャにはメソッド名、引数の数、引数の型と引数の並びが含まれる
・オーバーロードしたメソッドの定義
・メソッド名が同じで引数の数が異なる場合はOK
・例
int doMethod(int a, int b, boolean b) {
//処理
}
・メソッド名と引数が同じで戻り値の型が違うだけのメソッドは多重定義できない
→コンパイルエラーとなる
・OKなパターン
public class Sample {
void doMethod() {
//処理
}
String doMethod(int a) {
return "ABC";
}
}
継承
「子クラス」から「親クラス」へのアクセス
「子クラス」から「親クラス」の「メンバ変数」や「メソッド」を使用するには次のように記述します。
class 子クラス名 extends 親クラス名{
super.親クラスのメンバ変数;
super.親クラスのメソッド;
}
※「super.」は省略可。
但し、子クラスに親クラスと同じ名前のメンバ変数やメソッドがある場合は、
明示的に「super.」を付加しないと自クラス(子クラス)のものが使用されます。
※親クラスから子クラスへのアクセスはできない
■継承で引き継がれないもの
1:コンストラクタ
2:privateなメソッド、フィールド
■継承した時のコンストラクタの実行
①サブクラスのコンストラクタの呼び出し
②スーパークラスのコンストラクタの呼び出し
③スーパークラスのコンストラクタの実行
④サブクラスのコンストラクタの実行
注意点
スーパークラス、サブクラスどちらともコントラクタを書いていないとNG
スーパークラスのコンストラクタが定義されていたりするとNG
なお同じクラスに定義している他のコンストラクタを呼び出すには
this()を使う
■スーパークラスのコンストラクタの呼び出し
super(これもthis()と一緒で一番上にかかなければNG)
スーパークラスのメソッドに処理を頼むとき
super.スーパークラスのメソッド名
super.フィールド名
■オーバーライド
サブクラスでスーパークラスのメソッドを再定義すること
メソッドをオーバーライドする条件
・メソッドのシグニチャがスーパークラスのものと同じであること
・戻り値の型がスーパークラスのメソッドと同じか、サブクラスであること
・メソッドのアクセス制御がスーパークラスと同じかゆるいこと
・シグニチャが異なるメソッド定義はオーバーロードになる。
※シグニチャ メソッド名、引数の数、引数の型と順番が含まれる
■this
自クラスのインスタンスを指す
時クラスのインスタンスを示しフィールドの参照に利用する
this.変数名 = 変数名
→フィールドなどにぶち込んだりして利用してた。
抽象クラス、メソッド
■抽象化
共通部分だけを抽出し、それ以外を無視することを抽象化という
サッカー選手のAさん、Bさん、Cさんをサッカー選手として扱うのは抽象化。
対象から注目するべき要素を抜き出しそれ以外を無視することによって複雑なことを簡単にとらえるという考え
つまりサッカー選手という要素を取り出しサッカー選手であるAさん、Bさん、Cさんを無視する
なお抽象化してオブジェクトを扱うことをポリモーフィズムと呼ぶ
■ポリモーフィズムとは
サブクラスのインスタンスをスーパークラスの参照変数に代入して使用
引数を受け取ったインスタンスがクラスによって違う振る舞いをする
■特徴
・どの型で扱っていたとしても、実際に動作するのはインスタンスそのもの
・「使う側」のクラスは「共通化して扱える型」だけを知っていれば「使われる側」の具体的な違いを意識することはない
・そのため、「使う側」が「使われる側」の変更の影響を受けることはない
・影響を受けるのは共通化して扱える型が変ったときのみ
Worker pg = new Programmer();
Worker ne = new NetworkEngineer();
■なぜポリモーフィズムが必要なのか
共通のメソッドを呼び出すが、オブジェクトによってその機能を変化させる
実はこの機能がないと各サブクラスのインスタンスを別々に生成しないといけません。
変更されたクラスを使うクラスに変更の影響が及ばない
ポリモーフィズムに関係が深いものは抽象化、情報隠蔽
■情報隠蔽
公開すべきものと非公開にすべきものを区別して扱う
クラス宣言できる修飾子はpublicかデフォルト
公開部分はインターフェイスとして定義する
・ポリモーフィズムによって実際に動くインスタンスの型を隠蔽
・公開メソッドを集めたインターフェイスを用意する
・パッケージ宣言をする
・コンストラクタをprotectedにする
■interfaceに定義できるフィールドの修飾子
※interfaceは情報隠蔽
・static
・public
・final
interfaceに定義する抽象メソッドの修飾子
public
abstract
public interface Sample {
void hello(String str);//セミコロンで終わる
■interfaceの特徴
・メソッド宣言のみできる
抽象メソッド、クラスはインスタンス化できない/継承するのもである
→抽象メソッドのみ、具象メソッドは定義できない
・クラスは一度に複数のinterfaceを継承できる(implements)
→多重実現・interfaceは既存のinterfaceを継承できる(extends)
必要なのは、メソッド名、引数、戻り値の型だけである。
メソッドではpublicとabstractしかツカエヌ
マタハ、ナシデ
[修飾子] interface <インタフェース名> {
データ型 変数名 = 値;
修飾子 戻り値のデータ型 メソッド名(引数の型宣言);
}
■抽象クラス
抽象メソッドは必ずオーバーライドしなくてはいけない(コンパイルエラーとなる)
抽象クラスは抽象メソッド、具象メソッドどちらも定義できる
抽象メソッド、クラスはインスタンス化できない/継承するのもである
実現しているinterfaceメソッドを実装する必要はない
インスタンスは生成できない
メソッドをすべて実装しなくてもよい
・抽象クラス及び抽象メソッドの書式
abstract class クラス名 {
abstract 戻り値 メソッド名(引数リスト) ;
}
abstract修飾子で指定可能な構成要素
メソッド
クラス宣言
インターフェイス宣言
■abstract
抽象メソッドは自分で定義しなくてはいけない
暗黙的には修飾されない
■パッケージ
名前空間を提供する
アクセス制御を実現する
クラスの分類を可能にする
※引っかけでよくソースファイルの1行目に記述するとあるがパッケージ宣言の前にコメントは許されている
まとめ
まだまだ理解度が低くBronzeの資格がとれたとしても基礎の勉強がまだまだ必要
だということを感じた。。
やばいところ
・情報隠蔽
・ポリモーフィズム(多様性)