Enum is in the java.lang.Enum, and Object is in the java.lang.Object. So, why is Enum not an Object? (I am getting a java.lang.ClassCastException)
I want to make a class that can accept both Object and Enum, like this...
public class MyType<T extends Enum<T>, Object> {
But this gives a compilation error. How can i make my MyType so that it can accept all (or both) type of classes? (Enum or Object)?
Since every Java object is instanceof Object, there is nothing better to do than declare MyType<?> with no bounds. That will capture any type, including an enum type.
An Enum is an Object. See http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Enum.html
So
MyType<Object> {
should work.
You can see on documentation:
Excepting Object, which has no superclass, every class has one and
only one direct superclass (single inheritance). In the absence of any
other explicit superclass, every class is implicitly a subclass of
Object.
You can conclude:
even not explicit your class will extends from Object;
if Object was a figured manner to represent other class, you will not be able since java doesn't support multiple-inheritance.
Simply by looking at the API for class object, you can read:
Class Object is the root of the class hierarchy. Every class has Object as a superclass.
All objects, including arrays, implement the methods of this class.
This means that Enum is an object (you can verify this by looking at the JavaDocs for Enum aswell). Hence, if you simply tell MyType to contain Object(MyType<Object>), it will accept Object and Enum as you originally posted.
Although notice that this might cause unwanted behavior and is considered unsafe, since ALL classes are objects.
I don't think you've stated your question correctly. I think you want your class to accept Enum or Object. When you put it like that you can see that is the only possible choice.
If you want it to accept Enum and Object, that is equivalent to saying 'accept Enum'. In which case > is the answer.
Related
If I have a few derived classes that have methods that are different than the base class, but similar to each other, can I use a variable to downcast?
for example:
Object derivedClass = baseClass.getChild().getClass();
((derivedClass)differentClassObj.differentClassMethod()).derivedClassMethod();
Perhaps that's too vague and/or not efficient since I could just create empty methods in the base class to bypass this issue (or other tricks I haven't learned), but I'm still curious if it's possible to pass variables into casting or not.
Thanks for your insight!
Edit: to further clarify any confusion, I'm trying to determine if I can do casting using a variable. So say I wanted to cast something as a String (just for argument's sake):
String myObjStr = MyObject.class.getSimpleName();
// Then I want to know if I can cast objects using that variable in the casting
//(so far it doesn't appear to be working but I know that's because its a string.
//Is there some way I can manipulate it so that I CAN cast with it?)
((myObjStr).differentClassObj.differentClassMethod()).derivedClassMethod();
While you can sort of use a Class object to specify what type to cast an object to, it doesn't really help you:
Class<? extends ParentClass> derivedClass = baseClassObject.getChild().getClass();
// The following kind of does the cast you want, but not in a useful way:
derivedClass.cast(differentClassObject)
The problem is that you still need to statically know the type of the result. The static type of the cast output is only as specific as the static type of the Class object, not the class the Class object actually represents. Thus, even if you have a derivedClass object representing ChildClassOne, you only know that it's a Class<? extends ParentClass>. While the object's cast method will throw an exception for instances of ChildClassTwo, you can't call ChildClassOne methods on the return value.
If all instances of classes in this class hierarchy will have the method you're looking for, but the base class cannot provide a useful implementation, you should mark the base class abstract and give it this method as an abstract method. If some objects in this class hierarchy will not have the method you're looking for, you should probably redesign your program or perform casts the regular way. Introducing an interface might be a good idea. Whatever the case, casting with a Class object probably won't help you.
If you have only a Class object, how does one get a method reference to a method such as toString? Later we will have instances of this particular class on which we will invoke this method via the method reference.
For example, consider a Java enum, a subclass of Enum. Here T is defined as <T extends Enum>.
Class c = MyEnum.class
…
Function< T , String> f = c :: toString ;
I get an error saying "invalid method reference".
For toString, it's as easy as Object::toString. All Objects have toString, so you can use it right there. For other methods where you don't know statically that the object has that method, there's no easy way; you have to write a lambda that does it the ugly reflective way.
If you can access your Class object using a class literal in the form Class<MyEnum> c=MyEnum.class;, it implies that the type MyEnum is known at compile time. In this case, the Class object is an unnecessary detour. You can access all methods of the class MyEnum using the form MyEnum::methodName, e.g.
Function<MyEnum,String> f=MyEnum::toString;
This is what the tutorial describes as “Reference to an Instance Method of an Arbitrary Object of a Particular Type”. It doesn’t require an actual MyEnum instance.
Nevertheless, there is no point in dealing with MyEnum when you want to have a Function<T,…> as that function must be able to consume arbitrary instances of T, not necessarily being MyEnum. So this function can only use methods existing in T and it doesn’t need to search them in MyEnum.
Since your target method is not specific to MyEnum, that’s possible:
Function<T,String> f=T::toString;
But as already pointed out, the method toString is defined in java.lang.Object, so you may also use the form
Function<T,String> f=Object::toString;
as a method declared for all objects may also get invoked on instances of T. Though even this is a bit pointless as you can also use
Function<Object,String> f=Object::toString;
reflecting the ability to consume any instance of Object, not just T. Carefully written Generic code will always use wildcards to avoid unnecessary restrictions regarding its input. So it will accept a function which can consume T (which implies the ability to consume MyEnum) without requiring its type parameter to exactly match that type. For example:
<R> Stream<R> map(Function<? super T,? extends R> mapper)
map, applied on a Stream<T> will accept a Function<Object,…> as Object is a supertype of T…
So you can use T::methodName to access every method available for the bounds of that type, i.e. in your case you can use all methods of Enum and, of course, Object, but no methods specific to MyEnum not present in its supertypes. This isn’t different to ordinary method invocations you try to apply on instances of T. Further, a method not present in T wouldn’t be eligible for creating a valid Function<T,…> anyway.
If you want to create Function instances for methods not known at compile-time, you will have to use Reflection, and this is the only case where you have to deal with Class objects (in the context of method references). The second example of this answer shows how to create a Function for an instance method returning an object but that’s really only for those who know precisely what they are doing…
Note also that such reflectively created Functions have to use raw types as their appropriate generic type can’t be declared as it would refer to a type not present at compile-time.
What you are trying here, is to get the reference of toString() for the class Class, which is probably not what you intended. As toString() is defined for all objects, this should work (not tested):
Function< T , String> f = t -> t.toString();
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
java Enum definition
Better formulated question, that is not considered a duplicate:
What would be different in Java if Enum declaration didn't have the recursive part
if language designers were to use simply Enum<E extends Enum> how would that affect the language?
The only difference now would be that someone coud write
A extends Enum<B>
but since it is not allowed in java to extend enums that would be still illegal.
I was also thinking about someone supplying jvm a bytecode that defines smth as extending an enum - but generics can't affect that as they all are erased.
So what is the whole point of such declaration?
Thank you!
Edit
for simplicity let's look at an example:
interface MyComparable<T> {
int myCompare(T o);
}
class MyEnum<E extends MyEnum> implements MyComparable<E> {
public int myCompare(E o) { return -1; }
}
class FirstEnum extends MyEnum<FirstEnum> {}
class SecondEnum extends MyEnum<SecondEnum> {}
what's wrong with this class structure? What can be done that "MyEnum<E extends MyEnum<E>>" would restrict?
This is a common question, and understandably so. Have a look at this part of the generics FAQ for the answer (and actually, read as much of the whole document as you feel comfortable with, it's rather well done and informative).
The short answer is that it forces the class to be parameterized on itself; this is required for superclasses to define methods, using the generic parameter, that work transparently ("natively", if you will) with their subclasses.
Edit: As a (non-)example for instance, consider the clone() method on Object. Currently, it's defined to return a value of type Object. Thanks to covariant return types, specific subclasses can (and often do) define that they return a more specific class, but this cannot be enforced and hence cannot be inferred for an arbitrary class.
Now, if Object were defined like Enum, i.e. Object<T extends Object<T>> then you'd have to define all classes as something like public class MyFoo<MyFoo>. Consequently, clone() could be declared to return a type of T and you can ensure at compile time that the returned value is always exactly the same class as the object itself (not even subclasses would match the parameters).
Now in this case, Object isn't parameterized like this because it would be extremely annoying to have this baggage on all classes when 99% of them aren't going to utilise it at all. But for some class hierarchies it can be very useful - I've used a similar technique myself before with types of abstract, recursive expression parsers with several implementations. This construct made it possible to write code that was "obvious" without having to cast everywhere, or copy-and-paste just to change concrete class definitions.
Edit 2 (To actually answer your question!):
If Enum was defined as Enum<E extends Enum>, then as you rightly say, someone could define a class as A extends Enum<B>. This defeats the point of the generic construct, which is to ensure that the generic parameter is always the exact type of the class in question. Giving a concrete example, Enum declares its compareTo method as
public final int compareTo(E o)
In this case, since you defined A to extend Enum<B>, instances of A could only be compared against instances of B (whatever B is), which is almost certainly not very useful. With the additional construct, you know that any class that extends Enum is comparable only against itself. And hence you can provide method implementations in the superclass that remain useful, and specific, in all subclasses.
(Without this recursive generics trick, the only other option would be to define compareTo as public final int compareTo(Enum o). This is not really the same thing, as then one could compare a java.math.RoundingMode against a java.lang.Thread.State without the compiler complaining, which again isn't very useful.)
OK, let's get away from Enum itself as we appear to be getting hung up on it. Instead, here is an abstract class:
public abstract class Manipulator<T extends Manipulator<T>>
{
/**
* This method actually does the work, whatever that is
*/
public abstract void manipulate(DomainObject o);
/**
* This creates a child that can be used for divide and conquer-y stuff
*/
public T createChild()
{
// Some really useful implementation here based on
// state contained in this class
}
}
We are going to have several concrete implementations of this - SaveToDatabaseManipulator, SpellCheckingManipulator, whatever. Additionally we also want to let people define their own, as this is a super-useful class. ;-)
Now - you will notice that we're using the recursive generic definition, and then returning T from the createChild method. This means that:
1) We know and the compiler knows that if I call:
SpellCheckingManipulator obj = ...; // We have a reference somehow
return obj.createChild();
then the returned value is definitely a SpellCheckingManipulator, even though it's using the definition from the superclass. The recursive generics here allow the compiler to know what is obvious to us, so you don't have to keep casting the return values (like you often have to do with clone(), for example).
2) Notice that I didn't declare the method final, since perhaps some specific subclasses will want to override it with a more suitable version for themselves. The generics definition means that regardless of who create a new class or how it is defined, we can still assert that the return from e.g. BrandNewSloppilyCodedManipulator.createChild() will still be an instance of BrandNewSloppilyCodedManipulator. If a careless developer tries to define it to return just Manipulator, the compiler won't let them. And if they try to define the class as BrandNewSloppilyCodedManipulator<SpellCheckingManipulator>, it won't let them either.
Basically, the conclusion is that this trick is useful when you want to provide some functionality in a superclass that somehow gets more specific in subclasses. By declaring the superclass like this, you are locking down the generic parameter for any subclasses to be the subclass itself. This is why you can write a generic compareTo or createChild method in the superclass and prevent it from becoming overly vague when you're dealing with specific subclasses.
What is the java class type used for? I am confused about what it means and how it is different than declaring an object type:
Class className;
Thanks
There are several uses for a Class object. For example, say I want to create an instance of a class based on some class name stored in a config file.
String className = config.myClass;
Class clazz = Class.forName(className);
Object myClassInstance = clazz.newInstance();
It represents the runtime type of the object. The actual programmatic use of the Class type is often found in reflection and generics.
For example, loading a JDBC driver abstractly with help of Class#forName():
String jdbcDriverClassName = getItFromSomeExternalConfigurationFile();
Class.forName(jdbcDriverClassName);
Or typecasting an generic Object to a beforeknown type:
public static <T> T findAttribute(String key, Class<T> type) {
return type.cast(attributeMap.get(key)); // It's a Map<String, Object>.
}
...which can be used as
SomeType instance = findAttribute("someKey", SomeType.class);
A more extended example can be found here in flavor of a "generic object converter".
Actually, reading the java.lang.Class javadoc, including all of the available methods, should give you an idea what it can be used for.
Class is a special type of Object, i.e Class is a sub class of Object. Every class you define has its own Class object. You can access this as MyObject.class or myInstance.getClass(). In another word, any class you define has a Class attribute where as any class is an Object. I agree it is slightly confusing to a newbie.
javadoc says:
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.
Class has no public constructor. Instead Class objects are constructed automatically by the Java Virtual Machine as classes are loaded and by calls to the defineClass method in the class loader.
You can use it when checking the type of some variable or check for inheritance runtime.
It's also used in reflection, to load dynamically types and execute methods on them.
From the book Thinking in Java:
The Class object
To understand how Run Time Type Information (RTTI) works in Java, you must first know how type information is represented at run time. This is accomplished through a
special kind of object called the Class object, which contains information
about the class. In fact, the Class object is used to create all of the
'regular' objects of your class.
Most of the documentation regarding type erasure handling in Java assumes that the use case is handling a type like SomeType<ParamType>.
I am trying to process method parameter for the following method:
public void setOtherReferenceRanges(List<ReferenceRange<T>> referenceRanges)
When the container class is instantiated with a type DvQuantity, this signature should become
public void setOtherReferenceRanges(List<ReferenceRange<DvQuanitity>> referenceRanges) in runtime.
Using reflection one can see that the List has an actualTypeArgument which is ReferenceRange<T>. Since reflection uses class information, I would not expect it to give me ReferenceRange<DvQuantity>.
However, when I created the class containing this method, I passed the DvQuantity type as T. So the type filling in T should be available to Java runtime, but I could not find a way of getting it. I end up with a TypeVariableImpl object accessed via reflection, which does not seem to contain any useful data.
Can you think of any ways to discover this information in runtime?
When you say
when I created the class containing this method
I guess you mean when you create an object of that type, for example:
foo = new ContainerClass<DvQuantity>();
In that case, because of erasure, there is no way to recover the type DvQuantity.
However, if you create a class passing a type parameter to the superclass, like this
class DvQuantityContainerClass extends ContainerClass<DvQuantity> {...}
...
foo = new DvQuantityContainerClass();
Or, shorter, an inline anonymous subclass (which looks almost like the first example but with a subtle but important difference):
foo = new ContainerClass<DvQuantity>(){};
Then you can recover the type parameter, because you recover the type parameter used to extend a superclass at runtime. Unfortunately, Java itself doesn't provide an easy way to now get the type of the DvQuantityContainerClass.setOtherReferenceRanges method with the T filled in. For that, I've written gentyref, to do advanced reflection on generic types:
Method m = DvQuantityContainerClass.class.getMethod("setOtherReferenceRanges", List.class);
// this will return List<ReferenceRange<DvQuanity>>, like you are lookingn for
return GenericTypeReflector.getExactParameterTypes(m, DvQuantityContainerClass.class)
Generic type information is erased by the compiler and is not available at runtime. When I need to ensure a certain type at runtime I pass in a class argument:
public <T> void doSomething(T t, Class<T> c);
This is not always convenient or even possible, but for many cases it is possible.
So the type filling in T should be available to Java runtime, but I could not find a way of getting it.
Perhaps it's not entirely correct, but the way I think about it is that at runtime there is no actual class - just an object without a specific type which meets the interface of T. In other words, erasure happens not with objects, but instead with these nebulous (in the OOP world at least) type-things.
http://java.sun.com/docs/books/tutorial/java/generics/erasure.html
There are ways of capturing the type information inside the class itself (T types would need a method getUnderlyingType()... or something), but that's a bad idea. If you truly need to raw type of the object, I'd reconsider using generics.