Javaの隠された機能


295

C#の隠し機能を読んだ後、Javaの隠し機能は何ですか?


17
これらの非表示の機能を使用することが常に優れているとは限らないことに注意してください。多くの場合、彼らはあなたのコードを読んでいる他の人を驚かせ、混乱させます。
Kevin Bourrillion、2009年

1
あなた(/誰か)は、C#の質問のように、質問の本文で回答をきちんとまとめる必要があります。
ripper234 2009

回答:


432

Double Braceの初期化は、数か月前に初めて発見し、これまで聞いたことがありませんでした。

ThreadLocalsは通常、スレッドごとの状態を保存する方法としてそれほど広く知られていません。

JDK 1.5 Javaはロックだけでなく、非常に適切に実装された堅牢な同時実行ツールを備えているため、java.util.concurrentにあり、特に興味深い例は、比較を実装するスレッドセーフプリミティブを含むjava.util.concurrent.atomicサブパッケージです。-and-swap操作。これらの操作の実際のネイティブハードウェアサポートバージョンにマップできます。


40
ダブルブレースの初期化...奇妙なことですが、実際にはオブジェクトの匿名サブクラスを作成するので、その特定のイディオムをあまりにも広く採用することには注意が必要です。java.util.concurrentは本当に素晴らしいパッケージです。
MB。

6
私はJava を教えてきましたが、この構文に出会ったのはこれが初めてです...これは、学習を決して止めないことを示すものです= 8
Yuval

49
この「二重ブレース」イディオムで初期化されたコレクションへの参照を保持する場合(または、それを実名で呼び出す場合-イニシャライザブロックを持つ匿名クラス)、厄介なメモリを引き起こす可能性のある外部オブジェクトへの参照を暗黙的に保持します。リーク。完全に回避することをお勧めします。
ddimitrov 2008年

51
「ダブルブレース初期化」は、匿名の内部クラスを作成するための非常に冒涜的な名前であり、実際に何が起こっているのかを理解し、内部クラスがこのように使用されることを意図しているかのように聞こえます。これは私が隠しておきたいパターンです。
エリクソン2008年

11
ほとんど、それは実際には静的ブロックではなく、別の時間に実行されるため、異なる「イニシャライザブロック」です(詳細については、回答に記載したリンクを参照してください)
Boris Terzic 2009年

279

型パラメーターの分散における結合和:

public class Baz<T extends Foo & Bar> {}

たとえば、ComparableとCollectionの両方であるパラメーターを取得する場合は、次のようにします。

public static <A, B extends Collection<A> & Comparable<B>>
boolean foo(B b1, B b2, A a) {
   return (b1.compareTo(b2) == 0) || b1.contains(a) || b2.contains(a);
}

この不自然なメソッドは、指定された2つのコレクションが等しい場合、またはコレクションのいずれかに指定された要素が含まれている場合はtrueを返し、そうでない場合はfalseを返します。注目すべき点は、引数b1とb2でComparableとCollectionの両方のメソッドを呼び出すことができることです。


これの私のお気に入りの使用法は、Appendable Charsequenceを受け入れるメソッドが必要な場合です。
ニール・コフィー

5
&の代わりに「OR」を使用することはできますか?
mainstringargs 2009年

9
@Grasper:いいえ、そのコンテキストではOR(素結合)は提供されていません。ただし、代わりにEither <A、B>のような非結合unionデータ型を使用できます。このタイプは、ペア<A、B>タイプのデュアルです。このようなデータ型の例については、Functional JavaライブラリまたはScalaコアライブラリを参照してください。
Apocalisp 2009年

5
1つのクラスといくつかのインターフェイスのみを拡張する必要があると述べた必要があります->パブリッククラスBaz <TはClazz&Interface1&InterfaceI ...を拡張し、クラスBaz <TはClazz1&ClazzI>を拡張しない
JohnJohnGa

220

先日、インスタンス初期化子に驚きました。私はいくつかのコード折り畳みメソッドを削除し、複数のインスタンス初期化子を作成してしまいました:

