What's the purpose and function of int.class - java

I accidentally found that this works:
Class<?> a;
a = int.class;
System.out.println(a); // int
a = Integer.class;
System.out.println(a); // class java.lang.Integer
What does it really mean / do for primitives?
I tried and neither List<int> nor List<int.class> works (yeah, I know I have to use Integer). Also, obviously, I can't invoke getClass() on primitives, so it's useless for type checking of any sort.
In what situation would I use int.class and why is it even present in the language?

You would use it when you are trying to locate a method having an int argument via the reflection API.

From the specs:
The type of p.class, where p is the name of a primitive type
(§4.2), is Class<B>, where B is the type of an expression of
type p after boxing conversion (§5.1.7).
And
A class literal evaluates to the Class object for the named
type (or for void) as defined by the defining class loader
(§12.2) of the class of the current instance.
So how about
Class<Integer> a = int.class;
When to use: Lots of reflection use cases (for instance in argparse4j they use it to map from command line parameters to methods).

Related

ClassNotFoundException with Class.forName("int")

Please note that I can't get forName() to work specifically with "int".
On the other hand, it works alright with a class I created in the same package as
Class.forName("mypackage.dummyclass")
Is that something to do with fully qualified names? I've tried "java.lang.int" and "java.lang.integer", but it didn't help.
int is a primitive type in Java, not a class, so try java.lang.Integer instead (which is not exactly the same thing but is interchangeable for many purposes)
The correct syntax for getting the Class object associated with primitive types, like int, is
int.class
Likewise, you use byte.class, long.class, boolean.class, etc. for the other primitive types.
While there's a special relationship between int and java.lang.Integer, int.class is not the same thing as Integer.class.
Note that you cannot use Class.forName with a primitive type name.
As documented in the Java tutorial:
Class.forName()
If the fully-qualified name of a class is available, it is possible to get the corresponding Class using the static method Class.forName(). This cannot be used for primitive types.
And from the same tutorial, on how to use the .class syntax with primitives:
The .class Syntax
If the type is available but there is no instance then it is possible to obtain a Class by appending ".class" to the name of the type. This is also the easiest way to obtain the Class for a primitive type.
boolean b;
Class c = b.getClass(); // compile-time error
Class c = boolean.class; // correct
Class.forName is for class objects but int is primitive data type.
Try java.lang.Integer instead.
int is a primitive data type, not a class. Integer class can be used for int. So you should use "Integer".
Instead of java.lang.integer, try java.lang.Integer (With Capital I)
The above will work because, Class.forName() tries to create an object of the full class name passed as String arg in it.
java.lang.Integer - This is a class
int - This is not a class. It is a primitive data type. Hence, failing.

Type field in Boolean Wrapper Class?

In java API documentation, it is written that Boolean wrapper class have 3 fields. True, False and Type.
For Type they have given description that:
TYPE: The Class object representing the primitive type boolean.
I can't understand what is this "type" field for?
Every Java class is represented in a running Java program by an object of type java.lang.Class, which, amongst other things, lets you perform reflective operations upon objects of that type. You can normally get to an object's Class by calling obj.getClass(), or by specifying its name explicitly, eg. String.class.
Primitive types, like int and boolean, don't have a class to represent them. But there are situations where it would be appropriate to have a Class object for them, and the TYPE members of the wrapper class types (like java.lang.Integer and java.lang.Double) represent exactly these Class objects.
You might be given one if you perform reflective operations on, say, an array of booleans, like this:
boolean[] bools = new boolean[1];
Class<?> c = bools.getClass().getComponentType();
Assert.assertEquals(Boolean.TYPE, c); // passes!
Note that the primitive boolean class is NOT the same as the Boolean wrapper class! That is,
Assert.assertNotSame(Boolean.TYPE, Boolean.class); // passes!
TYPE is a Class<Boolean> compile-time constant of the Boolean wrapper class representing the primitive type (boolean) the Boolean class wraps around.
The same is in all object wrappers: they all have a TYPE constant representing their primitive counterpart (e.g. Integer.TYPE).
It is used in the reflection API, to represent the type of a boolean argument or return type of a method, or the type of a field of a class.

