覚えきれない部分をまとめてみました。
アクセス修飾子 | 意味 |
---|---|
public | すべてのクラスからアクセスできる。 |
protected | 同一パッケージに属する場合は継承関係に係わらずアクセス可能。 異なるパッケージに属する2つのクラスが継承関係にあるとき、publicと同じ働きをする。 異なるパッケージに属する2つのクラスが継承関係にないとき、privateと同じ働きをする。 |
default | 同一パッケージ内のみアクセスできる。 |
private | 同一クラス内のみアクセスできる。 |
クラス名が重複するのを避けるため、コンパイラやJVMは「パッケージ名.クラス名」の完全修飾クラス名で扱っている。
パッケージはディレクトリ構造とマッピングしていて、
例えば「jp.co.xxx.sample」という完全修飾クラスは[jp]フォルダ内の[co]フォルダ内の[xxx]フォルダに存在するsampleクラスということになる。
本来、staticなメソッドやフィールドは「クラス.フィールド名」や「クラス.メソッド名」
の書式で、どのクラスに定義されているものなのかを明示しなければならない。
これをフィールドやメソッド名だけで省略表記できるようにしたのがstaticインポート。
staticインポート宣言は以下のように完全装飾クラス名で記述する。
Java
import static jp.co.xxx.sample.num;//sampleクラスのstaticなnum変数をインポート。
import static jp.co.xxx.sample.print;//sampleクラスのstaticなprintメソッドをインポート。
Java
package pake1;
public class p1main {
public static int num1 = 100;
}
Java
package pake1;
public class p1main2 {
public static int num2 = 200;
}
Java
package pake2;
import static pake1.p1main2.*;
import pake1.p1main;
public class p2main {
public static void main(String[] args) {
System.out.println(p1main.num1);//100
System.out.println(num2);//200
}
}
クラス内に複数定義されたメソッドのうち、どのメソッドから処理を始めるのかを決めなくてはならない。
処理を始めるためのメソッドのことをエントリーポイントという。
Java
public static void main(String[] args){
//処理
}
このうちプログラマが自由に決められるのは引数名の「args」の部分のみ。
エントリーポイントの引数にはString配列型だけでなく、可変長引数のString型も受け取ることができる。
Java
// 引数名を変えた例
public static void main(String[] hogehoge){ //処理 }
// 可変長引数のString型に変えた例
public static void main(String... args){ //処理 }
プリミティブ型と参照型の違いについては以下の記事にまとめた。
8進数を表す場合は、「067」のように「0」を接頭辞として付ける。
16進数であれば「0x9F」のように「0x」を接頭辞として付ける。
2進数であれば「0b01010101」のように「0b」を接頭辞として付ける。
桁数の多い数値リテラルの見やすさを向上するためにアンダースコア「_」を使った数値表記がJava SE7から導入されている。
表記方法については以下の制約がある。
型 | 説明 |
---|---|
char型 | 文字リテラルは’c’のようにシングルクォーテーションで囲むこと。 |
String型 | 文字列リテラルは”str”のようにダブルクォーテーションで囲むこと。 |
JavaはUnicodeを標準の文字コードとしている。
javaでは’\u30A2’のように「\u」の接頭辞の後ろに16進数で4桁を付け、シングルクォーテーションで囲む。
char型の変数に0~65535までの数値を代入することができる。
使わなくなったオブジェクトを自動的に破棄してくれるJavaの便利な機能。
不要になったゴミ(ガーベジ)と回収(コレクション)するのでガーベジコレクションと呼ばれる。
強制的にガーベジコレクションを呼ぶためには以下の記述をする。
Java
Object = null;
System.gc();
ガーベジコレクションの対象は、参照されなくなったインスタンス。
コンパクション…インスタンスの破棄を繰り返すことで細切れになったメモリをまとめ、大きな空間を確保する機能。
int型の数値をshort型やbyte型に代入する場合、その値が型の範囲内であれば、コンパイルエラーにはならない。
数値を演算するとき、左右のオペランドは同じ型でなければならない。
もしオペランドの型が異なる場合は、小さいほうの型は大きい方の型に自動的に変換される。
※オペランドとは演算対象を指す。
同一性とは、複数のオブジェクトが同じインスタンスを参照していること。(同値性を兼ねる。)
同一性であるかどうかは「==」で演算子で判定する。
同値性とは、インスタンスは異なるが、同じ値を持っていること。
同値性であるかどうかはequalsメソッドを使って確認する。
但し、Objectクラスに定義されているequalsメソッドは同一性を確認するものになっている。
何を以って同値と判定するかはプログラマに委ねられているので、オーバーライドして確認する。
Stringのインスタンスは、文字列リテラルを記述するだけで作られる。
Java
String a = 'sample';
String b = 'sample';
System.out.println(a == b); //trueが返る。
これはコンスタントプールという仕組みがあるため。
同じ文字リテラルは定数値としてインスタンスとは異なる定数用のメモリ空間に作られ、そこへの参照が
String型変数に代入される。
但し、以下はfalseとなる。
Java
Stirng a = new Stirng("sample");
String b = 'sample';
System.out.println(a == b); //falseが返る。
new演算子を使ってプログラマが明示的に「新しいインスタンスを作る」場合、その都度インスタンスが作られ
それぞれが異なる参照を持つ。
そのためオブジェクトaはインスタンス用のメモリ空間に作られたStringインスタンスへの参照が渡され、
オブジェクトbはコンスタントプールによって定数用のメモリ空間に作られたStringインスタンスへの参照が渡される。
例えnewしたとしても、後から値を代入して結果的に文字列が同じになる場合はコンスタントプールを使用する。
Java
public static void main(String[] args) {
String a = "aaa";
String b = new String("");
b = "a"+"a"+"a";
System.out.println(a == b);//同一性の確認(trueが返る)
System.out.println(a.equals(b));//同値性の確認(trueが返る)
}
for文は、初期化文、条件文、更新文と3つの繰り返し処理で構成されている。
中カッコを省略して記述した場合、繰り返しの対象となるのは、構文が開始された次の1行のみとなる。
次のコードは「A」を5回出力した後、「B」を1回出力する。
Java
int cnt = 0;
while (cnt++ <5)
System.out.println("A");
System.out.println("B");
但し、do-while文で中カッコを省略した場合は、文を複数記述するとコンパイルエラーとなる。
Java
int cnt = 0;
do
System.out.println("A");//ここでコンパイルエラー。
System.out.println("B");
while (cnt++ <5);
Java SE5から可変長引数が導入された。
return文の後ろの処理は実行できない。
return文を実行した後に何らかの処理をするようなコードを記述するとコンパイルエラーとなる。
Java
void sample(int num){
return;
System.out.println(num);//ここでコンパイルエラー。
}
staticで修飾されたフィールドやメソッドは「static領域」と呼ばれる領域に配置される。
それ以外のものは「ヒープ領域」と呼ばれる領域に配置される。
インスタンスが生成されるときは、ヒープ領域ににあるクラス定義に従ってインスタンスが生成される。
次のコードはオーバーロードの条件を満たしている。
2つのint型を渡した呼び出しは、両方適用出来てしまう。
このような場合、JVMはどちらを呼び出していいかを判断できなくなってしまう。
そのため、JVMは「あいまいなメソッド呼び出し」としてコンパイルエラーを発生させる。
Java
public class test {
public static void main(String[] args) {
test ts = new test();
System.out.println(ts.calc(2, 3));//ここでコンパイルエラー。
}
double calc(double a,int b ){
return (a+b)/2;
}
double calc(int a,double b ){
return (a+b)/2;
}
}
すべてのコンストラクタで一部だけ共通の処理がしたい!そんなときは初期化ブロックを用いる。
★1行目にsuper()で2行目にthisが来るパターン。
Java
public class Kodomo extends Oya{
Kodomo(int x){
super();
this(100,200);//コンパイルエラー。
}
Kodomo(int x,int y){
}
}
★1行目にthisで2行目にsuper()が来るパターン。
Java
public class Kodomo extends Oya{
Kodomo(int x){
this(100,200);
super();//コンパイルエラー。
}
Kodomo(int x,int y){
}
}
フィールドはprivateにする。
フィールドを扱うメソッドは必要なものをpublicにする。(必ずしもすべてをpublicにする必要はない。)
Java
class A{
String val = "A";
void print(){
System.out.print(val);
}
}
class B extends A{
String val = "B";
}
Java
public class Main{
public static void main(String[] args){
A a = new A();
A b = new B();
System.out.print(a.val);//A
System.out.print(b.val);//A
a.print();//A
b.print();//A
}
}
答え:AAAA
フィールドを参照した場合は、変数の型で宣言された方を使う。
メソッドを呼び出した場合は、メソッド内の指示に従う。
MainクラスでA型のオブジェクトとして変数aがAクラスのインスタンス、
変数bがBクラスのインスタンスを持っています。
Bクラスにもval
フィールドやAクラスから継承したprint
メソッドがありますが
b.val
やb.print
を実行すると、「A」が出力されます。
これはなぜかというとval
フィールドやprint
メソッドを親クラスであるAクラスで定義しているためです。
親クラスと子クラスで同名のフィールドが定義されている場合、どちらが使用されるかは宣言時の型によって決まります。
変数bはA型なので、b.val
やb.print
を実行すると「A」が出力されるというわけです。
インターフェース内のメソッド宣言ではヘッダ部分のみしか宣言できない。
処理本体を書くとコンパイルエラー。(中括弧{}含む。)
但し、Java SE8から追加されたstaticメソッド及びdefaultメソッドは処理本体を記述できる。
Java
public interface A {
void methodA(int x);//OK
void methodB(int y){//この宣言はコンパイルエラー。
}
static int methodC(int z){//staticメソッドはOK
return z;
}
default int methodD(int o){//defaultメソッドはOK
return o;
}
}
抽象クラスとは、抽象メソッドと具象メソッドを保持できるクラスのこと。
抽象メソッドには以下の制約がある。
抽象クラスもインターフェースと同じくメソッドの宣言ではヘッダ部分のみしか宣言できない。
処理本体を書くとコンパイルエラー。(中括弧{}含む。)
Java
public abstract class aaa {
abstract void methodA(int x);//OK
abstract void methodB(int x){//コンパイルエラー。
}
}
例外処理は以下にまとめた。
catchブロック内にreturnがあってもfinallyブロックが先に処理される。
処理される順番はcatch→finallyだけど、
returnによって呼び出し元に制御が戻る前にfinallyブロックが先に処理されるということ。
Java
try{
throw new NullPointerException();
} catch (NullPointerException e){
return "A";
} finally{
System.out.println("B");
}
return "C";
答え:BA
catchブロックとfinallyブロックの両方がreturnをするときはfinallyの値で上書きされる。
(returnするときに戻り値を格納する専用の変数があり、catchブロックの処理を実行すると戻り値の値が10、
finallyブロックの戻り値の値が20に変わるため。)
Java
try{
throw new RuntimeException();
} catch (RuntimeException e){
return 10;
} finally{
return 20;
}
答え:20
finallyブロックで値を変更しても変数valの値が変わるだけ(20になるだけ)で、戻り値用の変数の値は変わらない。
但し、これはプリミティブ型の場合の話で、参照型の場合は、戻り値用の変数も同じインスタンスを持つため、finallyブロックで値を書き変えることが可能。
Java
int val = 0;
try{
String[] array = {"A","B","C"};
System.out.println(array[3]);
}catch (RuntimeException e){
val = 10;
return val;
}fially{
val += 10 ;
}
答え:10
finally文が実行されないのは以下のどれかのパターンに該当するとき
3行目:要素が0なので0が出力される。
4行目:存在しない要素1にアクセスしたので「java.lang.ArrayIndexOutOfBoundsException
」が発生する。
Java
public static void main(String[] args) {
System.out.println(args.length);
System.out.println(args[0]);
}
インスタンスが生成されるタイミングではなく、クラスがロードされたタイミングに一度だけ呼び出される初期化ブロック。
staticイニシャライザを使用することでstatic変数の初期化が可能になる。
Java
static{
salaryMap.put(SampleConst.PRESIDENT,SampleConst.PRESIDENT_SALARY);
salaryMap.put(SampleConst.DIRECTOR,SampleConst.DIRECTOR_SALARY);
salaryMap.put(SampleConst.EMPLOYEE,SampleConst.EMPLOYEE_SALARY);
}
可変なオブジェクトのことを「mutable(可変)」という。
不変なオブジェクトのことを「immutable(不変)」という。
Stringオブジェクトは不変なオブジェクトである。
メソッド名 | 意味 |
---|---|
indexOf() | 引数で指定した文字が文字列のどの位置に存在するかを調べるメソッド。 |
substring() | 指定した引数を添え字として任意の文字列を抽出するメソッド。 |
replace() | 文字列の先頭から末尾まで、指定された文字でヒットすればそれに置き換える。 |
replaceAll() | 置換した結果の文字列を持った新しいStringインスタンスを生成し、そのインスタンスへの参照を返す。 |
trim() | 引数で指定した文字列の前後にある空白を除去するメソッド。空白としてspace、tab、改行などが対象となる。 |
startWith() | 指定した引数で始まっているかを真偽値で返すメソッド。 |
endWith() | 指定した引数で終わっているかを真偽値で返すメソッド。 |
StringBuilderのappnedメソッドはオーバーロードさまざまな種類の引数を受け取ることができる。
受け取れる型 | 要点 |
---|---|
プリミティブ型 | プリミティブ型の値は全て文字列型に変換される。 真偽値のtrueなら”true”、整数値の10は”10″になる。 |
String型 | StringクラスのスーパクラスであるCharSequence |
char配列 | – |
オブジェクト | toStringメソッドはObjectクラスに定義されたものが呼び出されるので オーラーライドする必要がある。 |
insertメソッドとdeleteメソッドの例※指定したindexに値が挿入(削除)され後ろがずれる。
Java
StringBuilder sb = new StringBuilder("ABCDE");
sb.insert(2,"o");
System.out.println(sb);//ABoCDE
sb.delete(2,3);
System.out.println(sb);//ABCDE
deleteメソッドはindexを渡して値を削除するところに気をつける。indexの2番目から1文字消したいからといって下のようなコードを記述すると実行時エラーになる。
Java
sb.delete(2,1);
LocalDateクラスは日付を扱うためのクラス。
メソッド名 | 意味 |
---|---|
now() | 現在の日時でインスタンスを生成する場合 |
Of() | 日付を指定してインスタンスを生成する場合 |
parse() | 文字列形式をLocalDateクラスに変換する場合DateTimeFormatterを指定することもできる。 |
Java
LocalDate a = LocalDate.now();//「2017-07-17」
LocalDate b = LocalDate.of(2017,7,17);//「2017-07-17」
LocalDate c = LocalDate.parse("2017-01-17");//「2017-07-17」
LocalDate d = LocalDate.parse("2017-01-17",DateTimeFormatter.ISO_LOCAL_DATE);//「2017-07-17」
LocalTimeクラスは時間を扱うクラス。
Java
LocalTime t1 = LocalTime.now();//00:52:15.417
LocalTime t2 = LocalTime.of(0,1,2);//00:01:02
LocalTime t3 = LocalTime.parse("00:10:20");//00:10:20
LocalTime t4 = t3.plusHours(12);//t3の値は「00:10:20」のまま。
//t4の値は「12:10:20」になる。
Durationクラスは時刻の差を扱うクラス。
Durationは”期間”という意味。
betweenメソッドは2つの日時の差を計算し、Durationのインスタンスとして戻すメソッド。
periodクラスは日付の差を扱うクラス。
以上で記事の解説はお終い!
もっとJavaやSpringを勉強したい方にはUdemyがオススメ!同僚に差をつけよう!
View Comments
7章の問8の解説
クラスBはメソッドは定義されていませんよね…?
あとメインメソッドの解説のところ
Stringが小文字だと思います
wataru様
ご指摘ありがとうございます。
読み返したら問題文と関係ない説明文になってました(´;ω;`)
解説文を修正いたしました。
また、stringと小文字になっていた箇所も大文字に修正しました。
頭脳一式さん
上記でゲストログインしていたwataruです。
記事の修正ありがとうございます。いつも参考にしております!
これからも応援しています!