public class App {
    public App(String name) { System.out.println(name + "'s constructor called"); }

    static { System.out.println("static initializer called"); }

    { System.out.println("instance initializer called"); }

    static { System.out.println("static initializer2 called"); }

    { System.out.println("instance initializer2 called"); }

    public static void main( String[] args ) {
        new App("one");
        new App("two");
  }
}

mainメソッドを実行すると、次のように表示されます。

static initializer called
static initializer2 called
instance initializer called
instance initializer2 called
one's constructor called
instance initializer called
instance initializer2 called
two's constructor called

これらは、複数のコンストラクターがあり、共通のコードが必要な場合に役立つと思います

また、クラスを初期化するための構文糖を提供します。

List<Integer> numbers = new ArrayList<Integer>(){{ add(1); add(2); }};

Map<String,String> codes = new HashMap<String,String>(){{ 
  put("1","one"); 
  put("2","two");
}};

38
呼び出される必要がある明示的なメソッドに対するこれの利点は、誰かが後でコンストラクタを追加する場合に、init()を呼び出すことを覚えておく必要がないことです。それは自動的に行われます。これにより、将来のプログラマによるエラーを防ぐことができます。
Shiny氏と新安宇氏

40
また、init()メソッドとは異なり、finalフィールドを初期化できます。
ダロン、

2
クラスを拡張して、さまざまな子供をインスタンス化するとどうなりますか?それでも同じように動作しますか?
Kezzer、

12
多くの場合、認定資格は無効になり(例:stackoverflow.com/questions/281100/281127#281127)、技術的なメリットに疑問を投げかけます。しかし、ここでより多くのプログラマーが自分のSCJPについて研究した場合、これは多くの人にとって「隠された機能」とは見なされません。;-)
Jonik、2009

12
「24時間でJava」という本にもこの「明らかな特徴」があるのは間違いない。もっと読む:)(
Özgür2009年

201

JDK 1.6_07 +には、VisualVM(bin / jvisualvm.exe)と呼ばれるアプリが含まれています。これは、多くのツールの上にある素晴らしいGUIです。JConsoleよりも包括的です。


そして、それはJconsoleプラグインを使用することを可能にするプラグイン(それはnetbeansのものです)を持っています。けっこういい。
するThorbjörnRavnアンデルセン

VisualVMはスライスされたパン以来最高です。JDK 1.5に対して実行すると、すべての機能が搭載されていないのが残念です
sandos

状況によっては、VisualVMが遅い、または使用できないと思います。商用のYourKitにはこの問題はありませんが、残念ながら無料ではありません。
Roalt

JDK 1.6.0_22以降のVisual VMの最新バージョンは大幅に改善されています。JDK1.7にはさらに優れたバージョンがあると思います。
djangofan 2011


156

私がJava開発者にインタビューしたほとんどの人にとって、blocksというラベルの付いたポジションは非常に驚くべきものです。次に例を示します。

// code goes here

getmeout:{
    for (int i = 0; i < N; ++i) {
        for (int j = i; j < N; ++j) {
            for (int k = j; k < N; ++k) {
                //do something here
                break getmeout;
            }
        }
    }
}

gotoがJavaで言ったのは単なるキーワードですか?:)


2
まあ、私はむしろそれをいくつかの方法で行うオプションを持っていることを望みます。たとえば、System.exit(1)を使用している人を見ました。サーブレットとEJBコードでは、System.exit()を削除する必要があるという意味ではありません。JDKからですよね?
Georgy Bolyuba 2008

31
状況によっては、ネストされたループ構造内で、外側のループの次の反復に進むことが役立つ場合があります。これは、この機能の合理的な使用法です。
alasdairg 2008年

75
多くのプログラマーが特に知らないことは(そしておそらく同様に)、実際にラベルを付けて古いブロックから抜け出すことができるということです。ループである必要はありません。任意のブロックを定義して、ラベルを付け、breakを使用できます。
Neil Coffey

