简体   繁体   English

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

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

Questions: 问题:

  1. In the line 在线

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

    Is there a way avoid hard coding " short.class " and instead get a literal from pPrim ? 有没有办法避免硬编码“ short.class ”而是从pPrim获取文字?

    I got the idea for using " short.class " from the answer in Create new object using reflection? 我从使用反射创建新对象的答案中得到了使用“ short.class ”的想法

  2. Shouldn't I be able to use " T o = ... (for a Byte or a Short, eg) instead of Object o = ... ? 我不应该使用“ T o = ... (对于字节或短,例如)而不是Object o = ... ?”

    I think my method is nearly identical to the one found at the end of Class Literals as Runtime-Type Tokens . 我认为我的方法几乎与Class Literals末尾的Runtime-Type Tokens相同

  3. Is what I want to do a case of reflection? 我想做什么反思?

Background: 背景:

I'm studying the book OCA Java SE 7: Programmer 1 Study Guide by Finegan and Liguori in preparation for 1Z0-803. 我正在研究由Finegan和Liguori编写的OCA Java SE 7:程序员1学习指南,以准备1Z0-803。 So I'm practicing code a lot. 所以我正在练习代码。 While practicing, I wrote a class hoping to see what's going on inside primitives when cast from a char. 在练习的过程中,我编写了一个类,希望在从char中转换时看到基元内部发生了什么。 I listed the code below ... if you take a look please focus on the methods byteToBinaryString, shortToBinaryString, and primitiveToBinaryString ... that's where my question arose. 我列出了下面的代码......如果你看看请关注方法byteToBinaryString,shortToBinaryString和primitiveToBinaryString ......这就是我的问题出现的地方。

Steps that got me to the question: 让我回答问题的步骤:

  1. wrote byteToBinaryString 写了byteToBinaryString
  2. cloned byteToBinaryString to shortToBinaryString 将byteToBinaryString克隆为shortToBinaryString
  3. thought, "I should be able to avoid this method repitition, maybe with generics" 我想,“我应该能够避免这种方法的重复,也许还有仿制药”
  4. cloned shortToBinaryString to primitiveToBinaryString and tried to convert to generic 将shortToBinaryString克隆为primitiveToBinaryString并尝试转换为泛型
  5. began thinking this was a reflection thing also 开始认为这也是一种反思
  6. got stuck with the class literal hard coding 坚持使用类文字硬编码

Here's my code 这是我的代码

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

A couple of things: 有几件事:

This could be cleaned up a little: 这可以清理一下:

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

Also, if you are looking for a single argument constructor that takes a primitive value you could do: 此外,如果您正在寻找具有原始值的单个参数构造函数,您可以执行以下操作:

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

Finally, if you are trying to convert a number to an binary string and you are only working with integer numbers (I'm assuming you are) you could always cast the number upwards to a long and convert that to a binary string. 最后,如果您尝试将数字转换为二进制字符串并且您只使用整数(我假设您是),您可以始终将数字向上转换为long并将其转换为二进制字符串。

long integralValue = pPrim.longValue();

As a matter of fact, you can obtain a class literal from a primitive value by forcing a boxing conversion , and then reflecting the static field TYPE (which is declared for any primitive wrapper). 事实上,您可以通过强制进行装箱转换 ,然后反映静态字段TYPE (为任何原始包装器声明),从原始值获取类文字。

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

Here obj.getClass()==Short.class , and Short.TYPE==short.class . 这里obj.getClass()==Short.classShort.TYPE==short.class The assignment obj=s is a boxing conversion (from short to Short ), followed by a reference widening conversion (from Short to Object ). 赋值obj=s是装箱转换(从shortShort ),然后是参考扩展转换(从ShortObject )。 It also works if you replace the assignment by an invocation to a method such as Object box(Object obj){return obj;} because both assignment conversions and method invocation conversions allow boxing conversions to take place. 如果通过调用Object box(Object obj){return obj;}来替换赋值,它也可以工作Object box(Object obj){return obj;}因为赋值转换和方法调用转换都允许进行装箱转换。

However, all of this reflection does not provide any advantage with respect to hardcoding short.class , since you can't have generics on primitive types. 但是,所有这些反射都没有为short.class硬编码提供任何优势,因为你不能在原始类型上使用泛型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM