Specify Java class literal programmatically (without hard coding)? reflection?

Questions:

  • In line

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

    Is there a way to avoid hard coding " short.class " and get a literal from pPrim ?

    I got an idea to use " short.class " from the answer in Create a new object using reflection?

  • Should I use " T o = ... (for a byte or short, for example, instead of Object o = ... ?

    I think my method is almost identical to the method found at the end of Class Literals as Runtime type tokens .

  • I want to make a reflection case?

History:

I am studying OCA Java SE 7: Programmer 1 Study Guide from Finegan and Liguori in preparation for 1Z0-803. Therefore, I understand a lot of code. In practice, I wrote a class hoping to see what happens inside primitives when cast with char. I have listed the code below ... if you look, please focus on the methods byteToBinaryString, shortToBinaryString and primitiveToBinaryString ... where the question arose.

The steps that led me to the question:

  1. written by byteToBinaryString
  2. clone byteToBinaryString for shortToBinaryString
  3. thought: โ€œI should be able to avoid this replication method, possibly with genericsโ€
  4. cloned shortToBinaryString to primitiveToBinaryString and tried to convert to general
  5. began to think that it was a reflection.
  6. stuck with hard class coding literally

Here is 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 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); } } 
+6
source share
2 answers

A few things:

This can be cleaned up a bit:

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

Also, if you are looking for one argument constructor that takes on a primitive value that 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 a binary string and only work with integers (I assume you do this), you can always take the number to a long one and convert it to a binary string.

 long integralValue = pPrim.longValue(); 
+2
source

In fact, you can get a class literal from a primitive value by forcing box conversion and then flipping the static TYPE field (which is declared for any primitive wrapper).

  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 . The purpose of obj=s is a box transform ( short to short ), followed by a reference extension of the transform ( short to Object ). It also works if you replace the assignment with a call to a method, for example, Object box(Object obj){return obj;} , because both assignment transformations and method call transformations allow you to perform box transformations.

However, all this reflection does not give any advantages in relation to hard coding short.class , since you cannot have generics for primitive types.

+2
source

All Articles