27
これはまったく後藤ではなく、前の反復に戻ることができるだけです(つまり、前にジャンプすることはできません)。これは、反復がfalseを返すときに発生するメカニズムと同じです。javaにgotoがあると言うことは、コンパイラがJUMP命令を生成するすべての言語にgotoステートメントがあると言うのと同じです。
ゾンビ

4
したがって、問題を解決し、設計について考える能力ではなく、Javaの雑学に基づいてインタビューします。私はあなたの会社に面接しないようにします。:)
Javid Jamae

144

JDK 1.5以降に導入されている共変戻り値型はどうですか?それは魅力的ではない追加なのでかなり宣伝されていませんが、私が理解しているように、ジェネリックが機能するためには絶対に必要です。

基本的に、コンパイラーはサブクラスがオーバーライドされたメソッドの戻り値の型を、元のメソッドの戻り値の型のサブクラスになるように絞り込むことができるようになりました。したがって、これは許可されています:

class Souper {
    Collection<String> values() {
        ...
    }
}

class ThreadSafeSortedSub extends Souper {
    @Override
    ConcurrentSkipListSet<String> values() {
        ...
    }
}

サブクラスのvaluesメソッドを呼び出して、にダウンキャストすることなく sのソートされたスレッドセーフSetを取得できます。StringConcurrentSkipListSet


使用例を提供できますか?
Allain Lalonde

24
よく使います。clone()は良い例です。これはオブジェクトを返すことになっているため、たとえば(List)list.clone()と言う必要があります。ただし、リストclone(){...}として宣言する場合、キャストは不要です。
Jason Cohen

142

finallyブロックで制御を移すと、例外が発生しなくなります。次のコードはRuntimeExceptionをスローしません-失われます。

public static void doSomething() {
    try {
      //Normally you would have code that doesn't explicitly appear 
      //to throw exceptions so it would be harder to see the problem.
      throw new RuntimeException();
    } finally {
      return;
    }
  }

http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.htmlから


7
それは厄介ですが、最終的にどのように機能するかという単なる論理的な帰結でもあります。try / catch / finallyフロー制御は、意図されていることを行いますが、特定の制限内でのみ行います。同様に、catch / finallyブロック内で例外が発生しないように注意する必要があります。そうしないと、元の例外も破棄されます。また、tryブロック内でSystem.exit()を実行すると、finallyブロックは呼び出されません。通常の流れを壊すと、通常の流れを壊します...
Neil Coffey

最終的に{returnを使用しないでください。}しかし、ついに{リターンなしのコード}。これは論理的であり、最終的には例外が発生したときに実行されることも意図されており、例外ハンドラとしてのreturnの唯一の可能な意味は、例外を無視して、そして実際にreturnでなければならないことです。
extraneon

21
これは非表示の機能というよりは「ちょっとしたこと」のように見えますが、1つの方法として使用できる方法はいくつかありますが、この方法を使用することはお勧めできません。
davenpcj 2009年

これを行うと、Eclipseは警告を出します。私はEclipseを使っています。例外をキャッチしたい場合は...例外をキャッチします。
helios

これが、メソッドの途中から返されるダーティコードに支払う金額です。しかし、それでも良い例です。
Rostislav Matl 2010年

141

nullのチェックが不要になるような方法でinstanceofが実装されていることに言及している人を見たことはありません。

の代わりに:

if( null != aObject && aObject instanceof String )
{
    ...
}

ただ使う:

if( aObject instanceof String )
{
    ...
}

9
これがあまり知られていない機能であることは残念です。コードの最初のブロックに似た多くのコードを見てきました。
Peter Dolberg、2009

4
これは、Javaには、表示も参照もできない特別な(非表示の)null型があるためです。
Nick Hristov、2011

さらに悪いのは、C / C ++でfreeingまたはdeleteingする前にnullをチェックすることです。そのような基本的な概念。
Thomas Eding、2012

134

列挙型でメソッドとコンストラクターを許可すると、驚いた。例えば:

enum Cats {
  FELIX(2), SHEEBA(3), RUFUS(7);

  private int mAge;
  Cats(int age) {
    mAge = age;
  }
  public int getAge() {
    return mAge;
   }
}

