Java変態?コード最速マスター
Java変態文法最速マスター - プログラマーの脳みそが面白かった && 参考になったので便乗してリスペクト。変態世間であまり見かけない(かも知れない)Javaコードを、過去のエントリからまとめてみました。
nullでなければループ
「配列がnullでなければループ」というシーンはまれにありますが、nullチェックのためにインデントが深くなるのが我慢ならん、というときにこういう記述はどうでしょう。
String[] strs = // 略 // 配列がnullでなければ各要素に対して処理を実行 if ( strs != null ) for ( String str : strs ) { // 処理 }
if文の「{}」を省略してforを繋げているだけですが、インデントをさりげなく削れます。
似たような例で、「例外を無視して次へ」とかも。
// 例外が発生しても無視して次へ for ( String str : strs ) try { // 処理 } catch ( Exception e ) {}
ちなみに、これはできそうでできません。(synchronized はステートメントを受け付けない。)
synchronized( lock ) if ( obj == null ) { // 処理 }
see : http://d.hatena.ne.jp/unageanu/20090819/1250678246
see : http://d.hatena.ne.jp/unageanu/20090422/1240402184
インターフェイスに実装を書く
無名クラスを使うことでインターフェイスにも実装を書けます。インターフェイスは切っておきたいけど、XXXImpl.javaを別に用意するのはメンドイ、というときに使えます。
import java.io.File; /** * 一時ファイルディレクトリ解決サービス */ public interface TemporaryDirectoryService { /** * 一時ファイルディレクトリを取得する。 * @return 一時ファイルディレクトリ */ File getTemporaryDirectory(); /** * {@link TemporaryDirectoryService}のデフォルト実装。 */ TemporaryDirectoryService DEFAULT = new TemporaryDirectoryService () { public File getTemporaryDirectory() { String path = System.getProperty( "tmpfolder", "/tmp" ); return new File(path); } }; }
インターフェイスでstaticブロック
↑と似たようなネタですが、無名クラス+インスタンスイニシャライザで、インターフェイスにstaticブロックを作ったりも。
public interface Foo { ...略 /** 必要なシステムプロパティを設定。*/ Object INIT = new Object(){{ System.setProperty( "foo", "var" ); }}; }
Javaでcallee
JDK5からですが、無名クラスからそれを定義したメソッドの参照を取得できるようになったので、Javaでもcalleeが可能になっています。
/** * メソッド自身を取得する。 * @param o メソッド内で作成した無名クラス * @return メソッド自身 */ static Method callee( Object o ) { return o.getClass().getEnclosingMethod(); } /** * currentが10になるまで再帰する関数。 * @param current */ static void count( int current ) { System.out.println( current ); if ( current >= 10 ) { return ; } else { try { // メソッド自身を取得する。 callee( new Object(){} ).invoke( null, current+1 ); } catch ( Exception e ) { e.printStackTrace(); return; } } }
「new Object(){}」でさりげなく無名クラスを生成するのがポイントかな。「ログ出力時に操作名(メソッド名)を出力しろ」とかいう場合のメソッド名取得に使えないかと画策中。
共通の上位クラスを探す。
「推論の元になる引数が複数ある場合、共通の親クラスが使われる」ことを利用して、共通の上位クラスを探す関数を作れます。
// 引数の共通の親クラスを返す。 static <X> Class<?> test( X... args ) { return args.getClass().getComponentType(); } .... public static void main( String[] args ) { System.out.println( test( "a" ) ); // String System.out.println( test( "", new Object() ) ); // Object System.out.println( test( 1, 1D ) ); // Number System.out.println( test( new IOException(), new RuntimeException() ) ); // Exception }
実行結果です。
class java.lang.String class java.lang.Object class java.lang.Number class java.lang.Exception
複数のインターフェイスを実装したオブジェクトのみ受け付けるAPI
これは有名かもですが、型パラメータで「&」を使うことで「複数のインターフェイスを実装したクラス」を記述できます。
/** * {@link XMLReader}を作成する * @param handler SAXハンドラ * @return {@link XMLReader} * @throws SAXException * @throws ParserConfigurationException */ static final <H extends DTDHandler & DeclHandler & LexicalHandler & ContentHandler> XMLReader createReader( H handler ) throws SAXException, ParserConfigurationException { SAXParserFactory factory = SAXParserFactory.newInstance(); factory.setNamespaceAware(true); XMLReader r = factory.newSAXParser().getXMLReader(); r.setContentHandler( handler ); r.setDTDHandler( handler ); r.setProperty( "http://xml.org/sax/properties/lexical-handler", handler ); r.setProperty( "http://xml.org/sax/properties/declaration-handler", handler ); return r; }
see: http://d.hatena.ne.jp/unageanu/20071022/1193060612
といったところかな。個人的には仕事で普通に使っているので、みかけても引かないでくださいね > 関係者。