以编程方式指定Java类文字(不进行硬编码)?反射?

时间:2013-03-12 01:55:29

标签: java generics reflection literals

问题:

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

    有没有办法避免硬编码" short.class"而是从pPrim得到一个文字?

    我有了使用" short.class"的想法。来自Create new object using reflection?

  2. 的答案
  3. 我不能使用" T o = ...(对于字节或短片,例如)而不是Object o = ...

    我认为我的方法几乎与Class Literals as Runtime-Type Tokens末尾的方法相同。

  4. 我想做一个反思的案例吗?
  5. 背景:

    我正在学习OCA Java SE 7:Finegan和Liguori的程序员1学习指南,以准备1Z0-803。 所以我经常练习代码。在练习的过程中,我写了一堂课,希望看看会发生什么 从char中转换时的基元内部。我列出了以下代码......如果你看一下,请关注方法 byteToBinaryString,shortToBinaryString和primitiveToBinaryString ......我的问题就出现了。

    让我回答问题的步骤:

    1. 写了byteToBinaryString
    2. 将byteToBinaryString克隆为shortToBinaryString
    3. 思考,"我应该能够避免这种方法的重复,也许是使用泛型"
    4. 将shortToBinaryString克隆为primitiveToBinaryString并尝试转换为通用
    5. 开始认为这也是一个反思的事情
    6. 坚持使用类文字硬编码
    7. 这是我的代码

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

2 个答案:

答案 0 :(得分: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;
      }
    }
  }
}

最后,如果您尝试将数字转换为二进制字符串并且您只使用整数(我假设您是),您可以始终将数字向上转换为long并将其转换为二进制字符串

long integralValue = pPrim.longValue();

答案 1 :(得分:2)

事实上,您可以通过强制boxing conversion,然后反映静态字段TYPE(为任何原始包装器声明)来从原始值获取类文字。 / p>

 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;}等方法来替换赋值,它也可以工作,因为分配转换和方法调用转换都允许进行装箱转换。

然而,所有这些反射都没有为硬编码short.class提供任何优势,因为你不能在原始类型上使用泛型。