Java permits primitive types in generics

I know that java is not supposed support generic arguments which are primitive types, and sure enough something like:
Vector<byte> test;
will fail to compile.
however with a little slight-of-hand that I accidentally performed in a program, I found that it is actually possible to create a generic object with a primitive type (technique shown below)
Furthermore, java falsely allows this instance to be assigned to a variable of type Vector<Byte> when as the print statements show, byte.class and Byte.class are two separate beasts. Because of this, attempts to do calls on the object result in unexpected and strange behaviors/errors.
Is this a java bug? or is there some rhyme or reason to this madness? It seems like even if java allowed the unexpected behavior of creating primitive-typed generics, they should not be assignable to a generic of the wrapper type which is of a distinct class from the primitive.
import java.util.Vector;
public class Test
{
//the trick here is that I am basing the return type of
//the vector off of the type that was given as the generic
//argument for the instance of the reflections type Class,
//however the the class given by byte.class yields a non-class
//type in the generic, and hence a Vector is created with a
//primitive type
public static <Type> Vector<Type> createTypedVector(Class<Type> type)
{
return new Vector<Type>(0,1);
}
public static void main(String ... args)
{
//these lines are to demonstrate that 'byte' and 'Byte'
//are 2 different class types
System.out.println(byte.class);
System.out.println(Byte.class);
//this is where I create an instance of type Vector<byte>
//and assign it to a variable of type Vector<Byte>
Vector<Byte> primitiveTypedGenericObject = createTypedVector(byte.class);
//this line causes unexpected exceptions to be thrown
//because primitiveTypedGenericObject is not actually type
//Vector<Byte>, but rather Vector<byte>
primitiveTypedGenericObject.set(0,(byte)0xFF);
}
}
Both Byte.class and Byte.TYPE are Class<Byte> objects. The latter are just used to distinguish between primitive type and object type.
Actually Byte.TYPE is defined as:
public static final Class<Byte> TYPE = (Class<Byte>) Class.getPrimitiveClass("byte");
and getPrimitiveClass is an opaque method which retrieves the type from the VM so we can't investigate it further.
So, even if you think that you are passing a primitive data type Class, since they don't exist (why should they, since they refer to something that is typable according to the Java typing system for objects, which doesn't include primitive types until they are boxed into wrapper classes), you are creating a Vector<Byte>.
But in the end this doesn't matter much, upon reaching run-time execution type annotations are erased and the generic type doesn't mean anything. Whenever you'll add a byte it will be autoboxed to a Byte object and that's it.
I have no way to test your code at the moment, which exceptions are thrown at runtime when adding items to the Vector?
You've stumbled upon autoboxing and unboxing. See http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
The nutshell version
List<Integer> list = new List<Integer>();
list.add(1); // works
byte.class, int.class, etc. resolve to Byte, Integer, etc. See the Java Language Specification, 15.8.2:
15.8.2. Class Literals
......
The type of p.class, where p is the name of a primitive type (§4.2), is Class<B>, where B is the type of an expression of type p after boxing conversion (§5.1.7).
The type of void.class (§8.4.5) is Class<Void>.
No! It is not bug. It is called Autoboxing. When you pass byte to a generic method that expects Byte, the compiler automatically Autoboxes it to Byte which is an instance of Object. The antithesis of that operation is called Auto Unboxing and that is why operations like the one shown below are legal.
int a = new Integer(5);
Integer b = 5;

Class.forName casts