特定の列挙値がメソッドをオーバーライドできるようにする「定数の特定のクラス本体」を持つこともできます。

詳細なドキュメントはこちら


20
実際に本当に素晴らしい機能-列挙型OOを作成し、多くの初期化問題を非常にクリーンな方法で解決します。
Bill K

5
シングルトンとしての列挙?値が1つだけの列挙型?
Georgy Bolyuba 2008年

6
Georgy:シングルトンはオブジェクトの1つのインスタンスであり、1つの値を持つオブジェクトではありません。
dshaw 2008年

20
@Georgy:Joshua BlochのEffective Java(2 ed ed)のItem 3も参照してください。「このアプローチはまだ広く採用されていませんが、シングルトンを実装するには、単一要素の列挙型が最良の方法です。」
ジョニック2009

3
マイナーなnitpick:mAge最終的なはずです。enumに最終でないフィールドがある理由はめったにありません。
ヨアヒムザウアー

121

ジェネリックメソッドの型パラメーターは、次のように明示的に指定できます。

Collections.<String,Integer>emptyMap()

10
そして、神によってそれは醜くて混乱しています。タイプセーフとは無関係です。
Chris Broadfoot

8
これ大好き。それはあなたのコードをもう少し明確にし、そして一年か二年後にそれを維持しなければならない貧しいsodにとってより明確にします。
extraneon

6
これは、などの静的なジェネリックメソッドを宣言している状況で実際に非常に役立ちますpublic static <T> T foo(T t)。その後、Class.<Type>foo(t);
Finbarrに

何らかの理由で、これは静的にインポートされたメソッドでは機能しないようです。なぜでしょうか。
oksayt 2011

これは、リターンで3値のifを使用する場合に特に便利です。例えばreturn set1.equals(set2) ? new ArrayList<String>(set1) : Collections.<String>emptyList()。また、単純なCollections.emptyMap()でコンパイルエラーが発生するいくつかのメソッド呼び出しにも役立ちます。
Andreas Holstenson、2011年

112

enumを使用してインターフェースを実装できます。

public interface Room {
   public Room north();
   public Room south();
   public Room east();
   public Room west();
}

public enum Rooms implements Room {
   FIRST {
      public Room north() {
         return SECOND;
      }
   },
   SECOND {
      public Room south() {
         return FIRST;
      }
   }

   public Room north() { return null; }
   public Room south() { return null; }
   public Room east() { return null; }
   public Room west() { return null; }
}

編集:数年後...

ここでこの機能を使用します

public enum AffinityStrategies implements AffinityStrategy {

https://github.com/peter-lawrey/Java-Thread-Affinity/blob/master/src/main/java/vanilla/java/affinity/AffinityStrategies.java

インターフェイスを使用することにより、開発者は独自の戦略を定義できます。enum手段を使用して、組み込みのコレクション(5つのコレクション)を定義できます。


27
これは狂気です。(+1)
頭足類

12
@アリアンこれは狂気ではありません。この。IS。JAVAAAAAAHHHH!
slezica

1
WHAAAAATいいえ、私はエイドリアンと一緒です。これはJavaではありません。これは狂気です。これを使いたくてたまらない。
slezica

104

Java 1.5以降、Javaには可変アリティの関数を作成するためのより明確な構文があります。したがって、配列を渡すだけでなく、次のことができます

public void foo(String... bars) {
   for (String bar: bars)
      System.out.println(bar);
}

棒は、指定されたタイプの配列に自動的に変換されます。大きな勝利ではありませんが、それでも勝利です。


23
これについて重要なことは、メソッドを呼び出すときに、次のように書くことができるということです:foo( "first"、 "second"、 "third")
Steve Armstrong

9
古いhello worldを書き直すことができます。public static void main(String ... args){System.out.println( "Hello World!"); }
Karussell、2010年

@Karussellたぶん、しかし議論は無関係であるように思われるでしょう:p
ケリー・エルトン

93

私のお気に入り:すべてのスレッドスタックトレースを標準出力にダンプします。

窓:CTRL- BreakあなたのjavaのCMD /コンソールウィンドウで

UNIX: kill -3 PID


15
Unixではctrl- \も。または、JDKのjstackを使用します。
トム・ホーティン-タックライン'09

9
ありがとう、あなたは私のキーボードにBreakキーがあることを教えてくれました。
エイミーB

2
Windowsでは、CTRL-BREAKは、現在のコンソールウィンドウでプロセスを実行している場合にのみ機能します。代わりにJAVA_HOME / bin / jstack.exeを使用できます。WindowsプロセスIDを指定するだけです。
Javid Jamae、2010

殺害だと思った-SIGQUIT
Nick Hristov

@ニック、はいSIGQUITは通常シグナル#3です。
Chris Mazzola、2011

89

いくつかの人々がインスタンス初期化子について投稿しました、ここにそれの良い使い方があります:

Map map = new HashMap() {{
    put("a key", "a value");
    put("another key", "another value");
}};

すばやく簡単なことをしているだけの場合、マップを初期化する簡単な方法です。

または、それを使用してクイックスイングフレームのプロトタイプを作成します。

JFrame frame = new JFrame();

JPanel panel = new JPanel(); 

panel.add( new JLabel("Hey there"){{ 
    setBackground(Color.black);
    setForeground( Color.white);
}});

panel.add( new JButton("Ok"){{
    addActionListener( new ActionListener(){
        public void actionPerformed( ActionEvent ae ){
            System.out.println("Button pushed");
        }
     });
 }});


