
読者の皆様、ご挨拶。
Javaは興味深く、美しい言語です。 しかし時々、それを見ない方が良いと書かれていることがあります。 しかし、そのような曲線、ケースで何が起こるかを知ることは依然として有用です。
きれいなコードの愛好者、すみません。
むかしむかし、ハブに関する記事が
パート1 、 パート2
それらは非常に興味深いものですが、残念ながら、著者は継続しませんでした。
さらに2つのタスクを紹介します(それ以上の強度はありませんでした。記事を書くのはそれほど簡単ではないことがわかりました)。
もちろん、記事の最後には、説明を含む回答と、最強のための追加のタスクがあります。
最初のタスクは、Joshua Bloch Java Puzzlersによる素晴らしい本からきれいに取り上げられています。 この本はコードの書き方を教えているのではなく(むしろ、逆に、どうして必要ないのか、なぜか)、教えているわけではありませんが、個人的にそれを読むのはとても面白かったです。 ただ楽しみのために。 お勧めです。
それでは始めましょう。
条件
1.実行は許されません
public class A { public static class X { public static class Y { public static String Z = "life is good"; } public static CY; } public static class C { public static String Z = "life is pain"; } public static void main(String[] args) { System.out.println(XYZ); } }
どうなるの?
- コンパイルエラー
- ランタイムエラー
- 人生をもたらすでしょう良いです
- 人生は痛みをもたらすでしょう
2.ジェネリックはそのようなジェネリックです
public class B { public static <T> T foo() { try { return (T) new Integer(42); } catch (ClassCastException e) { return (T) "habr"; } } public static void main(String[] args) { System.out.println(B.<String>foo()); } }
どうなるの?
- コンパイルエラー
- ランタイムエラー
- 出力42
- habrを出力します
そして今、正しい答え:
1.実行は許されません
public class A { public static class X { public static class Y { public static String Z = "life is good"; } public static CY; } public static class C { public static String Z = "life is pain"; } public static void main(String[] args) { System.out.println(XYZ); } }
人生は痛みをもたらすでしょう
すべてがワイルドですが、シンプルです。 はい、jlsはこれを許可します。 優先順位は常にフィールドにあります。
さらに興味深いのは、これを回避し、人生を豊かにする方法です。 私は3つの解決策を知っています:
- リフレクションAPI
- インポートxy
- インスタンスを通じて静的にアクセスできます:(新しいXY())Z
トップ5の探求
後者の方法は優れていますが、オブジェクトを作成する必要があり、これは悪いことです。 プライベートコンストラクターを追加します。 (反射および静的インポートなし)
public static class X { public static class Y { private Y() {} public static String Z = "life is good"; } public static CY; }
答えは: 非表示のテキスト
((XY)null).Z; // , Java.
2.ジェネリックはそのようなジェネリックです
public class B { public static <T> T foo() { try { return (T) new Integer(42); } catch (ClassCastException e) { return (T) "habr"; } } public static void main(String[] args) { System.out.println(B.<String>foo()); } }
ランタイムエラー 、またはClassCastException
そのため、javaジェネリックでは構文糖にすぎないことを知ってい
コードをよく見てください:
System.out.println(B.<String>foo());
コンパイラは、引数の型がStringであることを理解しているため、最適なprintlnを置き換えます。
public void println(String x)
使用するオーバーロードメソッドのバージョンを決定することは、ランタイムではなくコンパイルレベルのタスクであることが重要です。
どうぞ
return (T) new Integer(42);
キャストは、ジェネリックがなくなったときに実行時に発生します。
どうなるの?
なし。 整数は単に戻ります。
さて、ここにあります-printfを呼び出します。これはStringを受け取り、Integerを渡します。
未来への教訓
- しないで
- 世界にはObjectを受け入れるprintln以上のものがあります
- 一般的な型キャストは松葉杖です
トップ5の探求
thowsまたはtry-catchを必要としない任意のThrowable(チェック済み例外を含む)をスローするメソッドを実装します。
public static void throwWithoutCheck(Throwable t) { // , . throwWithoutCheck(new Exception()) - throws! }
答えは: 非表示のテキスト
UPD:
チェックせずに出口をスローする方法はまだあります。 これらは答えを意味するものではありませんでしたが、もっと「正直」に言ってみましょう。
stopは@deprecatedであることに注意してください。 ストリームでの作業の概念は大幅に変更され、草は緑になり、空気はきれいになりました 。
停止の引数として、停止の「理由」を渡すことができます。 Javaでは、原則として、try catchブロックでこれを結論付けることはできません。ここですべてが明確であることを願っています。
例については orionllに感謝します。
または:
ここでもすべてが明らかです。Unsafeで作業することは不可能であり、この場合、すべてが完全に正当化されます。
例についてはミスハドフに感謝します。
private static <T extends Throwable> void castAndThrow(Throwable t) throws T { throw (T) t; } public static void throwWithoutCheck(Throwable t) { B.<RuntimeException>castAndThrow(t); }
UPD:
チェックせずに出口をスローする方法はまだあります。 これらは答えを意味するものではありませんでしたが、もっと「正直」に言ってみましょう。
Thread.currentThread().stop(new IOException());
stopは@deprecatedであることに注意してください。 ストリームでの作業の概念は大幅に変更され、
停止の引数として、停止の「理由」を渡すことができます。 Javaでは、原則として、try catchブロックでこれを結論付けることはできません。ここですべてが明確であることを願っています。
例については orionllに感謝します。
または:
Unsafe.getUnsafe().throwException(new IOException());
ここでもすべてが明らかです。Unsafeで作業することは不可能であり、この場合、すべてが完全に正当化されます。
例についてはミスハドフに感謝します。