クラスクラス

入門



おそらく、Javaクラスが最も有名な部分です。 私たちは毎日それらを使い、書き、支配します。 しかし、私たちも知らない多くのニュアンスがあります。 そして、私はこれのために「私たちの」Javaが大好きです-それは常に神秘的で、神秘的であり続けることができます。 今日、彼女の秘密の一部はあなたの足元に落ちます。 ここでは、珍しいコード例、面白い話、興味深い統計が見つかります。 誰も気にしない、猫へようこそ。



いくつかの詳細



Javaの専門家であれば、コード例は退屈になりますが、そうでない場合はいつものとおりです。 かつて、Java 7の内部および内部では、クラスファイル形式がどのように配置されているかなど、非常に興味深いことがありました。 私はこれらの文書に精通しなければならなかった。 そこから、この記事のほとんどすべてのアイデアを強調しました。 それにもかかわらず、私は基礎理論家と経験豊富な専門家の用語の不正確さを事前に謝罪します。 自明であるか、答えを簡単に検索できるため、いくつかの質問には答えません。



最初の質問: 「そして、Java 7のクラスのタイプとタイプは何ですか?」 ほとんどは正しく答えますが、一部は答えません。 非常に多くの場合、彼らはローカルクラスに言及することを忘れます。



ローカルクラス



ロシア語のローカルクラスの適切な定義はすぐには見つかりませんでしたが、英語の問題なので、自分の言葉で言うと、 「ローカルクラスは、別のクラスのメンバーではなく、コードブロックまたはメソッド内で宣言された、ネストさ 内部クラスです」 ちょっとわかりにくい? 例では、すべてが簡単です:



ローカルクラスの例
public class LocalClassExample { { //      class MyFirstLocalClass { int someField; }; } //   public void someMethod() { //   class MySecondLocalClass { }; } //    public static void someStaticMethod() { class MyThirdLocalClass { }; } //    public void someBlock() { try { } catch (Exception e) { class MyFourthLocalClass {}; } } }
      
      





私は人生で多くのコードを調べましたが、メソッド内で明示的な名前付きクラス宣言に出会ったことはありません。 運が悪いだけかもしれません。 会ったことがありますか? しかし、クラスのタイプとタイプに関する統計を収集することに決めたとき、ローカルクラスがrt.jarに存在し、さらにjava.lang.Packageなどの悪名高いクラスで使用されていることがわかりました。 生きて学びます。 興味深い声明もあります。 「匿名クラスは名前のないローカルクラスです。 専門家にとっての質問は、 「これはそうですか?」です。



注釈クラス



アノテーションなどのクラスを決して書かない人はもういません。 そしてすぐに小さな例。