 frame.add( panel );

もちろんそれは悪用される可能性があります:

    JFrame frame = new JFrame(){{
         add( new JPanel(){{
               add( new JLabel("Hey there"){{ 
                    setBackground(Color.black);
                    setForeground( Color.white);
                }});

                add( new JButton("Ok"){{
                    addActionListener( new ActionListener(){
                        public void actionPerformed( ActionEvent ae ){
                            System.out.println("Button pushed");
                        }
                     });
                 }});
        }});
    }};

どういうわけか、 "with"キーワード(実際には機能)がJavaに追加されたようです。配列のinitがコレクションで利用できなかったので、最近とてもうれしくなりました。ありがとう!
PhiLho 2008

15
ただし、これを使用することの副作用が1つあります。匿名オブジェクトが作成されますが、常にうまくいくとは限りません。
アミット

17
もっと見てみると、「虐待」バージョンでさえ、これが提供する自然な入れ子に奇妙に惹かれていると言わざるを得ません。
ビルK

4
うん-私は「乱用」バージョンがかなり好きです、それは本当に非常に明確で読みやすいと思いますが、おそらくそれは私だけです。
2010

3
絶対に同意します。GUIの階層を反映するコードの階層は、一連のメソッド呼び出しよりも大幅に改善されています。
opsb 2010年

88

動的プロキシー(1.3で追加)を使用すると、インターフェースに準拠する実行時に新しいタイプを定義できます。意外と重宝します。


10
動的プロキシーは、Fooインターフェースを作成し、デフォルトの「FooImpl」クラスでそれをどこでも使用することを選択する大きな理由です。最初は醜く見えるかもしれませんが(「Fooと呼ばれるクラスがあるだけなのはなぜですか?」)、単体テストの将来の柔軟性とモック機能に関する利点は便利です。非インターフェースに対してもそれを行う方法がありますが、それらは通常cblibのような追加のものが必要です。
ダリアン、

82

最終的な初期化は延期できます。

ロジックの複雑なフローでも戻り値が常に設定されるようにします。ケースを見逃して、誤ってnullを返すのは簡単です。nullを返すことが不可能になるわけではありません。それが意図的であることは明らかです。

public Object getElementAt(int index) {
    final Object element;
    if (index == 0) {
         element = "Result 1";
    } else if (index == 1) {
         element = "Result 2";
    } else {
         element = "Result 3";
    }
    return element;
}

それは驚くべきことです。設定がどこで発生しても、「最終的な変数の値は一度だけ設定できます」とかなり言えますか?
David Koelle

29
はい、ただしより強く:「最終的な変数の値は1回設定する必要があります」
Allain Lalonde

6
+1同意します。これは、コンパイル時にエラーを見つけるためのもう1つの貴重なツールであり、プログラマーが何らかの理由で使用するのをためらうようです。Java 5以降、「final」にはスレッドセーフな影響もあるので、コンストラクター中にfinal変数を設定できることは非常に重要です。
Neil Coffey

4
この特定の方法では、複数のリターンを使用します。実際、これが当てはまるほとんどの場合、おそらく別のメソッドにリファクタリングし、複数のリターンを使用します。
ripper234 2009年

これ大好き!最終的なキーワードは失敗すると思っていたので、常に削除しました。ありがとう!
KARASZIIstván2010

62

Javaのもう1つの「見過ごされている」機能は、JVM自体だと思います。それはおそらく利用可能な最高のVMです。そして、それは多くの興味深く有用な言語(Jython、JRuby、Scala、Groovy)をサポートします。これらの言語はすべて、簡単かつシームレスに連携できます。

(scalaの場合のように)新しい言語を設計する場合、既存のすべてのライブラリーをすぐに使用できるため、言語は最初から「有用」です。

これらの言語はすべて、HotSpotの最適化を利用しています。VMは非常によく監視され、デバッグ可能です。


18
いいえ、実際にはあまり良いVMではありません。JAVAを実行するためだけに設計されました。型なしの動的言語と関数型言語は、それではうまく機能しません。VMを使用する場合は、.NET / Monoを使用する必要があります。それは
すべての

14
実際、JVMはJavaバイトコードを実行するためだけに設計されています。最新のほとんどの言語をJavaバイトコードにコンパイルできます。Java Bytecodeに欠けているのは、動的言語サポート、ポインター、末尾再帰サポートだけです。
mcjabberz

12
@ Hades32:実際、.NET VMはJVMにかなり似ています。比較的最近になって(DLRで)動的言語がサポートされるようになり、Java 7もそのサポートを取得しようとしています。また、.NETの従来の「すべての言語」(C#、Visual Basic.NETなど)はすべて、まったく同じ機能セットを備えています。
ヨアヒムザウアー

13
JVMはジェネリックをサポートしませんが、.NET VMはジェネリックをサポートします。JVMは最高に近いものではありません。
ブリンディ2009年

3
JVMで直接サポートされていない特定の言語機能に関する不満を軽視しないでください...しかし、安定性、クロスプラットフォームの一貫性、優れたパフォーマンスは、JVMが余分なポイントを獲得する理由をはるかに超えていると思いがちです。私は何年にもわたって多くのプラットフォーム(AS / 400を含む)でサーバー側のJavaを使用してきましたが、それを完全に忘れることができました-バグはほとんど常に修正可能なコードにあります。単にクラッシュしません。
Rob Whelan、2012年

58

匿名のサブクラスを定義して、インターフェースを実装していなくても、直接そのメソッドを呼び出すことができます。

new Object() {
  void foo(String s) {
    System.out.println(s);
  }
}.foo("Hello");

@Vuntic-必要なコンテキスト内で単純なクラスを定義できます。
ChaosPandion 2010

1
@カオス、でもなぜ?それが役立つ実際の例を手に入れましたか?
するThorbjörnRavnアンデルセン

10
@Wouter-その場合、匿名オブジェクト(start())で呼び出されるメソッドは、実際にはサブクラスで定義されていません...
Axel

実際、これは、必要な設定を行う基本クラスを拡張し、作成したメソッドを呼び出し、その後分解する場合に非常に便利な機能です。基本クラスのメソッドを呼び出すことで始めます(おそらく同じ名前は付けないでしょう)。ここに
AmigoNico 2012年

56

asListメソッドでjava.util.Arraysは、可変引数、ジェネリックメソッド、オートボクシングをうまく組み合わせることができます。

List<Integer> ints = Arrays.asList(1,2,3);

15
返されたリストをListコンストラクターでラップする場合、それ以外の場合、intは固定サイズになります(配列によってサポートされるため)
KitsuneYMG

2
Arrays.asListは、set()要素にはできるがadd()やにはない、珍しい機能がありますremove()。だから私は、通常でラップnew ArrayList(...)たりしてCollections.unmodifiableList(...)、私は、リストの修正をしたいかどうかに応じて、。
クリスチャンセムラウ

53

このキーワードを使用して、内部クラスから包含クラスのフィールド/メソッドにアクセスします。以下では、かなり不自然な例で、匿名の内部クラスのコンテナークラスのsortAscendingフィールドを使用します。this.sortAscendingの代わりにContainerClass.this.sortAscendingを使用するとうまくいきます。

import java.util.Comparator;

public class ContainerClass {
boolean sortAscending;
public Comparator createComparator(final boolean sortAscending){
    Comparator comparator = new Comparator<Integer>() {

        public int compare(Integer o1, Integer o2) {
            if (sortAscending || ContainerClass.this.sortAscending) {
                return o1 - o2;
            } else {
                return o2 - o1;
            }
        }

    };
    return comparator;
}
}

4
これは、名前をシャドウしている場合にのみ必要です(この場合、メソッドパラメータ名を使用します)。引数を別の名前で呼び出した場合、 'this'を使用せずにContainerクラスのsortAscendingメンバー変数に直接アクセスできます。
sk。

7
囲んでいるクラスへの参照があると便利です。それを何らかのメソッドまたはコンストラクターに渡す必要がある場合。
PhiLho

Androidレイアウト開発でよく使用されます。たとえば、ボタンのリスナーからを使用してコンテキストを取得しMyActivity.thisます。
espinchi 2011

52

実際には機能ではありませんが、いくつかのWebページで最近発見した面白いトリックです。

class Example
{
  public static void main(String[] args)
  {
    System.out.println("Hello World!");
    http://Phi.Lho.free.fr

    System.exit(0);
  }
}

有効なJavaプログラムです(ただし、警告が生成されます)。理由がわからない場合は、グレゴリーの回答をご覧ください。;-)まあ、ここでの構文の強調表示もヒントになります!


15
コメント:)ときちんと、ラベル
するThorbjörnRavnアンデルセン

