2015-01-07 3 views
7

私はこのコードを持っています。なぜそれは機能しないのですか?(それが表示する作業の意味3)どうすれば修正できますか?javaアクセスリフレクションを通して整数コンストラクタ

public class Main { 
    public static<V> V copy(V var){ 
     try{ 
      return (V) var.getClass().getConstructor(var.getClass()).newInstance(var); 
     } 
     catch(Exception e){ 
      System.out.println("Copy faield " + e.getMessage() + " "); 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    public static void main(String[] args) { 
     Integer a = new Integer(3); 
     Integer b = copy(a); 

     System.out.println(a); 
     System.out.println(b); 


    } 
} 

これが出力されます。

Copy faield java.lang.Integer.<init>(java.lang.Integer) 
    java.lang.NoSuchMethodException: java.lang.Integer.<init>(java.lang.Integer) 
     at java.lang.Class.getConstructor0(Class.java:2818) 
     at java.lang.Class.getConstructor(Class.java:1723) 
     at Main.copy(Main.java:7) 
     at Main.main(Main.java:19) 
    3 
    null 

ありがとう!

Integer.class 
int.class 

整数のコンストラクタは、intパラメータを取り、ないInteger

+5

多くのfonctionでオブジェクトとしてラッパー(クラス)が使用int型であります。反射では、パラメータを自動的に解除することはできません。 –

+0

これはなぜ動作しますか?Integer c = new Integer(new Integer(5)); – yonutix

+0

ここでは一般的な方法で多くの仮定をしています。すべてのクラスが同じクラスの値をとるコンストラクタを持つわけではありません。 – mikea

答えて

5

ここでの問題は間違いです。

マジックメソッドを機能させるには、型の特別なチェックを行う必要があります。ラッパークラスの場合は、実際にパラメーターが対応するプリミティブ型のコンストラクターを探します。

私の知る限りなしラッパークラスからprimatoveクラスを取得する方法であっ内蔵されています - あなたは、マップを使用してマッピングを移入できます。

private static final Map<Class<?>, Class<?>> MAP = new HashMap<>() {{ 
    put(Integer.class, int.class); 
    put(Long.class, long.class); 
    // etc 
}}; 

次に、あなたの方法で:

Class<?> type = MAP.containsKey(var.getClass()) ? MAP.get(var.getClass()) : var.getClass(); 
return (V) var.getClass().getConstructor(type).newInstance(var); 

intIntegerとしてパラメータ値に渡しても問題ありません。少なくとも自動アンボックスされます。反射は、それが最初のケースのために生成されたバイトコードを見て便利だしませんが、「新しい整数(新しい整数(5))は、」働く理由を本当に理解するには

+0

ありがとう、ありがとうございます。どのように私はどのように私は共有することをお勧めしますメソッドの目的を維持することをかわすことができるかどうか考えている場合。 – yonutix

+0

@ CosminMihaiエレガントに扱う方法のコードを参照してください。 Merry Xmas :) – Bohemian

+0

ありがとうございました。charプリミティブ型の対応するクラスがCharacterであることを祈っています。 – yonutix

1

ICONST_5 
INVOKESPECIAL java/lang/Integer.<init> (I)V 
INVOKEVIRTUAL java/lang/Integer.intValue()I 
INVOKESPECIAL java/lang/Integer.<init> (I)V 

...などIntegrateのintValue()メソッドが呼び出されていることがわかります。そのため、Javaコンパイラは実際には「新しいInteger(新しいInteger(5))」を「新しいInteger(新しいInteger(5).intValue())」に変換しています。つまり、intをとるコンストラクタを使用できます。

リフレクションの変数の実際の実行時の型をJavaコンパイラが知ることができないため、同様のことは実行できず、実際の実行時型の引数を持つコンストラクタのみを探すことができます。

+0

私は、これらの特定のケースを解決するために、if文またはInteger、Float、DoubleおよびLongクラスのスイッチを配置すると思います。 – yonutix

2

オブジェクトを別のオブジェクトにコピーする一般的なアプローチ。このutilクラスはパッケージorg.apache.commons.lang3で利用可能です。

Integer c = (Integer) SerializationUtils.clone(a); 
+0

SerializationUtilsは標準ライブラリにはありません。 – yonutix

+0

多くのユーザーや大きなプロジェクトですでに使用されている成熟したライブラリを使用すると、数時間で何かを一緒に置くよりもずっとうれしいです。ちょうど私の意見。 –

-1

のint型ですが、整数は整数のみ `int`または` STRING`引数コンストラクタなし `Integer`のコピーコンストラクタを持ってい

関連する問題