C#の隠し機能を読んだ後、私は疑問に思いました、Javaの隠し機能のいくつかは何ですか?
100 に答える
Double Brace Initializationは、数か月前に初めて発見したときは驚きましたが、それまで聞いたこともありませんでした。
通常、 ThreadLocalsは、スレッドごとの状態を格納する方法としてはあまり知られていません。
JDK 1.5 Java には、ロックだけでなく、非常に適切に実装された堅牢な同時実行ツールが備わっているため、それらはjava.util.concurrentに存在します。特に興味深い例は、比較を実装するスレッドセーフなプリミティブを含むjava.util.concurrent.atomicサブパッケージです。 -and-swap操作であり、これらの操作の実際のネイティブ ハードウェア サポート バージョンにマップできます。
型パラメーター分散の結合和:
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 の両方のメソッドを呼び出すことができるということです。
先日、インスタンス初期化子に驚きました。私はいくつかのコードフォールドメソッドを削除していて、複数のインスタンス初期化子を作成することになりました:
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");
}};
JDK 1.6_07+ には、VisualVM (bin/jvisualvm.exe) というアプリが含まれています。これは、多くのツールの上にある優れた GUI です。JConsole よりも包括的なようです。
Java 6 以降のクラスパス ワイルドカード。
java -classpath ./lib/* so.Main
それ以外の
java -classpath ./lib/log4j.jar:./lib/commons-codec.jar:./lib/commons-httpclient.jar:./lib/commons-collections.jar:./lib/myApp.jar so.Main
http://java.sun.com/javase/6/docs/technotes/tools/windows/classpath.htmlを参照してください。
Java 開発者の職について私がインタビューしたほとんどの人にとって、ラベル付きのブロックは非常に驚くべきものです。次に例を示します。
// 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で単なるキーワードだと言ったのですか? :)
JDK 1.5 以降に導入された共変の戻り値の型はどうですか? それは魅力的でない追加であるため、あまり宣伝されていませんが、私が理解しているように、ジェネリックが機能するためには絶対に必要です.
基本的に、コンパイラは、サブクラスがオーバーライドされたメソッドの戻り値の型を元のメソッドの戻り値の型のサブクラスに狭めることができるようになりました。したがって、これは許可されます:
class Souper {
Collection<String> values() {
...
}
}
class ThreadSafeSortedSub extends Souper {
@Override
ConcurrentSkipListSet<String> values() {
...
}
}
にダウンキャストすることなく、サブクラスのメソッドを呼び出して、s のvalues
ソートされたスレッドセーフSet
を取得できます。String
ConcurrentSkipListSet
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から
nullをチェックする必要がないような方法で実装されているinstanceofについて言及している人は誰もいません。
それ以外の:
if( null != aObject && aObject instanceof String )
{
...
}
使用するだけです:
if( aObject instanceof String )
{
...
}
列挙型でメソッドとコンストラクターを許可すると、私は驚きました。例えば:
enum Cats {
FELIX(2), SHEEBA(3), RUFUS(7);
private int mAge;
Cats(int age) {
mAge = age;
}
public int getAge() {
return mAge;
}
}
特定の列挙値がメソッドをオーバーライドできるようにする「定数固有のクラス本体」を使用することもできます。
詳細なドキュメントはこちら.
ジェネリック メソッドの型パラメーターは、次のように明示的に指定できます。
Collections.<String,Integer>emptyMap()
列挙型を使用してインターフェイスを実装できます。
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 {
インターフェイスを使用することで、開発者は独自の戦略を定義できます。手段を使用して、enum
組み込みのコレクション (5 つのコレクション) を定義できます。
Java 1.5 の時点で、Java には、可変アリティの関数を記述するためのよりクリーンな構文が備わっています。したがって、配列を渡すだけでなく、次のことができるようになりました
public void foo(String... bars) {
for (String bar: bars)
System.out.println(bar);
}
バーは、指定された型の配列に自動的に変換されます。大きな勝利ではありませんが、それでも勝利です。
私のお気に入り: すべてのスレッド スタック トレースを標準出力にダンプします。
Windows: CTRL- BreakJava コマンド/コンソール ウィンドウで
ユニックス: kill -3 PID
何人かがインスタンス初期化子について投稿しています。
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");
}
});
}});
}});
}};
動的プロキシ(1.3で追加)を使用すると、実行時にインターフェイスに準拠する新しいタイプを定義できます。意外と何度も重宝します。
最終的な初期化は延期できます。
ロジックの複雑なフローでも、戻り値が常に設定されるようにします。ケースを見逃して誤って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;
}
Javaのもう1つの「見落とされた」機能は、JVM自体だと思います。これはおそらく、利用可能な最高の VM です。また、多くの興味深い便利な言語 (Jython、JRuby、Scala、Groovy) をサポートしています。これらすべての言語は、簡単かつシームレスに連携できます。
(scala の場合のように) 新しい言語を設計すると、既存のすべてのライブラリがすぐに利用可能になり、その言語は最初から「役立つ」ものになります。
これらの言語はすべて HotSpot 最適化を利用します。VM は非常によく監視され、デバッグ可能です。
のasListメソッドをjava.util.Arrays
使用すると、varargs、ジェネリック メソッド、オートボクシングを適切に組み合わせることができます。
List<Integer> ints = Arrays.asList(1,2,3);
このキーワードを使用して、内部クラスからクラスを含むフィールド/メソッドにアクセスします。以下のやや不自然な例では、匿名内部クラスからコンテナ クラスの 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;
}
}
本当の機能ではありませんが、最近 Web ページで発見した面白いトリックです。
class Example
{
public static void main(String[] args)
{
System.out.println("Hello World!");
http://Phi.Lho.free.fr
System.exit(0);
}
}
is a valid Java program (although it generates a warning). If you don't see why, see Gregory's answer! ;-) Well, syntax highlighting here also gives a hint!
これは正確には「隠された機能」ではなく、あまり有用ではありませんが、場合によっては非常に興味深いものに
なる可能性があります: クラス sun.misc.Unsafe - Java で直接メモリ管理を実装できます (自己変更 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);
}
};
}
When working in Swing I like the hidden Ctrl - Shift - F1 feature.
It dumps the component tree of the current window.
(Assuming you have not bound that keystroke to something else.)
すべてのクラス ファイルは、有効な JVM バイトコードであることを識別するために、16 進値0xCAFEBABEで始まります。
(説明)
私の投票は、スレッドプール、スケジュールされたタスク、調整されたタスクを可能にする並行コレクションと柔軟なエグゼキューターを備えたjava.util.concurrentに投票します。DelayQueue は私の個人的なお気に入りで、指定された遅延の後に要素が利用可能になります。
java.util.Timer と TimerTask は安全に停止できます。
また、正確に隠されているわけではありませんが、日付と時刻に関連する他のクラスとは異なるパッケージにあります。java.util.concurrent.TimeUnit は、ナノ秒、マイクロ秒、ミリ秒、および秒の間で変換する場合に役立ちます。
通常の someValue * 1000 または someValue / 1000 よりもはるかに優れています。
言語レベルのassertキーワード。
Java 言語の一部ではありませんが、Sun の JDK に付属する javap 逆アセンブラーは、広く知られていないか、使用されていません。
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.misc.Unsafe クラスです。
http://www.docjar.com/html/api/ClassLib/Common/sun/misc/Unsafe.java.html
あなたはできる;
- コンストラクターを呼び出さずにオブジェクトを作成します。
- メソッドの throws 句を気にせずに Exception でも例外をスローします。(私が知っているこれを行う他の方法があります)
- リフレクションを使用せずに、オブジェクト内のランダムにアクセスされるフィールドを取得/設定します。
- サイズが長い(64ビット)メモリブロックを割り当て/解放/コピー/サイズ変更します。
- オブジェクト内のフィールドまたはクラス内の静的フィールドの場所を取得します。
- オブジェクト ロックを個別にロックおよびロック解除します。(ブロックなしで同期するように)
- 提供されたバイト コードからクラスを定義します。バイトコードがどうあるべきかをクラスローダーが決定するのではなく。(これはリフレクションでも実行できます)
ところで: このクラスを誤って使用すると、JVM が強制終了されます。このクラスをサポートする JVM がわからないため、移植性がありません。
これが私のリストです。
私のお気に入りの (そして最も恐ろしい) 隠れた機能は、何もスローすることを宣言していないメソッドからチェック例外をスローできることです。
import java.rmi.RemoteException;
class Thrower {
public static void spit(final Throwable exception) {
class EvilThrower<T extends Throwable> {
@SuppressWarnings("unchecked")
private void sneakyThrow(Throwable exception) throws T {
throw (T) exception;
}
}
new EvilThrower<RuntimeException>().sneakyThrow(exception);
}
}
public class ThrowerSample {
public static void main( String[] args ) {
Thrower.spit(new RemoteException("go unchecked!"));
}
}
また、「null」をスローできることを知りたい場合もあります...
public static void main(String[] args) {
throw null;
}
これが何を出力するかを推測してください:
Long value = new Long(0);
System.out.println(value.equals(0));
そして、これが何を返すかを推測してください:
public int returnSomething() {
try {
throw new RuntimeException("foo!");
} finally {
return 0;
}
}
上記は優れた開発者を驚かせるものではありません。
Java では、次の有効な方法で配列を宣言できます。
String[] strings = new String[] { "foo", "bar" };
// the above is equivalent to the following:
String[] strings = { "foo", "bar" };
したがって、次の Java コードは完全に有効です。
public class Foo {
public void doSomething(String[] arg) {}
public void example() {
String[] strings = { "foo", "bar" };
doSomething(strings);
}
}
代わりに、次のコードが有効であってはならない正当な理由はありますか?
public class Foo {
public void doSomething(String[] arg) {}
public void example() {
doSomething({ "foo", "bar" });
}
}
上記の構文は、Java 5 で導入された varargs の有効な代替手段であったと思います。また、以前に許可されていた配列宣言とより一貫性があります。
シャットダウンフック。これにより、すぐに作成され、JVM の終了時にのみ開始されるスレッドを登録できます。したがって、これはある種の「グローバル jvm ファイナライザー」であり、このスレッドで便利なものを作成できます (たとえば、組み込みの hsqldb サーバーのような Java リソースをシャットダウンします)。これは、System.exit()、または CTRL-C / kill -15 で機能します (もちろん、UNIX では kill -9 では機能しません)。
さらに、セットアップは非常に簡単です。
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
endApp();
}
});;
次の値:
new URL("http://www.yahoo.com").equals(new URL("http://209.191.93.52"))
ですtrue
。
(Java Puzzlers より)
多くの JavaBean 開発を行い、プロパティ変更サポートを使用する場合、通常、次のような多くのセッターを作成することになります。
public void setFoo(Foo aFoo){
Foo old = this.foo;
this.foo = aFoo;
changeSupport.firePropertyChange("foo", old, aFoo);
}
私は最近、コードをより簡単に記述できるようにする、これのより簡潔な実装を提案するブログに出くわしました。
public void setFoo(Foo aFoo){
changeSupport.firePropertyChange("foo", this.foo, this.foo = aFoo);
}
実際には、メソッドが自動的に作成されるように、Eclipse でセッター テンプレートを調整できるところまで単純化されました。
言語を「強化」するための静的インポート。これにより、タイプセーフな方法で文字通りの優れた処理を実行できます。
List<String> ls = List("a", "b", "c");
(マップ、配列、セットでも実行できます)。
http://gleichmann.wordpress.com/2008/01/13/building-your-own-literals-in-java-lists-and-arrays/
さらに進んで:
List<Map<String, String>> data = List(Map( o("name", "michael"), o("sex", "male")));
それほど隠されていませんが、興味深いです。
メインメソッドなしで「Hello、world」を持つことができます(NoSuchMethodErrorがスローされます)
RusselW がStrangest language featureに最初に投稿したもの
public class WithoutMain {
static {
System.out.println("Look ma, no main!!");
System.exit(0);
}
}
$ java WithoutMain
Look ma, no main!!
手始めとして、Java 6 の JConsole 監視ソフトウェアに本当に感謝しています。すでにいくつかの問題が解決されており、新しい用途を見つけ続けています。
どうやら JConsole は Java 5 に既に存在していたようですが、現在は改善されており、少なくとも現在はより安定して動作していると思います。
Java 5 のJConsole : Java 5 の JConsole
Java 6 のJConsole : Java 6 の JConsole
その間、シリーズの他のツールをよく見てください: Java 6 トラブルシューティング ツール
デフォルトのイニシャライザを使用しない場合、Java 処理は変数定義に対して巧妙なトリックを行います。
{ int x; もし(なんでも) x=1; 場合 (x == 1) ... }
これにより、コンパイル時に、X が適切に定義されていないパスがあるというエラーが発生します。これは私を数回助けてくれました。私は次のようなデフォルトの初期化を検討するようになりました:
int x=0; 文字列 s=null;
この有用なチェックをブロックするため、悪いパターンになることはありません。
そうは言っても、回避するのが難しい場合があります-デフォルトとして意味がある場合は、=null に戻って編集する必要がありましたが、最初のパスには入れませんでした。
これは実際には隠された機能ではありませんが、これが正常にコンパイルされているのを見ると、大きな驚きがありました。
public int aMethod(){
http://www.google.com
return 1;
}
コンパイルされる理由は、 http: //www.google.comの「http:」の部分がコンパイラによってラベルとして扱われ、残りの行がコメントであるためです。
したがって、奇妙なコード(または難読化されたコード)を記述したい場合は、そこにたくさんのhttpアドレスを配置するだけです。;-)
メソッドでクラスを宣言できます。
public Foo foo(String in) {
class FooFormat extends Format {
public Object parse(String s, ParsePosition pp) { // parse stuff }
}
return (Foo) new FooFormat().parse(in);
}
これに対するサポートを追加するのに十分な時間がかかりました。
私はJava1.6から書き直されたThreadingAPIが本当に好きです。Callablesは素晴らしいです。基本的には戻り値のあるスレッドです。
自己結合ジェネリック:
class SelfBounded<T extends SelfBounded<T>> {
}
Java コンソール ベースのアプリケーションのスプラッシュ スクリーンを表示できる機能。
コマンド ライン ツールを使用するjava
かjavaw
、オプションを使用して-splash
例えば:
java -splash:C:\myfolder\myimage.png -classpath myjarfile.jar com.my.package.MyClass
C:\myfolder\myimage.png
クラス「com.my.package.MyClass」を実行するたびに、画面の中央にコンテンツが表示されます
ああ、私はこの小さな宝石をほとんど忘れていました。実行中の Java プロセスでこれを試してください。
jmap -histo:ライブ PID
特定の VM 内のライブ ヒープ オブジェクトのヒストグラムを取得します。特定の種類のメモリ リークを迅速に把握するための非常に貴重な方法です。それらを防ぐために私が使用するもう 1 つの手法は、すべてのコレクション クラスのサイズ制限付きサブクラスを作成して使用することです。これにより、簡単に識別できる制御不能なコレクションで迅速な障害が発生します。
メソッドの静的インポートが好きです。
たとえば、次のユーティリティ クラスを作成します。
package package.name;
public class util {
private static void doStuff1(){
//the end
}
private static String doStuff2(){
return "the end";
}
}
あとはこんな感じで使います。
import static package.name.util.*;
public class main{
public static void main(String[] args){
doStuff1(); // wee no more typing util.doStuff1()
System.out.print(doStuff2()); // or util.doStuff2()
}
}
静的インポートは、数学を含むあらゆるクラスで機能します...
import static java.lang.Math.*;
import static java.lang.System.out;
public class HelloWorld {
public static void main(String[] args) {
out.println("Hello World!");
out.println("Considering a circle with a diameter of 5 cm, it has:");
out.println("A circumference of " + (PI * 5) + "cm");
out.println("And an area of " + (PI * pow(5,2)) + "sq. cm");
}
}
実際には機能ではありませんが、goto
javacに目を突くように促す以外に何もしない予約語であることに笑ってしまいます。あなたが今OO-landにいることを思い出させるために。
静的インポートを使用すると、次のようなクールなことを実行できます。
List<String> myList = list("foo", "bar");
Set<String> mySet = set("foo", "bar");
Map<String, String> myMap = map(v("foo", "2"), v("bar", "3"));
Javadoc - 適切に記述されている場合 (残念ながら一部の開発者には常に当てはまるとは限りません)、コードが実際に行うこととは対照的に、コードが行うべきことについて明確で首尾一貫した説明が得られます。その後、見栄えの良い HTML ドキュメントのセットに変換できます。継続的インテグレーションなどを使用すると、定期的に生成できるため、すべての開発者が最新の更新を確認できます。
匿名の内部クラスでメソッドを定義して呼び出すことができます。
それほど隠されているわけではありませんが、クラスで新しいメソッドを定義し、次のように呼び出すために使用できることを知っている人はほとんどいません。
(new Object() {
public String someMethod(){
return "some value";
}
}).someMethod();
あまり有用ではないため、おそらくあまり一般的ではありません。メソッドを定義する場合にのみ(またはリフレクションを介して)メソッドを呼び出すことができます
strictfp キーワード。(実際のアプリケーションで使用されているのを見たことはありません:)
int.class、float.class などの表記を使用して、プリミティブ型のクラスを取得できます。リフレクションを行うときに非常に便利です。
final 配列を使用して、匿名の内部クラスから値を「返す」ことができます (警告、以下の役に立たない例):
final boolean[] result = new boolean[1];
SwingUtilities.invokeAndWait(new Runnable() {
public void run() { result[0] = true; }
});
C スタイルの printf() :)
System.out.printf("%d %f %.4f", 3,Math.E,Math.E);
出力: 3 2.718282 2.7183
二分探索 (およびその戻り値)
int[] q = new int[] { 1,3,4,5};
int position = Arrays.binarySearch(q, 2);
C# と同様に、配列に「2」が見つからない場合は負の値を返しますが、返された値の 1 の補数を取ると、実際に「2」を挿入できる位置を取得します。
上記の例では、position = -2, ~position = 1 は、2 を挿入する位置です...これにより、配列内で「最も近い」一致を見つけることもできます。
私はそのかなり気の利いたと思います... :)
Java 6 にスクリプトのサポートが含まれていることは知っていましたが、最近発見したjrunscriptは、Python シェルや Ruby の irb のように、JavaScript (および、Groovy などの他のスクリプト言語) を対話的に解釈して実行できます。
これがリリース 1.5 で追加されたことは知っていますが、新しい列挙型は優れた機能です。古い「int 列挙型パターン」を使用する必要がなくなったことで、多くのコードが大幅に改善されました。 じゃがいもの甘い肉汁については、JLS 8.9 をチェックしてください。
完全に隠されているわけではありませんが、リフレクションは信じられないほど便利で強力です。クラスタイプが構成可能な単純な Class.forName("...").newInstance() を使用するのは素晴らしいことです。この種のファクトリ実装を書くのは簡単です。
一部の機能、一部の煩わしさ: Java の文字列処理により、ネイティブ タイプとして「表示」されます (演算子 +、+= の使用)。
書くことができること:
String s = "A";
s += " String"; // so s == "A String"
は非常に便利ですが、単に構文糖衣です (つまり、コンパイルされます):
String s = new String("A");
s = new StringBuffer(s).append(" String").toString();
したがって、単純な連結のためのオブジェクトのインスタンス化と 2 つのメソッド呼び出し。この方法でループ内に長い文字列を構築することを想像してみてください!? AND StringBuffer のすべてのメソッドが同期されていると宣言されている。ありがたいことに(私が思うに)Java 5では、同期なしでStringBufferと同一のStringBuilderを導入しました。
次のようなループ:
String s = "";
for (int i = 0 ; i < 1000 ; ++i)
s += " " + i; // Really an Object instantiation & 3 method invocations!
コードで次のように書き換えることができます(する必要があります)。
StringBuilder buf = new StringBuilder(); // Empty buffer
for (int i = 0 ; i < 1000 ; ++i)
buf.append(' ').append(i); // Cut out the object instantiation & reduce to 2 method invocations
String s = buf.toString();
元のループよりも約 80% 以上高速に実行されます。(私が実行したいくつかのベンチマークでは最大 180%)
インスタンス変数の最終:
マルチスレッド コードに非常に役立ち、インスタンスの状態と正確性について議論するのがずっと簡単になります。業界のコンテキストでそれをあまり見たことがなく、Java クラスで考えたことがないことがよくあります。
静的 {何か;}:
静的メンバーを初期化するために使用されます(また、静的メソッドを使用することを好みます(名前があるため)。考えられません。
私は今日、$ が Java のメソッドまたは変数の正式な名前であることを (再) 学びました。静的インポートと組み合わせることで、読みやすさの見方に応じて、コードを少し読みやすくすることができます。
に含まれる同期管理が不要な場合は、StringBuilder
代わりに使用します。アプリケーションのパフォーマンスが向上します。StringBuffer
StringBuilder
Java 7 の改善は、隠された Java 機能よりもさらに優れています。
- ひし形の構文: リンク
インスタンス化時にこれらの無限の <> 構文を使用しないでください。
Map<String, List<String>> anagrams = new HashMap<String, List<String>>();
// Can now be replaced with this:
Map<String, List<String>> anagrams = new HashMap<>();
- スイッチ内の文字列: リンク
古い C の int の代わりに、スイッチで String を使用します。
String s = "something";
switch(s) {
case "quux":
processQuux(s);
// fall-through
case "foo":
case "bar":
processFooOrBar(s);
break;
case "baz":
processBaz(s);
// fall-through
default:
processDefault(s);
break;
}
- 自動リソース管理 リンク
この古いコード:
static void copy(String src, String dest) throws IOException {
InputStream in = new FileInputStream(src);
try {
OutputStream out = new FileOutputStream(dest);
try {
byte[] buf = new byte[8 * 1024];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
} finally {
out.close();
}
} finally {
in.close();
}
}
次のはるかに単純なコードに置き換えることができます。
static void copy(String src, String dest) throws IOException {
try (InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dest)) {
byte[] buf = new byte[8192];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
}
}
「const」はキーワードですが、使用できません。
int const = 1; // "not a statement"
const int i = 1; // "illegal start of expression"
コンパイラの作成者は、将来使用される可能性があると考えていたので、予約しておく方がよいと思います。
Scannerオブジェクトを追加できます。構文解析に最適です。
String input = "1 fish 2 fish red fish blue fish";
Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*");
System.out.println(s.nextInt());
System.out.println(s.nextInt());
System.out.println(s.next());
System.out.println(s.next());
s.close();
私が本当に驚いたのは、カスタムのシリアル化メカニズムでした。
これらのメソッドはプライベートですが!! 、オブジェクトのシリアル化中にJVMによって「不思議なことに」呼び出されます。
private void writeObject(ObjectOutputStream out) throws IOException;
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;
このようにして、独自のカスタムシリアル化を作成して、より「何でも」(安全、高速、まれ、簡単など)にすることができます。
これは、多くの情報をノードに渡す必要がある場合に本当に考慮すべきことです。シリアル化メカニズムは、データの半分を送信するように変更される場合があります。ボトルネックがプラットフォームにない場合が多くありますが、ネットワークを介して送信されるボトルネックの量で、ハードウェアに何千ものdllを節約できる可能性があります。
こちらが記事です。 http://java.sun.com/developer/technicalArticles/Programming/serialization/
識別子には、ウムラウトなどの外国語の文字を含めることができます。
書く代わりに:
String title="";
誰かが書くことができます:
String Überschrift="";
選択したエンコーディングのプロパティ ファイルはどうですか? 以前は、プロパティをロードするときに InputStream を提供し、load()
メソッドはそれを ISO-8859-1 としてデコードしていました。実際にはファイルを他のエンコーディングで保存することもできますが、データを適切にデコードするには、ロード後に次のような嫌なハックを使用する必要がありました。
String realProp = new String(prop.getBytes("ISO-8859-1"), "UTF-8");
しかし、JDK 1.6 の時点でload()
は、InputStream の代わりに Reader を取るメソッドがあります。つまり、最初から正しいエンコーディングを使用できます ( store()
Writer を取るメソッドもあります)。これは私にはかなり大したことのように思えますが、JDK に何の宣伝もなしに忍び込まれたようです。ほんの数週間前に偶然見つけたのですが、Google で簡単に検索したところ、ほんの 1 つしか言及されていませんでした。
ほとんどの人は、アレイを複製できることを知りません。
int[] arr = {1, 2, 3};
int[] arr2 = arr.clone();
プライベート メソッドを呼び出し、リフレクションを使用してプライベート フィールドにアクセス/変更できることに気付いたとき、人々は少し驚くことがあります...
次のクラスを検討してください。
public class Foo {
private int bar;
public Foo() {
setBar(17);
}
private void setBar(int bar) {
this.bar=bar;
}
public int getBar() {
return bar;
}
public String toString() {
return "Foo[bar="+bar+"]";
}
}
このプログラムを実行しています...
import java.lang.reflect.*;
public class AccessibleExample {
public static void main(String[] args)
throws NoSuchMethodException,IllegalAccessException, InvocationTargetException, NoSuchFieldException {
Foo foo=new Foo();
System.out.println(foo);
Method method=Foo.class.getDeclaredMethod("setBar", int.class);
method.setAccessible(true);
method.invoke(foo, 42);
System.out.println(foo);
Field field=Foo.class.getDeclaredField("bar");
field.setAccessible(true);
field.set(foo, 23);
System.out.println(foo);
}
}
...次の出力が得られます。
Foo[bar=17]
Foo[bar=42]
Foo[bar=23]
Java 6 の Annotation Processing API は、コード生成と静的コード検証の観点から非常に優れています。
実際、私が Java で気に入っているのは、隠れたトリックがほとんどないことです。とても分かりやすい言語です。15年経った今、私が思いつくほぼすべてのものがすでにこれらの数ページにリストされているほどです.
ほとんどの人は Collections.synchronizedList() がリストに同期を追加することを知っているでしょう。ドキュメントを読まないとわからないことは、リスト オブジェクト自体を同期することで、そのリストの要素を安全に反復処理できるということです。
CopyOnWriteArrayList は知らない人もいるかもしれませんが、Future はマルチスレッドの結果アクセスを抽象化する興味深い方法を表しています。
VM (ローカルまたはリモート) にアタッチし、さまざまな管理、エージェント、アタッチ API を介して、GC アクティビティ、メモリ使用、ファイル記述子、さらにはオブジェクト サイズに関する情報を取得できます。
TimeUnit はおそらく long よりも優れていますが、私は Wicket の Duration クラスを好みます。
String.format() を使用して、文字列 sprintf スタイルを構築できます。
String w = "world";
String s = String.format("Hello %s %d", w, 3);
もちろん、特別な指定子を使用して出力を変更することもできます。
詳細はこちら: http://java.sun.com/j2se/1.5.0/docs/api/java/util/Formatter.html#syntax
ローカル クラスの初期化ブロックとメソッドで、最終的なローカル変数とパラメーターにアクセスできます。このことを考慮:
final String foo = "42";
new Thread() {
public void run() {
dowhatever(foo);
}
}.start();
閉鎖のようなものですね。
ガベージ コレクタとガベージ コレクタによるオブジェクト コレクションの管理方法は非常に強力で、長時間実行される時間に敏感なアプリケーションでは特に有効です。それは、java.lang.ref パッケージの弱参照、ソフト参照、ファントム参照から始まります。特にキャッシュを構築するために、それらを見てください(すでに java.util.WeakHashMap があります)。ここで、ReferenceQueue をもう少し深く掘り下げると、さらに詳細に制御できるようになります。最後に、ガベージ コレクター自体のドキュメントを取得すると、実行頻度、さまざまなコレクション領域のサイズ、および使用されるアルゴリズムの種類を制御できるようになります (Java 5 については、http://java.sun.com/docsを参照してください)。 /hotspot/gc5.0/gc_tuning_5.html )。
JDK ディストリビューションの bin ディレクトリにある JVisualVM。特別なパラメーターを使用して起動していない Java アプリケーションを監視し、プロファイリングすることもできます。Java 6SE JDK の最近のバージョンのみ。
ソース コードの URL。たとえば、これは合法的な Java ソース コードです。
http://google.com
(はい、それは Java Puzzlers にありました。私は笑いました...)
ステートメントに関するいくつかfinally
の制御フローのトリック:return
int getCount() {
try { return 1; }
finally { System.out.println("Bye!"); }
}
明確な割り当てのルールは、単純な制御フロー分析を通じて、最終的な変数が常に割り当てられていることを確認します。
final int foo;
if(...)
foo = 1;
else
throw new Exception();
foo+1;
これについて読んでいない
Integer a = 1;
Integer b = 1;
Integer c = new Integer(1);
Integer d = new Integer(1);
Integer e = 128;
Integer f = 128;
assertTrue (a == b); // again: this is true!
assertFalse(e == f); // again: this is false!
assertFalse(c == d); // again: this is false!
Javaの整数のプール(オートボクシング用の-128から127までの内部「キャッシュ」)を検索するか、Integer.valueOfを調べて、これについて詳しく読んでください
Joshua Bloch の新しい「Effective Java 」は、優れたリソースです。
文字列パラメータ化クラスファクトリ。
Class.forName( className ).newInstance();
デプロイメントjarファイルからリソース(プロパティファイル、xml、xslt、イメージなど)をロードします。
this.getClass().getClassLoader().getResourceAsStream( ... ) ;
final 配列を使用して、匿名の内部クラスから変数を渡すことができることは既に述べました。
別の、間違いなくより良くて見苦しくないアプローチは、java.util.concurrent.atomic パッケージの AtomicReference (または AtomicBoolean/AtomicInteger/…) クラスを使用することです。
そうする利点の 1 つは、これらのクラスが などのメソッドも提供するcompareAndSet
ことです。これは、同じ変数を変更できる複数のスレッドを作成する場合に役立ちます。
別の便利な関連パターン:
final AtomicBoolean dataMsgReceived = new AtomicBoolean(false);
final AtomicReference<Message> message = new AtomicReference<Message>();
withMessageHandler(new MessageHandler() {
public void handleMessage(Message msg) {
if (msg.isData()) {
synchronized (dataMsgReceived) {
message.set(msg);
dataMsgReceived.set(true);
dataMsgReceived.notifyAll();
}
}
}
}, new Interruptible() {
public void run() throws InterruptedException {
synchronized (dataMsgReceived) {
while (!dataMsgReceived.get()) {
dataMsgReceived.wait();
}
}
}
});
この特定の例では、メッセージが非 null になるのを単純に待つことができますが、多くの場合 null は有効な値であり、別のフラグを使用して待機を終了する必要があります。
waitMessageHandler(…)
上記はさらに別の便利なパターンです。どこかにハンドラーを設定し、例外をスローする可能性のあるInterruptibleの実行を開始し、finally ブロック内のハンドラーを次のように削除します。
private final AtomicReference<MessageHandler> messageHandler = new AtomicReference<MessageHandler>();
public void withMessageHandler(MessageHandler handler, Interruptible logic) throws InterruptedException {
synchronized (messageHandler) {
try {
messageHandler.set(handler);
logic.run();
} finally {
messageHandler.set(null);
}
}
}
ここでは、メッセージが受信されたときにmessageHandlerの (null でない場合)handleMessage(…)
メソッドが別のスレッドによって呼び出されると想定しています。messageHandlerは単純にMessageHandler型であってはなりません: そうすれば、変化する変数で同期することになりますが、これは明らかにバグです。
もちろん、InterruptedExceptionである必要はありません。 IOExceptionなど、特定のコードで意味のあるものであれば何でもかまいません。
交差タイプを使用すると、(ちょっとした)継承階層を持つ列挙型を実行できます。実装を継承することはできませんが、ヘルパー クラスに委譲することはできます。
enum Foo1 implements Bar {}
enum Foo2 implements Bar {}
class HelperClass {
static <T extends Enum<T> & Bar> void fooBar(T the enum) {}
}
これは、ある種のパターンを実装する多数の異なる列挙型がある場合に便利です。たとえば、親子関係を持ついくつかの列挙型のペア。
enum PrimaryColor {Red, Green, Blue;}
enum PastelColor {Pink, HotPink, Rockmelon, SkyBlue, BabyBlue;}
enum TransportMedium {Land, Sea, Air;}
enum Vehicle {Car, Truck, BigBoat, LittleBoat, JetFighter, HotAirBaloon;}
「OK、他の列挙値の親である列挙値が与えられた場合、子型の可能なすべての子列挙型のうち、この特定の親値を親として持つ割合は何パーセントですか?」という汎用メソッドを記述できます。タイプセーフで、キャストせずに実行されます。(例: 「海」は考えられるすべての車両の 33%、「緑」は考えられるすべてのパステルの 20% です)。
コードは次のようになります。かなり厄介ですが、改善する方法はあります。特に、「リーフ」クラス自体は非常にきちんとしていることに注意してください。ジェネリック クラスには恐ろしく醜い宣言がありますが、一度しか記述しません。ジェネリック クラスがあれば、それらを使用するのは簡単です。
import java.util.EnumSet;
import javax.swing.JComponent;
public class zz extends JComponent {
public static void main(String[] args) {
System.out.println(PrimaryColor.Green + " " + ParentUtil.pctOf(PrimaryColor.Green) + "%");
System.out.println(TransportMedium.Air + " " + ParentUtil.pctOf(TransportMedium.Air) + "%");
}
}
class ParentUtil {
private ParentUtil(){}
static <P extends Enum<P> & Parent<P, C>, C extends Enum<C> & Child<P, C>> //
float pctOf(P parent) {
return (float) parent.getChildren().size() / //
(float) EnumSet.allOf(parent.getChildClass()).size() //
* 100f;
}
public static <P extends Enum<P> & Parent<P, C>, C extends Enum<C> & Child<P, C>> //
EnumSet<C> loadChildrenOf(P p) {
EnumSet<C> cc = EnumSet.noneOf(p.getChildClass());
for(C c: EnumSet.allOf(p.getChildClass())) {
if(c.getParent() == p) {
cc.add(c);
}
}
return cc;
}
}
interface Parent<P extends Enum<P> & Parent<P, C>, C extends Enum<C> & Child<P, C>> {
Class<C> getChildClass();
EnumSet<C> getChildren();
}
interface Child<P extends Enum<P> & Parent<P, C>, C extends Enum<C> & Child<P, C>> {
Class<P> getParentClass();
P getParent();
}
enum PrimaryColor implements Parent<PrimaryColor, PastelColor> {
Red, Green, Blue;
private EnumSet<PastelColor> children;
public Class<PastelColor> getChildClass() {
return PastelColor.class;
}
public EnumSet<PastelColor> getChildren() {
if(children == null) children=ParentUtil.loadChildrenOf(this);
return children;
}
}
enum PastelColor implements Child<PrimaryColor, PastelColor> {
Pink(PrimaryColor.Red), HotPink(PrimaryColor.Red), //
Rockmelon(PrimaryColor.Green), //
SkyBlue(PrimaryColor.Blue), BabyBlue(PrimaryColor.Blue);
final PrimaryColor parent;
private PastelColor(PrimaryColor parent) {
this.parent = parent;
}
public Class<PrimaryColor> getParentClass() {
return PrimaryColor.class;
}
public PrimaryColor getParent() {
return parent;
}
}
enum TransportMedium implements Parent<TransportMedium, Vehicle> {
Land, Sea, Air;
private EnumSet<Vehicle> children;
public Class<Vehicle> getChildClass() {
return Vehicle.class;
}
public EnumSet<Vehicle> getChildren() {
if(children == null) children=ParentUtil.loadChildrenOf(this);
return children;
}
}
enum Vehicle implements Child<TransportMedium, Vehicle> {
Car(TransportMedium.Land), Truck(TransportMedium.Land), //
BigBoat(TransportMedium.Sea), LittleBoat(TransportMedium.Sea), //
JetFighter(TransportMedium.Air), HotAirBaloon(TransportMedium.Air);
private final TransportMedium parent;
private Vehicle(TransportMedium parent) {
this.parent = parent;
}
public Class<TransportMedium> getParentClass() {
return TransportMedium.class;
}
public TransportMedium getParent() {
return parent;
}
}
Joshua Bloch 著の「Java Puzzlers」を読めば、啓発と恐怖の両方が得られます。
同じクラスのインスタンスは、他のインスタンスのプライベート メンバーにアクセスできます。
class Thing {
private int x;
public int addThings(Thing t2) {
return this.x + t2.x; // Can access t2's private value!
}
}
Java 6 (Sun 製) には、JavaScrip インタープリターが組み込まれています。
http://java.sun.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.html#jsengine
コンマと配列。これは正当な構文です: String s[] = {
"123" ,
"234" ,
};
オブジェクトを使用してジェネリック型の実行時チェックを追加できますClass<T>
。これは、クラスがどこかの構成ファイルで作成されており、クラスのジェネリック型のコンパイル時チェックを追加する方法がない場合に便利です。アプリがたまたま間違って構成されていて、すべてのクラスがチェックのインスタンスでいっぱいになりたくない場合に、実行時にクラスが爆発することは望ましくありません。
public interface SomeInterface {
void doSomething(Object o);
}
public abstract class RuntimeCheckingTemplate<T> {
private Class<T> clazz;
protected RuntimeChecking(Class<T> clazz) {
this.clazz = clazz;
}
public void doSomething(Object o) {
if (clazz.isInstance(o)) {
doSomethingWithGeneric(clazz.cast(o));
} else {
// log it, do something by default, throw an exception, etc.
}
}
protected abstract void doSomethingWithGeneric(T t);
}
public class ClassThatWorksWithStrings extends RuntimeCheckingTemplate<String> {
public ClassThatWorksWithStrings() {
super(String.class);
}
protected abstract void doSomethingWithGeneric(T t) {
// Do something with the generic and know that a runtime exception won't occur
// because of a wrong type
}
}
列挙型クラスのメソッド定義内で(this)を切り替えることができます。「うわっ!」と叫びました。これが実際に機能することを発見したとき、大声で。
一部のデバッグ ビルドには、HotSpot からネイティブ (JIT) アセンブリ コードをダンプするオプションがあるようです。
残念ながら、その投稿のリンクからビルドを見つけることができませんでした。誰かがより正確な URL を見つけることができれば、ぜひ試してみたいと思います。
ファンクターはとてもクールです。それらは関数ポインタに非常に近く、Java では不可能だと誰もがすぐに言います。
SwingWorker for easily managing user interface callbacks from background threads.
数年前、私が Java (1.4.x) をしなければならなかったとき、私は eval() メソッドが欲しかったのですが、Suns の javac は Java で書かれていた (だった?) ので、tools.jar をリンクして、それをいくつかのグルーコードで使用するだけでした。それ。
他の誰もまだ言っていないので(私は思う)、私のお気に入りの機能はオートボクシングです!
public class Example
{
public static void main(String[] Args)
{
int a = 5;
Integer b = a; // Box!
System.out.println("A : " + a);
System.out.println("B : " + b);
}
}
メソッドをオーバーライドして、スーパークラス コンストラクターにそれを呼び出させることができます (これは、C++ プログラマーを驚かせるかもしれません)。
Java Bean プロパティのアクセサ メソッドは、「get」および「set」で開始する 必要はありません。
Josh Bloch でさえ、Effective Java でこれを誤解しています。
単純なif-then-elseステートメントに等しい三項演算子に最初に気付いたとき、私は驚きました。
minVal = (a < b) ? a : b;
インターフェイスは複数のインターフェイスを拡張できますが、クラスは 1 つのクラスしか拡張できないことに驚きました。