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?
T o = ...
(for a Byte or a Short, eg) 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 .
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.
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 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).
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 assignment obj=s
is a boxing conversion (from short
to Short
), followed by a reference widening conversion (from Short
to Object
). 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.
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.