In Java, will using Class.forName in a cast result in the object being cast to a class or being cast to the cast found. As an example, if you did this
Object a;
String b = "testing";
a = (Class.forName("java.lang.Object")) b;
Would a be an instance of Class or an instance of Object?
Class.forName returns a Class instance. I'm fairly certain your code as quoted doesn't compile, you're trying to use a function call as a cast.
Update: Just had a thought: If you're asking how to use a dynamically-loaded class in a cast, you basically can't. Casting is (mostly) a compile-time thing. Have the dynamically-loaded class implement an interface you can compile into your code and then cast to that, or if you can't do that, use reflection to access the dynamically-loaded class' members.
You can cast with the class object's .cast method:
Object a;
String b = "testing";
a = Class.forName("java.lang.Object").cast(b);
But you seem to have wrong ideas about casting - in Java, casting does not change any object, it just tells the compiler that the object is of some type, and on runtime, the VM will test if this is really the case (if the compiler can't already prove it). If you "cheated", the VM will throw an ClassCastException here (it will not convert your object).
(It works a bit different if primitive types are involved.)
The Class object's cast method is a generic variant of this same mechanism. Since it has the return type T (from Class<T>), this allows generic code to cast an unknown object to some class type, where this class object corresponds to a type variable.
This will not help you here - the return type of Class.forName is Class<?>, which means that its cast method can only return Object.
And anyway, casting to java.lang.Object has no effect (it will always succeed), other than hiding the to the compiler that the value has some specialized type. (This might matter if you have overloaded methods.)
Simply writing
Object a;
String b = "testing";
a = b;
has the same effect here.
If it is required to cast an instance this is a way to do it
String className = "YourClass";
Class someClass = Class.forName( className );
Constructor constructor = (Constructor) someClass.getConstructor();
Object someInstance = constructor.newInstance();
// now you can cast as allways.
(YourClass) (someInstance)
Class.forName always returns the Class.

Why do I get "Illegal generic type for instanceof"?

Given:
public class C<T> {
private class D {
public boolean equals( Object o ) {
if ( !(o instanceof D) ) // line 4
return false;
D other = (D)o; // line 6
return i == other.i;
}
int i;
}
}
I get:
C.java:4: illegal generic type for instanceof
if ( !(o instanceof D) )
^
I also get an "unchecked cast" warning about line 6. Why? The o is not a generic type -- it's just a plain Object. How can I correctly implement equals() by both checking for and casting to an instance of D?
Note: Obviously, this code example is a whittled-down version of my actual code. The real classes for C and D are much larger and D is a private inner class of C used by its implementation.
FYI: The real D does make use of the generic parameter T.
The o is not a generic type -- it's just a plain Object.
That's not the problem. The problem ... and the root cause of both compilation errors ... is that D is a generic class. And it is generic because it is a non-static nested class in a generic class. Its fully qualified name would be some.pkg.C<T>.D.
FYI: The real D does make use of the generic parameter T.
And the fact that it could make use of T is what makes D a generic class.
The reason that you cannot use instanceof D or (D) is generic type erasure. Basically, the runtime cannot distinguish between the types of (say) C<String>.D and C<Integer>.D. And since it cannot do that, it cannot determine if instanceof D should return true or false or if (D) should succeed or throw ClassCastException.
One solution would be to declare D as static. But that will not work with your "real D" because a static class cannot make use of a generic type parameter from the enclosing class(es). Your "FYI" says that it does that.
Another solution is to instantiate the outer class C passing it the actual type of T as a java.lang.Class<T> instance. Then use this Class instance to implement the runtime type checks and casts as required. This is likely to be messy.
The third solution is to carefully analyze the code and determine if it is safe to a #SuppressWarning annotations to suppress the "unsafe cast" etc warnings.
What type erasure? 'o' is of type Object directly.
Actually Object is the declared type of the o variable. The actual object will most likely have some other type, and it is that type that (if it is a D instance for example) will have been subjected to type erasure.
#StephenC is right in that the problem is that D means C<T>.D, which is a parameterized type. The solution is to use the raw type or the wildcard-parameterized type:
if ( !(o instanceof C.D) )
or
if ( !(o instanceof C<?>.D) )
If you make the inner class static, the code compiles fine.
Ex:
private static class D{...}
Read here for the difference.
You could also try o.getClass() != D.class (after guarding against o being null, of course)
D.class.isInstance(o)
seems to work here.

Categories

Resources