6

質問:

  1. 行で

    Object o = myC.getConstructor(short.class).newInstance(myC.cast(pPrim));

    ""のハードコーディングを回避しshort.class、代わりにからリテラルを取得する 方法はありpPrimますか?

    リフレクションを使用して新しいオブジェクトを作成short.classするの答えから 「」を使用するというアイデアを思いつきましたか?

  2. T o = ...代わりに「」(たとえば、バイトまたはショート)を使用できるべきではありませんObject o = ...か?

    私の方法は、クラスリテラルの最後にランタイムタイプトークンとしてあるものとほぼ同じだと思います。

  3. 振り返りの場合、私がやりたいことは何ですか?

バックグラウンド:

1Z0-803の準備として、FineganとLiguoriによる本OCA Java SE 7:Programmer 1StudyGuideを勉強しています。だから私はコードをたくさん練習しています。練習中に、charからキャストしたときにプリミティブ内で何が起こっているかを確認することを期待してクラスを作成しました。以下にコードをリストしました...ご覧になる場合は、byteToBinaryString、shortToBinaryString、primitiveToBinaryStringの各メソッドに注目してください...ここで私の質問が発生しました。

私を質問に導いたステップ:

  1. byteToBinaryStringを書き込みました
  2. byteToBinaryStringをshortToBinaryStringに複製しました
  3. 「おそらくジェネリックスで、このメソッドの繰り返しを回避できるはずです」と考えました。
  4. shortToBinaryStringをprimitiveToBinaryStringに複製し、ジェネリックに変換しようとしました
  5. これも反省だと思い始めました
  6. クラスリテラルのハードコーディングで立ち往生しました

これが私のコードです

    import java.util.TreeMap;
import java.util.Set;

public class StackoverflowQuestion {

  // I wrote this 1st
  public static String byteToBinaryString(byte pByte) {
    int primLength = 8;
    int count = 0;
    String s = "";
    while ( count++ < primLength ) {
      byte sm = (byte) (pByte & 0x01);
      pByte >>= 1;
      s = sm + s;
      if ( count % 4 == 0 && count != primLength ) {
        s = " " + s;
      }
    }
    return s;
  }

  // Then I cloned byteToBinaryString to this and had the thought, 
  // I shouldn' have to repeat this
  public static String shortToBinaryString(short pShort) {
    int primLength = 16;
    int count = 0;
    String s = "";
    while ( count++ < primLength ) {
      short sm = (short) (pShort & 0x0001);
      pShort >>= 1;
      s = sm + s;
      if ( count % 4 == 0 && count != primLength ) {
        s = " " + s;
      }
    }
    return s;
  }

  // So I cloned shortToBinaryString, modifidied to this and ...
  public static <T extends Number> String primitiveToBinaryString(T pPrim) {
    int primLength = 16;
    int count = 0;
    String className = pPrim.getClass().getName();
    try {
      Class<?> myC = Class.forName(className);
      // ... got stuck here
      Object o = myC.getConstructor(short.class).newInstance(myC.cast(pPrim));
      System.out.println(pPrim + "<--pPrim.equals(o)-->" + pPrim.equals(o) + "<--" + o);
    } catch ( Exception e ) {
      System.out.println("Caught exception: " + e);
    }
    String s = "";
    while ( count++ < primLength ) {
      //T sm = new Class<T>(pPrim.intValue() & 0x0001);
      //pPrim >>= 1;
      //s = sm + s;
      if ( count % 4 != 0 && count != primLength ) {
        s = "-" + s;
      }
    }
    return s;
  }

  public static void main ( String[] args ) {

    // exercise byteToBinaryString
    for ( int i = 0; i < 256; i++ ) {
      char cByte = (char) i; 
      byte b1 = (byte) cByte;
      System.out.printf( "char(%c): charValue(%05d): bin(%s): dec(%+6d)\n", cByte, (int) cByte, byteToBinaryString(b1), b1 );
    }

    // exercise shortToBinaryString
    // please ignore my use of TreeMap, just figuring out how it works
    TreeMap<Integer, String> charsTM = new TreeMap<Integer, String>();
    charsTM.put(00000, "00000");
    charsTM.put(00001, "00001");
    charsTM.put(32766, "32766");
    charsTM.put(32767, "32767");
    charsTM.put(32768, "32768");
    charsTM.put(32769, "32769");
    charsTM.put(65535, "65535");

    short s1  = 32767;
    char  ch1 = 32768;

    Set<Integer> charKeys = charsTM.keySet();
    // loop through the boundary values I selected to show what's going on in memory
    for ( Integer i : charKeys ) {
      ch1 = (char) i.intValue();
      s1 = (short) ch1;
      System.out.printf( "char(%c): charValue(%05d): bin(%s): dec(%+6d)\n", ch1, (int) ch1, shortToBinaryString(s1), s1 );
    }

    // exercise primitiveToBinaryString
    primitiveToBinaryString( (byte)  127 );
    primitiveToBinaryString( (short) 32767 );
    primitiveToBinaryString( (int)   2147483647);
    primitiveToBinaryString(         2147483648L);
    primitiveToBinaryString(         2147483648F);
    primitiveToBinaryString(         2147483648D);
  }
}
4

2 に答える 2

2

いくつかのこと:

これは少しクリーンアップできます:

String className = pPrim.getClass().getName();
Class<?> myC = Class.forName(className);
//Can just do
Class<?> myC = pPrim.getClass();

また、プリミティブ値をとる単一の引数コンストラクターを探している場合は、次のことができます。

public Constructor<?> getPrimitiveSingleArgConstructor(Class<?> myC) {

  for( Constructor<?> constructor : myC.getConstructors() ) {
    if( constructor.getParameterTypes().length == 1 ) {
      Class<?> paramType = constructor.getParameterTypes()[0];
      if (paramType.isPrimitive()) {
        return constructor;
      }
    }
  }
}

最後に、数値を2進文字列に変換しようとしていて、整数のみを操作している場合(私はあなたがそうだと思います)、いつでも数値を上向きにlongにキャストし、それを2進文字列に変換できます。

long integralValue = pPrim.longValue();
于 2013-03-12T03:56:14.303 に答える
2

実際のところ、ボクシング変換を強制し、静的フィールドTYPE(任意のプリミティブラッパーに対して宣言されている)を反映することにより、プリミティブ値からクラスリテラルを取得できます。

 short s = 0;
 Object obj = s;
 System.out.println(obj.getClass().getDeclaredField("TYPE").get(null));

ここobj.getClass()==Short.classで、、 Short.TYPE==short.class。割り当てobj=sは、ボクシング変換(fromshortからShort)と、それに続く参照拡大変換(fromShortからObject)です。Object box(Object obj){return obj;}また、割り当ての変換とメソッドの呼び出しの変換の両方でボクシングの変換を実行できるため、割り当てをメソッドの呼び出しに置き換えた場合にも機能します。

short.classただし、プリミティブ型にジェネリックスを使用することはできないため、このリフレクションのすべてがハードコーディングに関して利点を提供するわけではありません。

于 2013-03-12T11:55:46.407 に答える