Going my way

いいなと思ったことをメモしていきます。

基本過ぎていまさら聞けないJavaの盲点集


Advertisements


インターフェースは多重継承ができる

Javaではクラスの多重継承は禁止されているが、インターフェースの多重継承は可能である。
インターフェース内で変数の宣言はできない。フィールドは全て定数になる。

(例)

package test;

interface Man{
	public static final String He = "男";
	public abstract void Tinko();
}

interface Woman{
	//interface内の変数は暗黙的にpublic static finalとなる。定数の初期化は必須である。
	String She = "女";
	
	//インターフェースのメソッドは暗黙的にpublic abstraceで就職される
	void Manko();
}

interface Okama extends Man, Woman{
	
}

/** おかまの能力を継承した新人類クラス */
public class Shinjinrui implements Okama{

	public void Tinko(){
		System.out.println("男性のもの");
	}
	//このメソッドのアクセス修飾子はpublic じゃないとエラーになる。
	//なぜならインターフェースのメソッドが暗黙的にpublic abstractで修飾されているから
	//アクセス修飾子を厳しくすることはできない。
	public void Manko(){
		System.out.println("女性のもの");
	}
	
}
package test;

public class Main {
	public static void main(String[] args){
		Shinjinrui kami = new Shinjinrui();
		kami.Tinko();
		kami.Manko();
		System.out.println(kami.He);
		System.out.println(kami.She);
	}
}

<結果>


男性のもの
女性のもの
男
女

Stringクラス(不変)とStringBuilderクラス(可変)の違い
Stringクラスは不変として設計されているため、Stringオブジェクトがラップする文字列の変更するためのメソッドは聴許されていない。

変更可能な文字列を作成したい場合は、StringBufferクラスを使う必要がある。

Stringクラスで提供されている文字列連結のためのメソッドはconcat
StringBuilderクラスの場合はappendメソッドを使う。

public class StringTest {
	public static void main(String[] args){
		String str = "original";
		String strTmp = null;
		
		//こうすると新しいオブジェクトが生成されるが、ここでこのオブジェクトを参照する変数がないからガーベジコレクションの対象になる
		str.concat(" addStr");
		
		strTmp = str.concat(" addStr");
		
		//結果は「strTmp:original addStr」
		System.out.println("strTmp:" +strTmp);
		
		//結果は「str.concat():original」
		System.out.println("str.concat():"+str);
		
		//新たにできた「original addStr2」のオブジェクトを参照する
		str = str.concat(" addStr2");
		
		//結果は「str.concat():originaladdStr」
		System.out.println("str.concat():"+str);
		
		
		StringBuffer strb = new StringBuffer("originalBuff");
		strb.append("addBuff");
		System.out.println(strb);
		
	}
}

「equals」と「==」の違いについて
以下のようにString型の変数を宣言する。

String str = "hoge";

これを宣言したとき、同じ"hoge"のリテラル文字列が既にメモリ上にあれば、

そのリテラル文字列が変数に割り当てられる。

str2 = "hoge"とした場合

以下の図のように、同じオブジェクトを参照することになる。
f:id:go_my_own_way:20120718182934g:plain

「==」は同じオブジェクトを参照するかを比較する。
「equals」はオブジェクトが保持する文字列を比較する。

以下の例を見ればよりわかりやすいと思う。

public class StringTest2 {
	public static void main(String[] args){
		String str1 = "hoge";
		String str2 = "hoge";
		
		//結果はTRUE
		if (str1 == str2){
			System.out.println("str1とstr2は同じオブジェクトを参照している");
		}else{
			System.out.println("str1とstr2は違うオブジェクトを参照している");
		}
		
		
		//新たにnewでオブジェクトを作った場合
		String str3 = "hoge";
		String str4 = new String("hoge");
		
		//結果はFALSE
		if (str3 == str4){
			System.out.println("str3とstr4は同じオブジェクトを参照している");
		}else{
			System.out.println("str3とstr4は違うオブジェクトを参照している");
		}
		
		
		//equalsの場合、結果はTRUE
		if (str3.equals(str4)){
			System.out.println("str3とstr4のオブジェクトは同じ文字列を保持している");
		}else{
			System.out.println("str3とstr4のオブジェクトは同じ文字列を保持している");
		}
		
		
	}
}


<結果>

str1とstr2は同じオブジェクトを参照している
str3とstr4は違うオブジェクトを参照している
str3とstr4のオブジェクトは同じ文字列を保持している


ちゃんと詳しく勉強したい人がいたら、この本を参考にするといいです。