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.
Related
Why does this code not compile?
public class Wrapper<T> extends T {}
Is it because this is semantically never a proper design choice? Or can this physically not compile in any language because of some sort of type ambiguity?
I'd imagine you could use it to create a public class Persistent<T> extends T {} that allows you to for example extend the T with some functionality to serialize the T to a byte array and store it on disk, while still allowing instances of Persistent<T> to be passed to functions that would otherwise only take values of type T.
As such this would be possible:
EDIT: this would not be possible, as there could be no sensible implementation for load() (as correctly pointed out by michid). To not corrupt his comment though, I'll leave it here.
Integer i1 = Integer.valueOf(5);
Persistent<Integer> i2= new Persistent<Integer>();
i2.load(i1) //example method to load i1 into i2, basically serializing it
List<Integer> myIntegers = new ArrayList<>();
famousPeople.add(i1);
famousPeople.add(i2);
When you extend a class you extend the existing functionality by some additional one provided by the super class. When the super class is T it can be anything but you cannot know what. So how would you extend something you know nothing about?
I am wondering. I have a class OccList<T>. I am fine with OccList holding any object, but I want to do more if T is a String, or if T is an integer.
Is there any way I can use the same name while doing it? My solution thus far is to create a new class class StringOccList extends OccList<String>. Optimally I'd like to be able to use OccList<String> and let java create the appropriate class according to the type used, much like method signatures work. Is it possible? Is there a better solution?
It has to be a different class, unless you want the added functionality to be part of the base class.
Think about it; lets say you have a method printAll that calls System.out.println on all the contents of the list. Where is the method going to go?
You only want the method to be callable if it's a String. Then it cannot be part of the base class (because otherwise it would be defined in the base class), so you need to use a different class like StringOccList
It's okay if the method is callable in the base class. You can write it so that (in the case of String) it calls T.toString on all members, or you can have the method throw an exception if T isn't the appropriate type.
That's what it means to be "generic" - the class will work for any kind of inner type. If it won't work for any kind of inner type, then it's not generic anymore!
Yes, you could make use of the one place where Java infers types, that is method returns. Imagine you want an OccList of String, but you don't want to do this
OccList<String> list = new OccList<String>();
Well, then you just write up a method to do that. Like this:
public static <E> OccList<E> newOccList(){
return new OccList();
}
and invoke it like this:
OccList<String> stringList = newOccList();
OccList<Integer> integerList = newOccList();
OccList<File> fileList = newOccList();
It'll work for any generic type you need.
This is used in the Google Guava library, please refer to it here
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.
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.
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.