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.
Related
As far as I understood, object is simply singleton instance. I would like to create enumeration type with cell types, and then class Cell with constructor containing coordinates and enumeration type. However, it cannot be done, and I cannot find out why.
object CellType extends Enumeration {
val Empty, X, O = Value
}
In another file:
class Cell(column: Int, row: Int, cellType : CellType) {
} // CellType is an object, and it doesn't work!
Do you have any ideas how to do it, or at least a reason why Scala forbids objects in contructors?
Error message:
Warning:(3, 37) imported 'CellType' is permanently hidden by
definition of object CellType in package model import
de.htwg.model.CellType
CellType is not a type, it's an object. It is actually the only object of its type, CellType.type. If you want to have a function argument that can only be this object, you may use an argument of type CellType.type. But then, why even bother putting it as an argument, if it can only be CellType? Might as well use the object directly, not passing it as an argument.
What you probably want is not the type of CellType, but the type of its enumerated values, which happens to be CellType.Value.
NB: I personally found rather disturbing that the scala language defines on the same level traits and classes, which are types, and objects, which are instances of a singleton type. You should not be misguided by this apparent analogy, and really consider objects as values, and classes and traits as types.
I'm wondering what specifically allows an object of one class to be cast as another class. Looking at the Class.isInstance(Object obj) javadoc, it suggests that an object has to be 'assignment-compatible' with another class in order to be cast to that class. But what constitutes 'assignment-compatible'?
I'm trying to figure out how the following returned a ClassCastException:
public class A
{
multiple private attributes
No constructor
multiple public methods
}
public class B extends A
{
blank default constructor
2 additional private attributes
4 additional public getter / setter methods for these attributes
}
The line
B b = (B)variable.getA() // where getA() returned an instance of class A
returns a ClassCastException A cannot be cast as B. I know that casting from a parent class to a subclass is a bad idea. I did not write the code in question, I'm just looking at it in a production support capacity.
Class B is the only class in the codebase that extends from A. So the result of getA() is not an object of another subclass of A (say C) cast to A.
So why in this instance can Java not cast an object of class A to the seemingly compatible class B?
Consider these two cases:
A a = new B();
B b = (B)a; <-- Ok.
A a = new A();
B b = (B)a; <-- ClassCastException
So in order to cast an object to B it must be an instance of B (or a subclass of B).
In your case it is however an instance of A.
The javadoc for Class.isInstance(Object obj) gives the definition of assignment compatible:
Specifically, if this Class object represents a declared class, this method returns true if the specified Object argument is an instance of the represented class (or of any of its subclasses); it returns false otherwise. If this Class object represents an array class, this method returns true if the specified Object argument can be converted to an object of the array class by an identity conversion or by a widening reference conversion; it returns false otherwise. If this Class object represents an interface, this method returns true if the class or any superclass of the specified Object argument implements this interface; it returns false otherwise. If this Class object represents a primitive type, this method returns false.
Basically, you can assign an object of type A to variable of type B if type A extends or implements type B.
Thrown to indicate that the code has attempted to cast an object to a subclass of which it is not an instance. For example, the following code generates a ClassCastException:
Object x = new Integer(0);
System.out.println((String)x);
more info here and here.
If we replaced A and B with meaningful names that help us think about the problem, then the answer becomes clearer. If A becomes Mammal and B is Dog, then we can reasonably say that all Dogs are Mammals, but we cannot say that all Mammals are Dogs. Even if they superficially shared the same attributes, there is no guarantee that all Mammals would fulfill the contract of being a Dog, and the compiler shouldn't try to assume so.
Just wanted to add the official specification to support
Ricardo's correct answer that "you can assign an object of type A to variable of type B if type A extends or implements type B":
The JLS defines assignment-compatibility as follows:
5.2. Assignment Contexts
If the type of an expression can be converted to the type of a variable by assignment conversion, we say the expression (or its value) is assignable to the variable or, equivalently, that the type of the expression is assignment compatible with the type of the variable.
The term "assingment conversion" is only defined as applying the appropriate conversion from the list given in the "Assignment Contexts"-chapter:
The term "conversion" is also used to describe, without being specific, any conversions allowed in a particular context. For example, we say that an expression that is the initializer of a local variable is subject to "assignment conversion", meaning that a specific conversion will be implicitly chosen for that expression according to the rules for the assignment context.
The most relevant for reference types being
5.1.5. Widening Reference Conversion
A widening reference conversion exists from any reference type S to any reference type T, provided S is a subtype of T (§4.10).
Subtypes include implemented interfaces (see 4.10.2. Subtyping among Class and Interface Types ).
There are additional rules for numeric and generic types, but they are not relevant for the example given in the question.
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;
I feel like i got some idea about wrapper classes. My question is when will a method expect object?
only then we need to use wrapper classes right?
generally a method expects some paratmeters like
int add(int a);
Is this "int a" a primitive value?
example pls
The Java primitive types are int, double, byte, boolean, char, short, long, and float.
If a function signature wants int, then you are passing it a primitive. If, for example, it wanted Integer, it wants the wrapper class Integer. In Java 1.5, autoboxing can take effect and automatically wrap primitives into its wrapper type. Unboxing can also take place, where a wrapper class is converted to its primitive equivalent for methods that expect primitives.
class Example
{
public static void usePrimitiveInt(int i) { }
public static void useIntegerClass(Integer i) { }
public static void main(String [] args)
{
int i = 5;
Integer iObj = 10;
Example.usePrimitiveInt(i); // use primitive
Example.useIntegerClass(i); // autobox int to Integer
Example.usePrimitiveInt(iObj); // unbox iObj into primitive
}
}
Remember that another name for the wrapper pattern is the adapter pattern.
One of the first examples of the wrapper pattern that we see in java are the primitive wrapper classes:
java.lang.Integer wraps int
java.lang.Character wraps char
java.lang.Long wraps long
etc.
These wrappers are useful when you need object representations of the primitives, for instance when you need to store them in a Collection.
Wrappers can be useful when you need to normalise a common interface across different classes, especially those that you cannot change because for instance they might be part of a 3rd party library.
For example, say you need to process a list of people that will be attending an event, however you may have multiple sources of information with their own representations of a person.
Your processing method accepts a list of Attendee objects.
The first source gives you a list of Employee objects
2.1 The EmployeeWrapper contains the Employee object and implements or extends Attendee
The second source gives you a list of Customer objects
3.1 The CustomerWrapper contains the Customer object and implements or extends Attendee
The third list gives you a list of VendorContact objects
4.1 The VendorWrapper contains the VendorContact object and implements or extends Attendee
You now have a normalised representation of the different types of Attendee objects.
You said you understand wrapper classes. Then there should be nothing to explain. The method expects a wrapper class when the method signature says it does. If the parameter type is Integer, the method expects wrapper class. If int, it expects primitive value.
I have read that in order to access the call object representing a primitive type, I can do this:
Class intClass = int.class;
But how do primitive types have classes to represent them? They are primitive, which should mean they have no class. Why does the example above work, and what class contains int (Integer class maybe)?
As the javadoc for the Class class states
Instances of the class Class represent classes and interfaces in a
running Java application. An enum is a kind of class and an annotation
is a kind of interface. Every array also belongs to a class that is
reflected as a Class object that is shared by all arrays with the same
element type and number of dimensions. The primitive Java types
(boolean, byte, char, short, int, long, float, and double), and the
keyword void are also represented as Class objects.
A Class object simply provides some metadata and factory methods for the type it represents.
For example, Class#isPrimitive() will tell you if the represented type is a primitive.
The class Class and its instances are, among other things, used for reflection.
Let's say you had the a class like
public class Example {
public long add(int first, long second) { // for whatever reason
return first + second;
}
}
and you wanted to invoke the add method, given only its name and parameter types. The following would fail
Class<?> exampleClass = Example.class;
exampleClass.getMethod("add", Integer.class, Long.class);
because the parameter types are not Integer and Long, they are int and long.
You'd have to do something like
Class<Example> exampleClass = Example.class;
Method addMethod = exampleClass.getMethod("add", int.class, long.class);
Example instance = exampleClass.newInstance();
addMethod.invoke(instance, 42, 58L);
If you look at the field summary for the Integer class, you will find that the primitive type int is actually represented by the class instance TYPE. Therefore, int.class would equal Integer.TYPE.
Here's a link to Javadocs where you can find the TYPE class instance.
When you type int.class you get the corresponding object wrapper class, which every primitive has. Read the Java tutorials on autoboxing for more information, and to see each primitive's corresponding wrapper class.