 @Target(ElementType.LOCAL_VARIABLE) @Retention(RetentionPolicy.RUNTIME) public @interface SmileAnn { String name() default ""; }
      
      





それでも、驚くべきことがあります。 以下のコードは有効だと思いますか?



奇妙な注釈コード
 @Target(ElementType.LOCAL_VARIABLE) @Retention(RetentionPolicy.RUNTIME) public @interface DontSmileAnn { String name() default ""; /**  ? */ static final String WHAT1 = "WHAT1"; /**  ? */ final String WHAT2 = "WHAT2"; /**     ? */ static class What3 { }; }
      
      





実際、複雑なことは何もありません。 しかし続けましょうが、この例をどのように気に入っていますか?



相続人
 public class ExtendsFromAnn implements DontSmileAnn { @Override public Class<ExtendsFromAnn> annotationType() { return ExtendsFromAnn.class; } @Override public String name() { return "ExtendsFromAnn"; } }
      
      





ここでの答えはすべてシンプルです-これらは実際のコード例です。実際には、ボンネットinterface = interfaceの下で、いくつかの警告があります。したがって、インターフェイスで記述できるすべてのものも注釈に入れることができます(警告もあります)。 テストで出会った型注釈のクラスからのコードの継承。 私は注釈についてすべてを持っていますが、文字列の配列の注釈付き型とその宣言の形式の小さな例があります:



異常な形状
  public static void main(String[] args) { //   ,    . @SmileAnn String []simpleArray[] = {{}}; }
      
      





私はあなたを退屈させなかったと思います。 しかし、そうでない場合、次の段落はあなたのためです。



レギュラークラス



通常のクラスに関する情報で一般的な例を除いて誰かを驚かすことは非常に困難です。 どんな方法を試しても、意味のあるものは見つかりませんでした。 しかし、私には1つの話、冗談があります。



開発者がタスクを解決するためにユーティリティクラスを記述する必要があった。 彼はすべてを正しく行い、java-doc、テストを書いたようです。 レビュー用のパッチを送信しました。



 /**java-doc*/ public class Utils { /** ,     */ }
      
      





チーフのミカリーチはパッチを見て、 「すべては大丈夫ですが、愚か者から保護しましょう-プライベートコンストラクターを追加してください」と言いました 開発者はいつものようにパッチをやり直したくありませんが、あなたはそれを最初からやり直すことはできません。 。 しかし、何もする必要はありません。やり直す必要があり、すべてが簡単です-プライベートコンストラクタを追加します。



 /**java-doc*/ public class Utils { /**      */ private Utils() {} /** ,     */ }
      
      





「完了」と開発者は叫んで、 「よくやった 」とミカリーチは答えた。 彼は提出を押したかった、ベルが鳴った。 この瞬間、重要な問題から解放された部門の長は、昔を振り返ることに決め、レビューのための最初のパッチを突いた。 「ああ!」 彼は叫んだ。 「Mikhalych、コードの書き方を忘れましたか? そして、deb * laからの保護はどこにありますか?」 。 部署の長は真面目な人であるため、Mikhalych氏は次のように語っています「私たちの会社には何がありますか。 。 Moody Mikhalychは、クラスに抽象を追加するためのメモでパッチをラップします。 開発者の下唇が揺れました。



 /**java-doc        */ public abstract class Utils { /**      */ private Utils() {} /** ,     */ }
      
      





皮肉なことに、その日、インターンは部門に来て、彼の最初の割り当てを受けて、戦いに急ぎました。 彼の視線はUtilsに落ち着き、彼の顔には賞賛と困惑が現れました。 勇気を得て、彼は最初のきらめく質問を大声で尋ねました。 「みんな、プライベートコンストラクターを持つクラスからどのように継承できますか?」



列挙クラス



誰が今彼らを驚かせるでしょうか? 今、10年前なら。 そのため、コードの理解に関するいくつかの質問があります。 列挙の次の要素の宣言に違いがあると思いますか?



 public class EnumExample { public enum E1 { SIMPLE } public enum E2 { SIMPLE() } public enum E3 { SIMPLE { } } public enum E4 { SIMPLE() { } } }
      
      





正しい答えを知っていれば、次の質問は簡単に思えます。 「コンソールで何が起こるでしょうか?」



 public class EnumExample { public enum E1 { SIMPLE } public enum E2 { SIMPLE() } public enum E3 { SIMPLE { } } public enum E4 { SIMPLE() { } } public static void main(String[] args) { System.out.println(E1.SIMPLE.getClass().isEnum()); System.out.println(E2.SIMPLE.getClass().isEnum()); System.out.println(E3.SIMPLE.getClass().isEnum()); System.out.println(E4.SIMPLE.getClass().isEnum()); } }
      
      





もちろん、ここではすべてが表面にあります-E3.SIMPLEとE4.SIMPLEはこれらの列挙型の匿名クラスのインスタンスです。 したがって、最後の2つの呼び出しは誤った結果を返します。 isEnum()を使用してenumクラスチェックを使用する場合は注意してください。



内部クラス



何を何と一緒に食べるのかなど、内部の情報に関する多くの情報があります。 しかし、私がインタビューした多くの人は2つの質問に答えることができませんでした。 まず、例を見てみましょう。



内部の内部クラス
 //  InnerClassExample.java public class InnerClassExample { private int myField; public class InnerClass { private int myField; public class InnerInnerClass { private int myField; public InnerInnerClass() { } } } } //  InnerClassCreate.java public class InnerClassCreate { public static void main(String[] args) { } }
      
      





そして最初の質問: 「InnerInnerClassクラスのコンストラクターでInnerClassExampleクラスのmyFieldフィールドにアクセスする方法とこれは可能ですか?」 2番目の質問: 「InnerClassCreateクラスのメインメソッドでInnerInnerClassクラスのインスタンスを作成する方法は?



答え
 public class InnerClassExample { private int myField; public class InnerClass { private int myField; public class InnerInnerClass { private int myField; public InnerInnerClass() { int mf1 = InnerClassExample.this.myField; // : . //   : int mf2_0 = InnerClass.this.myField; int mf2_1 = InnerClassExample.InnerClass.this.myField; // ?  . int mf3_0 = InnerInnerClass.this.myField; int mf4_1 = InnerClassExample.InnerClass.InnerInnerClass.this.myField; // ?  . } } } } public class InnerClassCreate { public static void main(String[] args) { // 1. ,     ,    new   InnerInnerClass one = new InnerClassExample().new InnerClass().new InnerInnerClass(); // 2 InnerClass innerClass = new InnerClassExample().new InnerClass(); InnerInnerClass two = innerClass.new InnerInnerClass(); // 3 InnerInnerClass three = getInnerClass().new InnerInnerClass(); } private static final InnerClass getInnerClass() { return new InnerClassExample().new InnerClass(); } }
      
      





それはすべてコード例です。



クラス統計



Mac OSでjdk1.7.0_60からrt.jarのいくつかのタイプとクラスのタイプの統計を収集しました。 そしてデータは

クラスの説明 数量
ローカル 21
注釈 137
乗り換え 278
内部(静的ではない) 1482
アブストラクト 1560
匿名 2230
インターフェース 2352
ネストされた静的 3222
普通 12943
合計で、19898クラスが私の分析の対象となりました。 ご清聴ありがとうございました。



All Articles