簡體   English   中英

以編程方式指定Java類文字(不進行硬編碼)?反射?

[英]Specify a Java class literal programmatically (without hard coding it)? reflection?

問題:

  1. 在線

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

    有沒有辦法避免硬編碼“ short.class ”而是從pPrim獲取文字?

    我從使用反射創建新對象的答案中得到了使用“ short.class ”的想法

  2. 我不應該使用“ T o = ... (對於字節或短,例如)而不是Object o = ... ?”

    我認為我的方法幾乎與Class Literals末尾的Runtime-Type Tokens相同

  3. 我想做什么反思?

背景:

我正在研究由Finegan和Liguori編寫的OCA Java SE 7:程序員1學習指南,以准備1Z0-803。 所以我正在練習代碼。 在練習的過程中,我編寫了一個類,希望在從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);
  }
}

有幾件事:

這可以清理一下:

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;
      }
    }
  }
}

最后,如果您嘗試將數字轉換為二進制字符串並且您只使用整數(我假設您是),您可以始終將數字向上轉換為long並將其轉換為二進制字符串。

long integralValue = pPrim.longValue();

事實上,您可以通過強制進行裝箱轉換 ,然后反映靜態字段TYPE (為任何原始包裝器聲明),從原始值獲取類文字。

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

這里obj.getClass()==Short.classShort.TYPE==short.class 賦值obj=s是裝箱轉換(從shortShort ),然后是參考擴展轉換(從ShortObject )。 如果通過調用Object box(Object obj){return obj;}來替換賦值,它也可以工作Object box(Object obj){return obj;}因為賦值轉換和方法調用轉換都允許進行裝箱轉換。

但是,所有這些反射都沒有為short.class硬編碼提供任何優勢,因為你不能在原始類型上使用泛型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM