Javaお勉強(3)
Java難しいよJava
Arrays.binarySearchメソッド
- 検索して見つかった要素の添字を返す
- 使う前にsortしておく必要あり
ジェネリックの継承型指定
<型パラメータ extends データ型> → データ型かそのサブクラスのみを指定 ■ワイルドカード指定 <? extends 型パラメータ> → 型パラメータのデータ型かそのサブクラスのみを指定(上限境界ワイルドカード) オブジェクトの追加は出来ない(addとかは型安全でないのでダメ) <? super 型パラメータ> → 型パラメータのデータ型かそのスーパークラスのみを指定(下限境界ワイルドカード) オブジェクトの追加はOK
import java.util.*; class Foo { public void add(List<? extends String> list) { list.add("hoge"); //コンパイルエラー(上限境界ワイルドカードなのでオブジェクトの追加が出来そうで出来ない) Object obj = list; //OK String str = list.get(0); //OK list = new ArrayList<String>(); //OK list = new ArrayList<Object>(); //コンパイルエラー(Object型はString型のサブクラスではない) } }
Setとか
- 全てのSetがadd出来るとは限らない
- SortedSetはその設計上addできない
- TreeSetのsubSetメソッドはSortedSet型を返すので注意
- HashSetは重複許さない
Comparableインターフェース(自然順序付け)
- IntegerとかStringとか他たくさん
- 無条件でArray.sort()できる
- 無条件でPriorityQueueの順番が自然順序付けになる
newするときに左辺と右辺でクラスが異なるときに、同じ名前の変数とかメソッドが宣言されていたとき
まあ基本的に左辺のメソッドの型、クラス変数になる
- インスタンス変数は左辺になる
- メソッドは右辺になる(オーバーライドによる上書き)
class Super { public String str = "Super"; public void method() { System.out.println("Super"); } } class Sub extends Super{ public String str = "Sub"; public void method() { System.out.println("Sub"); } } public class Hoge { public static void main(String[] args) { Super obj = new Sub(); obj.method(); //Sub System.out.println(obj.str); //Super } }
- じゃあ例外宣言が親と子で違った場合はどーなるの???→左辺
class Super { void foo() throws Exception { throw new Exception(); } } class Sub extends Super { void foo() { System.out.println("Sub"); } } public class Hoge2 { public static void main(String[] args) { Super obj = new Sub(); obj.foo(); //コンパイラはSuperのfooメソッドをチェックしちゃう→例外処理必要なのでコンパイルエラー } }
インナークラス
- staticでないインナークラスはアウタークラスのメンバ扱い→アウタークラスのインスタンス化が必要(Outer.Inner in = new Outer().new Inner();)
- staticなインナークラスはそんなことない
インクリメントしたら参照はどうなるのか
下の例だと、x++のときにオートボクシングでint型でインクリメントされて、Integer x = new Integer(401);と入っている感じじゃないかなと思ってる
結果的に違う参照が入っていることに注目
public class Piyo { public static void main(String[] args) { Integer x = 400; Integer y = x; x++; StringBuilder sb1 = new StringBuilder("hoge"); StringBuilder sb2 = sb1; sb1.append("fuga"); System.out.println(x==y); //false System.out.println(sb1==sb2); //true } }
Javaのキーワードを変数名に使いたいんだけどそんなことって出来るの?
- Javaで最初から導入されているキーワードは出来ないけど、途中から導入されたものは可能
- 例えば、assertはJDK1.4から導入されたので、
javac -source 1.3 Hoge.java
とかやるとassertという名の変数を作ってもコンパイルが成功する
abstractなクラスでもコンストラクタは呼べる
- newは出来ないけどな!!
- ちゃんと子クラスから呼べます
mainメソッドの作法
これはOK
public class Piyo2 { public void main(String...orz) { System.out.println(orz[0]); } }
こっちはコンパイルが通る(!)が実行時例外発生(mainメソッドが無いと言われる)
public class Piyo3 { public void main(String[]...orz) { System.out.println(orz[0]); } }
多重継承
インターフェースの継承はextendsを使うから、implementsみたいに並べてたくさん書けるという話
interface A {} interface B {} interface C {} interface D {} interface E {} interface F {} interface GreatSuperInterface extends A,B,C,D,E,F { }