Java 7のDa Vinci Machine Projectと自転車との戦い

こんにちは、ハラジテリ!



ごく最近、多くの人が期待するJava 7がリリースされました。 残念なことに、多くの人はイノベーションの構成に失望しました。ProjectLambdaのような非常に期待されるさまざまなグッズが含まれていなかったからです。 しかし、まだ多くの革新があり、今日では、最も重要なものの1つであるDa Vinci Machine Projectについて説明します。これにより、JVMで動的言語をより効率的に使用できます。 より正確には、Da Vinci Machine Projectの一部であるメソッドハンドルを検討します。 私はまだ言語のこの部分の概念を完全に理解することができていませんが、ほとんどの人はなぜそれが必要なのか理解していません:)この記事では、Javaプログラマーがこれまでにない最大数の自転車に精通していない1つのユースケースを検討します。 もちろん、メソッドをオーバーロードし、インターフェイスでパラメーターを渡すことに関するものです。



Javaでは、どのオーバーロードメソッドを呼び出すかは、コンパイル段階で決定されることが知られています(たとえば、実行時に行われるC#とは対照的です)。 次のコードがあるとします:

class A { } class B extends A { } public class Test { public void call(A a) { System. out .println( "A" ); } public void call(B b) { System. out .println( "B" ); } public static void main( String [] argv) { A b = new B(); Test test = new Test(); test.call(b); } } * This source code was highlighted with Source Code Highlighter .



  1. class A { } class B extends A { } public class Test { public void call(A a) { System. out .println( "A" ); } public void call(B b) { System. out .println( "B" ); } public static void main( String [] argv) { A b = new B(); Test test = new Test(); test.call(b); } } * This source code was highlighted with Source Code Highlighter .



  2. class A { } class B extends A { } public class Test { public void call(A a) { System. out .println( "A" ); } public void call(B b) { System. out .println( "B" ); } public static void main( String [] argv) { A b = new B(); Test test = new Test(); test.call(b); } } * This source code was highlighted with Source Code Highlighter .



  3. class A { } class B extends A { } public class Test { public void call(A a) { System. out .println( "A" ); } public void call(B b) { System. out .println( "B" ); } public static void main( String [] argv) { A b = new B(); Test test = new Test(); test.call(b); } } * This source code was highlighted with Source Code Highlighter .



  4. class A { } class B extends A { } public class Test { public void call(A a) { System. out .println( "A" ); } public void call(B b) { System. out .println( "B" ); } public static void main( String [] argv) { A b = new B(); Test test = new Test(); test.call(b); } } * This source code was highlighted with Source Code Highlighter .



  5. class A { } class B extends A { } public class Test { public void call(A a) { System. out .println( "A" ); } public void call(B b) { System. out .println( "B" ); } public static void main( String [] argv) { A b = new B(); Test test = new Test(); test.call(b); } } * This source code was highlighted with Source Code Highlighter .



  6. class A { } class B extends A { } public class Test { public void call(A a) { System. out .println( "A" ); } public void call(B b) { System. out .println( "B" ); } public static void main( String [] argv) { A b = new B(); Test test = new Test(); test.call(b); } } * This source code was highlighted with Source Code Highlighter .



  7. class A { } class B extends A { } public class Test { public void call(A a) { System. out .println( "A" ); } public void call(B b) { System. out .println( "B" ); } public static void main( String [] argv) { A b = new B(); Test test = new Test(); test.call(b); } } * This source code was highlighted with Source Code Highlighter .



  8. class A { } class B extends A { } public class Test { public void call(A a) { System. out .println( "A" ); } public void call(B b) { System. out .println( "B" ); } public static void main( String [] argv) { A b = new B(); Test test = new Test(); test.call(b); } } * This source code was highlighted with Source Code Highlighter .



  9. class A { } class B extends A { } public class Test { public void call(A a) { System. out .println( "A" ); } public void call(B b) { System. out .println( "B" ); } public static void main( String [] argv) { A b = new B(); Test test = new Test(); test.call(b); } } * This source code was highlighted with Source Code Highlighter .



  10. class A { } class B extends A { } public class Test { public void call(A a) { System. out .println( "A" ); } public void call(B b) { System. out .println( "B" ); } public static void main( String [] argv) { A b = new B(); Test test = new Test(); test.call(b); } } * This source code was highlighted with Source Code Highlighter .



  11. class A { } class B extends A { } public class Test { public void call(A a) { System. out .println( "A" ); } public void call(B b) { System. out .println( "B" ); } public static void main( String [] argv) { A b = new B(); Test test = new Test(); test.call(b); } } * This source code was highlighted with Source Code Highlighter .



  12. class A { } class B extends A { } public class Test { public void call(A a) { System. out .println( "A" ); } public void call(B b) { System. out .println( "B" ); } public static void main( String [] argv) { A b = new B(); Test test = new Test(); test.call(b); } } * This source code was highlighted with Source Code Highlighter .



  13. class A { } class B extends A { } public class Test { public void call(A a) { System. out .println( "A" ); } public void call(B b) { System. out .println( "B" ); } public static void main( String [] argv) { A b = new B(); Test test = new Test(); test.call(b); } } * This source code was highlighted with Source Code Highlighter .



  14. class A { } class B extends A { } public class Test { public void call(A a) { System. out .println( "A" ); } public void call(B b) { System. out .println( "B" ); } public static void main( String [] argv) { A b = new B(); Test test = new Test(); test.call(b); } } * This source code was highlighted with Source Code Highlighter .



  15. class A { } class B extends A { } public class Test { public void call(A a) { System. out .println( "A" ); } public void call(B b) { System. out .println( "B" ); } public static void main( String [] argv) { A b = new B(); Test test = new Test(); test.call(b); } } * This source code was highlighted with Source Code Highlighter .



  16. class A { } class B extends A { } public class Test { public void call(A a) { System. out .println( "A" ); } public void call(B b) { System. out .println( "B" ); } public static void main( String [] argv) { A b = new B(); Test test = new Test(); test.call(b); } } * This source code was highlighted with Source Code Highlighter .



  17. class A { } class B extends A { } public class Test { public void call(A a) { System. out .println( "A" ); } public void call(B b) { System. out .println( "B" ); } public static void main( String [] argv) { A b = new B(); Test test = new Test(); test.call(b); } } * This source code was highlighted with Source Code Highlighter .



class A { } class B extends A { } public class Test { public void call(A a) { System. out .println( "A" ); } public void call(B b) { System. out .println( "B" ); } public static void main( String [] argv) { A b = new B(); Test test = new Test(); test.call(b); } } * This source code was highlighted with Source Code Highlighter .





Javaルールに従って、 public void call(A a)



メソッドが呼び出され、それに応じて「A」が表示されます。これは、オブジェクトの実際のタイプがB



であるため、奇妙に見えるかもしれませんB



必要なメソッドを呼び出すには、次のようにメソッドを呼び出すようにコードを書き換える必要があります。





  1. if (b instanceof B){
  2. test.call((B)b);
  3. }
*このソースコードは、 ソースコードハイライターで強調表示されました。




このアプローチには生命権がありますが、そのようなクラスが数十個ある場合、コードは見苦しくなり、一般的に重複が発生します。



Java 7は、この問題を解決するのに役立つツールを導入しました。言語レベルでなければ、少なくとも松葉杖のレベルではありません。 したがって、 java.lang.invoke



パッケージのクラスが役立ちjava.lang.invoke







だから、私たちは最も興味深いものに移ります-これがすべて私たちを助けるか。 これで、コードは次のようになります。





  1. import static java.lang.invoke.MethodHandles。*;
  2. import java.lang.invoke.MethodHandle;
  3. import java.lang.invoke.MethodType;
  4. クラス A {
  5. }
  6. クラス BはAを拡張します{
  7. }
  8. パブリック クラステスト{
  9. public void call(A a){
  10. システム out .println( "A" );
  11. }
  12. public void call(B b){
  13. システム out .println( "B" );
  14. }
  15. public static void main( String [] argv){
  16. A b = new B();
  17. テストテスト= 新しいテスト();
  18. {
  19. ルックアップルックアップ= lookup();
  20. MethodType mt = MethodType.methodType(void。Class、b.getClass());
  21. MethodHandle mh = lookup.findVirtual(Test。Class、 "call" 、mt);
  22. mh.invokeWithArguments(test、b);
  23. } catch (Throwable e){
  24. e.printStackTrace();
  25. }
  26. }
  27. }
*このソースコードは、 ソースコードハイライターで強調表示されました。


ここで何が起こるか見てみましょう。 27行目で、関数の「検索エンジン」を直接宣言します。 次に、28行目で、戻り値とパラメーターの型を宣言します。 戻り値の型が最初にmethodType



メソッドに渡され、次に検索するメソッドのパラメーターリストの型が渡されることに注意することが重要です。 30行目MethodHandle



で、 Test



クラスのメソッドの検索結果を、名前call



および戻り値の型とmt



パラメーターと共に取得します。 31行目では、 test



オブジェクトで見つかったメソッドをパラメーターb



呼び出して、画面に期待される「B」を確認します。



Lookup



クラスには、静的関数を検索するためのメソッドなど、まだかなりの数のメソッドがありますが、機能の研究は宿題として読者に残っています。



All Articles