Just playing with java fundamentals I came up with question whether I can check inheritance between two .class objects without instantiating them.
For example, if I have a class Foo, which is a subclass of Baa:
Foo a = new Foo(); return a instanceof Baa will return true.
But what do I have to do if I wanna do the equivalent test with Foo.class and Baa.class?
I think I can do something like this:
Foo.class.newInstance() instanceof Baa.class
But would it be possible to test the same without instantiating Foo?
You can use Class.isAssignableFrom(Class) to check the hierarchy in inheritance. According to java-docs:
Determines if the class or interface represented by this Class object is either the same as, or is a superclass or superinterface of, the class or interface represented by the specified Class parameter.
This will not instantiate any of the classes and you will get the desired functionality.
Related
We know that by default, every class inherits ultimately from the java.lang.Object class, which is why methods such as toString are readily available to every class. Therefore, a generic class is effectively as follows:
public class Foo extends java.lang.Object {
public Foo() {super(); }
}
However, is it at all possible to create a class which does NOT automatically inherit from the Object class, and thus, has no superclass? And if so, what would be the effect?
We can't write class without having java.lang.object as superclass. Compiler will automatically extend the object class.Only the object class itself and interfaces are the ones which do not extend object class.
No, that is not possible. From the documentation:
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.
I do not believe that you can have a class that does not inherit Object. Quoting from Object as a Superclass..
The Object class, in the java.lang package, sits at the top of the
class hierarchy tree. Every class is a descendant, direct or indirect,
of the Object class. Every class you use or write inherits the
instance methods of Object. You need not use any of these methods,
but, if you choose to do so, you may need to override them with code
that is specific to your class.
In cases where the inheritance is not explicitly stated, it is implicitly stated. Now, inheritance will obviously not form a cycle. The Object class is the only one which inherits from nobody, it's the top of hierarchy.
I have a class FTSFor rather I should say java enum which implements MEnum interface and SF interface as follows :
public enum FTSF implements MEnum<FTSF>, SF {
private static final Map<String, FTSF> cmap = MEnum.bCMap(FTSF.class);
.........
so on and so forth
Questions :
1) Since FTSF is a Java enum, that's why it can implement as many classes it want? I am slightly confused since implement keyword is usually used when a class implements an interface.
2) I know that one can pass class as an argument inside a method parameter,so above, when FTSF class is passed inside the bCMap method,i am trying to figure out what does gets passed as an argument inside bCMap method. Is it the class file that gets generated when we compile Java code?
1) Enums, just like any other class, can implement as many interfaces as you like. (I got a bit confused as you asked "why it can implement as many classes as it wants". A class can only implement interfaces, not classes. It can extend only one class. As you clarified in a later comment, both MEnum and SF are interfaces.)
2) When you compile a Java class, called T, the Java compiler creates a single object which is an instance of a generic class Class<T>. This is a special class which holds information about the class you've just written - such as its name, and the set of fields and methods it contains. It's part of a feature called Reflection. In this statement from your question:
private static final Map<String, FTSF> cmap = MEnum.bCMap(FTSF.class);
the expression FTSF.class is a reference to this single instance of class Class<FTSF>. So the method bCMap() is being passed a reference to this object; however, given the context, the most likely reason for passing this argument to the method is not because the method wants to know about the class, but because the class object is being used as a dummy argument to tell the compiler that the generic method bcMap returns a Map<String, FTSF> (instead of, for example, a Map<String, Object>).
1) Java classes can only extend one class, but they can implement as many as they want. It doesnt have to do with FTSF being an enum.
2) It is the Class object that represents the FTFS. You can also get it by calling getClass() as long as you arent in a subclass. It is useful for things like reflection. The documentation for it is here https://docs.oracle.com/javase/7/docs/api/java/lang/Class.html
I'm having some trouble finding the specifics on what happens when you return a subclass in a method of superclass type in Java. For example:
public class SuperClass
{
int a;
}
public class SubClass extends SuperClass
{
int b;
}
SuperClass superObj;
SubClass subObj;
private SuperClass getObject ()
{
return subObj;
}
public static void main (...)
{
superObj = getObject();
}
What exactly happens to subObj when it's returned as its superclass? I realise while typing this example that I could probably just as easily test it myself, but i'm still curious as to what the process is exactly when this happens, and whether it's considered good (if it works, that is) or bad practice.
I'm asking because I'm currently working on a project in which I have two abstract base classes, and several subclasses for each of them. I'm trying to find out good/bad ways to handle having to change from one subclass to another while still using the convenience polymorphism adds when using abstract base classes.
EDIT: I fixed main and the class declarations, sorry about that.
Casting does not fundamentally change an object to a different type, it simply tells the compiler to view the object as its superclass (or subclass, when downcasting). In your example, superObj is still an instance of the SubClass type, but it now appears to be a SuperClass. What this means is that if you try to reference superObj.b, you will get a compilation error (since b does not exist in SuperClass). However you could reference (SubClass)superObj.b. In this case you are telling the compiler to consider subClass as an instance of SubClass (which it really is).
Let's take this a step further and add another class to your code:
public class SisterClass extends SuperClass
{
int c;
}
Without changing anything else in your code (other than the syntax problems), you try to reference ((SisterClass)superObj). This will compile but fail with a ClassCastRuntime runtime error. Although SisterClass is a subclass of SuperClass, superObj is not an instance of SisterClass. So, you can only cast to what the object actually is.
There are some oddities in your code (defining a method inside main?), but that not withstanding... The method getObject will not change your subObj, it will simply return a reference to it that looks like type SuperClass. By "looks like" I mean that it will only expose any methods or members from SuperClass. However, if you take that returned value and attempt to downcast it to SubClass, the cast will succeed and you will find the field/methods from SubClass will work as you expect without any loss of information from having been returned as SuperClass.
SubClass is extension of SuperClass
you are just casting it down to its base class, all extensions are not available, you should not be looking to try and get them back to Implementations as you would be guessing what that are, as you could extend it numerous times in various ways,
The returned class would have a but not b
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.