46

これは正確に「隠された機能」ではなく、あまり有用ではありませんが、場合によっては非常に興味深いものに
なる可能性があります。クラスsun.misc.Unsafe- Javaで直接メモリ管理を実装できるようになりますこれをたくさん試してみると):

public class UnsafeUtil {

    public static Unsafe unsafe;
    private static long fieldOffset;
    private static UnsafeUtil instance = new UnsafeUtil();

    private Object obj;

    static {
        try {
            Field f = Unsafe.class.getDeclaredField("theUnsafe");
            f.setAccessible(true);

            unsafe = (Unsafe)f.get(null);
            fieldOffset = unsafe.objectFieldOffset(UnsafeUtil.class.getDeclaredField("obj"));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    };
}

20
それはsun。* APIです。これは、Java言語自体の一部ではありません
DW。

Unsafeには、コンストラクターを呼び出さずにオブジェクトを作成する、malloc / realloc / freeスタイルのメソッドなど、好奇心が強いメソッドが他にも多数あります。
Peter Lawrey、2010

特にputDouble(long address、double d)のようなメモリ位置のプリミティブゲッターとセッターが大好きです。
ダニエル

42

隠されたようなスイングIで作業する場合Ctrl- Shift- F1機能。

現在のウィンドウのコンポーネントツリーをダンプします。
(そのキーストロークを他の何かにバインドしていないと仮定します。)


1
ほとんどの場合、ウィンドウマネージャーにはそのキーにバインドされたものがあります。Gnomeはそれにバインドしないので、「デスクトップ13に切り替える」にバインドするKDEを実行していると仮定します。これを変更するには、コントロールパネル、[地域]、[キーボードショートカット]に移動し、Shift-Ctrl-F1のマッピングを削除します
Devon_C_Miller

40

すべてのクラスファイルは16進値0xCAFEBABEで始まり、有効なJVMバイトコードとして識別されます。

説明


38

私の投票は、並行コレクションと柔軟なエグゼキューターがjava.util.concurrentに行き、とりわけスレッドプール、スケジュールされたタスク、調整されたタスクを許可します。DelayQueueは私の個人的なお気に入りであり、指定された遅延後に要素が使用可能になります。

java.util.TimerとTimerTaskは安全に休止できます。

また、完全に隠されているわけではありませんが、日付と時刻に関連する他のクラスとは異なるパッケージにあります。java.util.concurrent.TimeUnitは、ナノ秒、マイクロ秒、ミリ秒、秒の間で変換するときに役立ちます。

通常のsomeValue * 1000またはsomeValue / 1000よりもはるかによく読み取れます。


最近発見されたCountDownLatchCyclicBarrier- そう便利!
Raphael

37

言語レベルのassertキーワード。


19
アサートの問題は、実行時にスイッチをオンにする必要があることです。
エキストラ

10
しかし、それが無効になっている場合、それはそこにないようです。コードには必要なだけアサーションを追加できます。アサートを無効にしてもパフォーマンスは低下しません。
Ravi Wallau、

5
これはアサートの良い点だ思います。ペナルティなしにオフにすることができます。
andref '07 / 07/11

問題は...あなたが誤ってアサートでの副作用を実装した場合、あなたは仕事にウルプログラムのアサーションをオンにするんだ、である
ちー

アサーションがオンになっているかどうかを検出するには、{boolean assertsOn = false; assertassOn = true; if(assertsOn){/ *複雑な検証* /}}。これにより、アサートの状態が予期されていない場合に例外をログに記録またはスローすることもできます。
fernacolo

37

実際にはJava言語の一部ではありませんが、SunのJDKに付属するjavap逆アセンブラは広く知られていないか、使用されていません。


36

1.5でfor-eachループコンストラクトが追加されました。私は3未満です。

// For each Object, instantiated as foo, in myCollection
for(Object foo: myCollection) {
  System.out.println(foo.toString());
}

ネストされたインスタンスで使用できます:

for (Suit suit : suits)
  for (Rank rank : ranks)
    sortedDeck.add(new Card(suit, rank));

for-eachコンストラクトは配列にも適用でき、イテレーターではなくインデックス変数を非表示にします。次のメソッドは、int配列の値の合計を返します。

// Returns the sum of the elements of a
int sum(int[] a) {
  int result = 0;
  for (int i : a)
    result += i;
  return result;
}

Sunのドキュメントへのリンク


30
iほとんどの人が配列要素ではなくインデックスであることを期待するので、ここでの使用は非常に混乱すると思います。
cdmckay 2009

したがって... int sum(int [] array){int result = 0; for(int element:array){result + = element; }結果を返します。}
ドリュー

28
これについて私を混乱させる唯一のことは、ループカウント値にアクセスするためのキーワードを作成するのは本当に簡単に思えるかもしれませんが、それはできません。2つの配列をループし、最初の配列の値に基づいて2番目の配列を変更したい場合、2番目の配列へのオフセットがないため、古い構文を使用せざるを得ません。
Jherico、2009年

6
これは、JNDIで使用されるような列挙型でも機能しないのは残念です。そこのイテレータに戻ります。
エキストラ

3
@extraneon:Collections.list(Enumeration <T> e)を見てください。これは、foreachループで列挙を繰り返すのに役立ちます。
ヴェルナーレーマン

34

私は個人的java.lang.Voidに非常に遅くに発見しました-ジェネリックと組み合わせてコードの可読性を向上させます。Callable<Void>


2
かなりではありません。ある時点で、具体的にする必要があります:Executors.newSingleThreadExecutor()。submit(new Callable <Void>(){..})-新しいCallable <?>()をインスタンス化することはできません。指定する必要があります明示的なタイプ-したがって、これはCallable <Object>の代わりになります。
RahelLüthy、2009年

4
Voidはnullのみで、Objectは何でもかまいません。VoidはObjectよりも具体的です。
Peter Lawrey、2010
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.