Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

    I got the idea for using "short.class" from the answer in Create new object using reflection?

  2. Shouldn't I be able to use "T o = ... (for a Byte or a Short, e.g.) instead of Object o = ...?

    I think my method is nearly identical to the one found at the end of Class Literals as 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. 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. 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.

Steps that got me to the question:

  1. wrote byteToBinaryString
  2. cloned byteToBinaryString to 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
  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);
  }
}
like image 901
openmic Avatar asked Mar 12 '13 01:03

openmic


People also ask

What is a class literal in Java?

A class literal is an expression consisting of the name of a class, interface, array, or primitive type followed by a . and the token class . The type of a class literal is Class .

How do you create a class object using reflection?

We can use newInstance() method on the constructor object to instantiate a new instance of the class. Since we use reflection when we don't have the classes information at compile time, we can assign it to Object and then further use reflection to access it's fields and invoke it's methods.


1 Answers

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 integralValue = pPrim.longValue();
like image 171
Pace Avatar answered Oct 11 '22 03:10

Pace