I'm having a problem with casting Classes to each other.
To explain it in more detail, take a look at this image.
In my code, I do SkillBase s = new SkillBase(); and then set some values in that class.
Then I try to do Subclass sub = (Subclass)s; but when running it it gives a ClassCastException.
I added a small debug part, which checks if it's instanceof which returns true.
I've tried the google, saw some questions on here aswell and read them (none of them had an answer that was for me)
So, what do I do?
SkillBase is not an instance of Subclass, so why do you think casting will work? Try with this:
SkillBase s = new Subclass();
Subclass sub = (Subclass)s;
which will succeed. Also I think you are not correct with instanceof, I am certain that:
s instanceof Subclass
yields true in the the code above but false in your case.
Thinking in real world terms: you can always cast Dog to Animal because every dog is an animal*, but casting Animal to Dog might fail since some animals aren't dogs.
* in fact, compiler does that for you, it is known as polymorphism
You can only up-cast i.e. assign sub classes to super class references. Think of it this way: Subclass extends the Superclass by adding a new method f(). Now Superclass doesn't know any thing about f() and hence the problem.
You're probably using instanceof wrong.
The runtime is right to crash, as SkillBase is not a Subclass.
The other way around is true.
s can't be cast to Subclass because it wasn't instantiated as a Subclass. It is a Skillbase. If you want to use a Subclass why not just instantiate it?
Subclass s = new Subclass();
You can still set the parameters you want because they hare inherited by Skillbase and the cast is no longer necessary.
The problem is that you are not using casting properly. A class can always be cast as its parent, but not the other way around. The concept is that a child class (by definition) knows the structure of the parent, and (by definition) already supports all the signatures in the parent. Consequently, the parent is a subset of the child.
The inverse, however, is not true. The parent class knows nothing about the child class and/or whether the child has added extra signatures to its structure. Consequently, there is no way to tell the compiler to treat the parent as a child and make available all the methods that the child has in the parent.
It layman speak, water (child) is a liquid (parent), but not all liquids are water. Consequently, any measurements you want to make on liquids (ie: quantity, viscosity, etc) hold true for water as well, but not the other way around (ex: density of water is completely different than density of oil).
So to bring this all back to your situation, you can cast Subclass as a Skillbase but not the other way around.
Subclass instanceof Skillbase == true
(Skillbase) new Subclass() - also valid
(SKillbase) new Sub#2 - also valid
etc...
Related
apologies if this is simple or has been answered before, I'm new to Java and in my research I can't find too much on this issue and have not yet found a solution.
I have an ArrayList with multiple classes that all share a common Interface, in this example the interface is called "Packable". I'm trying to create a method that takes a class parameter and sweeps through each element of this ArrayList, returning a new list containing all the items in the original list that are of the same class as the reference parameter.
This is my code so far, trying the instanceof method:
public List<Packable> getOfType(Packable reference){
List<Packable> typeOfItems = new ArrayList<>();
for (Packable item: itemsStored) {
if (item instanceof reference){
typeOfItems.add(item);
}
}
return typeOfItems;
}
This is throwing an error as it doesn't yet recognise reference as a class. This question mentions a method isAssignableFrom with the answer stating: "When using instanceof, you need to know the class of B at compile time. When using isAssignableFrom() it can be dynamic and change during runtime." (Thanks Marc Novakowski)
I understand that given the parameter the class isn't known at compilation and as such I've tried implementing isAssignableFrom and can't really seem to get it to work. The IDE doesn't really recognise or suggest it, and there isn't too much about the method online. I've tried implementing it the way the JavaDocs suggest but this isn't working either:
if (reference.isAssignableFrom(item.getClass())){
typeOfItems.add(item);
}
Any help or advice on methods to look into would be greatly appreciated. Thanks for reading the question, and again apologies if this is simple or has been answered elsewhere and I've just missed it. Thanks everyone
I'm not sure what Packable is, but you appear to be confused about a few concepts here.
In java, Packable reference does not represent the Packable concept. It represents a specific instance of Packable (or null).
In other words, given Dog dog, that means dog is some specific dog. Not 'the general concept of a dog'. We know that the specific animal that dog is referring to is, at least, a Dog. It could be Fifi, the neighbour's schnauzer.
instanceof, on the other hand, is about the general concept of things: if (fifi instanceof Dog) is how you're supposed to use it. You're more or less attempting to do the equivalent of if (fifi instanceof rover) which just doesn't make sense. How can one dog be 'an instance' of another? It's not that the answer is 'true' or 'false', but that the very question doesn't even make sense, which is why javac doesn't compile it. It has no idea what this even means.
Java, being java, makes objects of many things. Notably including the very notion of things. Thus, there is the class java.lang.Class, instances of which represent classes. A bit of alice-going-down-the-rabbit-hole thing is happening here: Classes as a concept are also represented as instances of the java.lang.Class class.
A class OBJECT (so, an instance of java.lang.Class) has the .isAssignableFrom method. This in fact takes another j.l.CLass as argument, it's for checking if one type is a subtype of another. In that sense, the question linked is needlessly confusing - you're really looking for the instanceOf method (there is an instanceof language construct, but the j.l.Class class has an isInstance method, which is unrelated, other than that they roughly accomplish the same goal: Check if some INSTANCE is of a type that is equal to, or a subtype of, some TYPE.
This is an example of how to use it:
Class<?> c = Number.class;
Object o = Integer.valueOf(5);
System.out.println(c.isInstance(o));
this is more or less equivalent to:
Object o = Integer.valueOf(5);
System.out.println(o instanceof Number);
Except now the Number part no longer needs to be written at 'write the code' time, you can supply it, say, read it from a parameter. You'd have to, of course, dynamically construct the Class instance. You can do so either by string-lookup, or by getting the actual type of an actual object. For example:
String input = scanner.next(); // user types in "java.lang.Number"
Class<?> c = Class.forName(input);
Object o = Integer.valueOf(5);
System.out.println(c.isInstance(o));
Or:
Object i = Integer.valueOf(5);
Object d = Double.valueOf(10);
Class<?> c = i.getClass(); // will be java.lang.Integer.class
System.out.println(c.isInstance(d)); // false
But doing this latter bit is really dangerous. Often i.getClass() returns some hidden impl detail subtype (java is hierarchical and object oriented, anywhere, say, an ArrayList is needed, someone is free to make a new class: class MyVariantOfArrayList extends ArrayList, and use that - now you write ArrayList foo = getList(), but foo.getClass() doesn't return ArrayList - no, you invoke that method on the object the foo variable points at, so, it'd be MyVariantOfArrayList.class, not ArrayList.class.
It's possible Packable itself represents a type. But then it either needs to also have isInstance and isAssignableFrom and such (and you need to start questioning why you're badly reinventing the wheel here - java.lang.Class already exists!), or it needs a .getRepresentedClass() method. You can't call it .getClass(), as the JVM has already given all objects that method, and it would return Packable.class itself.
For the following question,
Suppose the object referenced in a cell of
ArrayList<Polygon> pentagonGroup
is of type Pentagon. If you later reference that object, what type will it have?
What would the answer be?
I tried playing around in a IDE and it seems like child objects even when placed into a Parent list are identified as a Child when doing the following operation.
Child c = new Child();
ArrayList<Parent> pa = new ArrayList<Parent>();
pa.add(c);
Class cls = pa.get(0).getClass();
System.out.println(cls.getName());
This seems kind of odd when one is unable to use Child object specific methods without downcasting it back to an Child.
System.out.println(pa.get(0).getChildMessage()); // invalid
System.out.println(((Child)pa.get(0)).getChildMessage()); // valid
Given my results the answer to the first question would be (Pentagon). Would that be correct?
EDIT:
So I'm actually still not sure about the very first question asked above; Would the answer be Polygon or would it be Pentagon?
At runtime, you can get the type of pa.get(0):
Class cls = pa.get(0).getClass();
System.out.println(cls.getName());
While at compile stage, the compiler only knows pa.get(0) is Parent, so you can not call pa.get(0).getChildMessage() without down casting. It's for type safe.
In fact, you can casting any object to Child to make it compile,
Object o = new Object();
System.out.println(o.getChildMessage());
but it will throw casting exeception at run time.
Assuming Child extends Parent, the ArrayList is composed of Parent objects, as far as the compiler is concerned. So when you get a value from the list, it is a Parent. In your case, it is also a Child, but it might not be in the general case.
Remember java is not like groovy with dynamic binding, so if the Parent doesn't have the getChildMessage() method, it has no method it can assign to. So you have the option of either defining a getChildMessage() method in Parent (maybe return an empty string or throw an exception) and override it in Child, or downcasting as you did, but then make sure it is a Child first with instanceof, e.g.
Say I have this class hierarchy:
Animal <-- FourLegged <-- Dog
Animal <-- FourLegged <-- ....
Animal <-- ThreeLegged <-- ... (what has 3 legs?)
Animal <-- TwoLegged <-- Chicken
Animal <-- TwoLegged <-- ...
(Forgot what the scientific terms for four-legged and two-legged animals are. But that's beside point, right? :) )
If I have an Animal object, and I need to know whether it is a FourLegged or if it is a TwoLegged, I would normally do animalObject instanceof FourLegged.
Is that slower than adding a bunch of isFourLegged(), isThreeLegged(), isTwoLegged(), to Animal class?
(I would like to know the performance impact. This is NOT a design exercise. So I would appreciate it if you won't be wasting time suggesting how to re-write the class)
Edit
Some people have suggested adding 'getNumberOfLegs()", which is perfectly reasonably given this specific example. But suppose the point is NOT to have the number of legs, but to get what type of animal this is.
If your subclasses doesn't add any behavior and is just a way to specify the number of legs, you should go with this refactoring called Replace Subclass With Fields. => no need for subclasses any more.
Otherwise, add a polymorphic method like: numberOfLegs(), implemented by each of your Animal's subclasses.
Try
Animal animal = new Dog();
if(animal.getClass().isAssignableFrom(FourLegged.class)){
System.out.println("FourLegged");
}
Do it in same way for others
The question centers around the "speed" of execution: Is one way slower than another?
Unless you're talking about algorithmic differences, the only way to know anything remotely accurate about performance is to measure your expected use case. In Java many variables affect performance, including the JVM chosen, JVM arguments, and so on.
Having said that, it is straightforward to see that instanceof potentially has more work to do:
Set checkClass = this.getClass()
Is checkClass == the target class? If yes, return true.
Does checkClass have a superclass? If no, return false.
Set checkClass = superclass of checkClass
Goto 2
(With potentially more effort involving the possibility of interfaces; in this case I am presuming that the JVM implementation is aware that the target class is not an interface and can use that knowledge to its benefit.)
However, a virtual method call requires no potential iteration: Fetch a function pointer from the object's vtable, and call it.
But when the target class is the immediate superclass of the object, then there is only one iteration in traversing the class hierarchy. Is that case "faster" or "slower" than a virtual method call?
Bottom line: It depends. When performance matters, measure. In the absence of data clearly pointing to a performance bottleneck with the code, prefer code that is clear, concise, understandable, and maintainable.
I know this question has been asked a lot, but the usual answers are far from satisfying in my view.
given the following class hierarchy:
class SuperClass{}
class SubClass extends SuperClass{}
why does people use this pattern to instantiate SubClass:
SuperClass instance = new SubClass();
instead of this one:
SubClass instance = new SubClass();
Now, the usual answer I see is that this is in order to send instance as an argument to a method that requires an instance of SuperClass like here:
void aFunction(SuperClass param){}
//somewhere else in the code...
...
aFunction(instance);
...
But I can send an instance of SubClass to aFunction regardless of the type of variable that held it! meaning the following code will compile and run with no errors (assuming the previously provided definition of aFunction):
SubClass instance = new SubClass();
aFunction(instance);
In fact, AFAIK variable types are meaningless at runtime. They are used only by the compiler!
Another possible reason to define a variable as SuperClass would be if it had several different subclasses and the variable is supposed to switch it's reference to several of them at runtime, but I for example only saw this happen in class (not super, not sub. just class). Definitly not sufficient to require a general pattern...
The main argument for this type of coding is because of the Liskov Substituion Principle, which states that if X is a subtype of type T, then any instance of T should be able to be swapped out with X.
The advantage of this is simple. Let's say we've got a program that has a properties file, that looks like this:
mode="Run"
And your program looks like this:
public void Program
{
public Mode mode;
public static void main(String[] args)
{
mode = Config.getMode();
mode.run();
}
}
So briefly, this program is going to use the config file to define the mode this program is going to boot up in. In the Config class, getMode() might look like this:
public Mode getMode()
{
String type = getProperty("mode"); // Now equals "Run" in our example.
switch(type)
{
case "Run": return new RunMode();
case "Halt": return new HaltMode();
}
}
Why this wouldn't work otherwise
Now, because you have a reference of type Mode, you can completely change the functionality of your program with simply changing the value of the mode property. If you had public RunMode mode, you would not be able to use this type of functionality.
Why this is a good thing
This pattern has caught on so well because it opens programs up for extensibility. It means that this type of desirable functionality is possible with the smallest amount of changes, should the author desire to implement this kind of functionality. And I mean, come on. You change one word in a config file and completely alter the program flow, without editing a single line of code. That is desirable.
In many cases it doesn't really matter but is considered good style.
You limit the information provided to users of the reference to what is nessary, i.e. that it is an instance of type SuperClass. It doesn't (and shouldn't) matter whether the variable references an object of type SuperClass or SubClass.
Update:
This also is true for local variables that are never used as a parameter etc.
As I said, it often doesn't matter but is considered good style because you might later change the variable to hold a parameter or another sub type of the super type. In that case, if you used the sub type first, your further code (in that single scope, e.g. method) might accidentially rely on the API of one specific sub type and changing the variable to hold another type might break your code.
I'll expand on Chris' example:
Consider you have the following:
RunMode mode = new RunMode();
...
You might now rely on the fact that mode is a RunMode.
However, later you might want to change that line to:
RunMode mode = Config.getMode(); //breaks
Oops, that doesn't compile. Ok, let's change that.
Mode mode = Config.getMode();
That line would compile now, but your further code might break, because you accidentially relied to mode being an instance of RunMode. Note that it might compile but could break at runtime or screw your logic.
SuperClass instance = new SubClass1()
after some lines, you may do instance = new SubClass2();
But if you write, SubClass1 instance = new SubClass1();
after some lines, you can't do instance = new SubClass2()
It is called polymorphis and it is superclass reference to a subclass object.
In fact, AFAIK variable types are meaningless at runtime. They are used
only by the compiler!
Not sure where you read this from. At compile time compiler only know the class of the reference type(so super class in case of polymorphism as you have stated). At runtime java knows the actual type of Object(.getClass()). At compile time java compiler only checks if the invoked method definition is in the class of reference type. Which method to invoke(function overloading) is determined at runtime based on the actual type of the object.
Why polymorphism?
Well google to find more but here is an example. You have a common method draw(Shape s). Now shape can be a Rectangle, a Circle any CustomShape. If you dont use Shape reference in draw() method you will have to create different methods for each type of(subclasses) of shape.
This is from a design point of view, you will have one super class and there can be multiple subclasses where in you want to extend the functionality.
An implementer who will have to write a subclass need only to focus on which methods to override
How does inheritance work in relation to a for-each loop? Imagine I have two classes: SubClass and SuperClass, and I have the following ArrayList.
/**
* Containes both SuperClass and SubClass instances.
*/
ArrayList<SuperClass> superClasses = new ArrayList<SuperClass>();
Is it possible to iterate over superClasses in such a way as to only select subClasses.
The following:
for(SubClass subClass : superClasses){
// Do Foo
}
does not do this.
The following is the only thing that I could get to work:
for(SuperClass superClass : superClasses){
if(superClass instanceof SubClass){
// Do Foo
}
}
However I do not want to use instanceof unless absolutely necessary, as I keep reading everywhere (StackOverflow, Oracle Tutorials etc) that one can almost always find a better solution that increases encapsulation. Is there a more elegant way of doing this?
Well you could write a helper method to hide the instanceof test... Guava has a method like this, for example, in Iterables.filter, which you could use like this:
for (SubClass subclass : Iterables.filter(superclasses, SubClass.class)) {
...
}
It's only moving the instanceof check though really - it's not getting rid of it. Fundamentally you need that check, because something's got to do the filtering.
The first approach (for (SubClass subClass : superClasses)) cannot work as the compiler cannot ensure that there are only objects of tyoe SubClass in there.
In Java (without external libraries) it is not possible to preselect on the Class. Therefore the instanceof is the normal way to do this.
instanceof would work absolutely fine in this situation. But if you really do have reasons for not using it you could always give the superclass some variable, Boolean skipMe = true, and change that to false in the subclass if you wanted.
But I suggest using instanceof
I recommend to manage a separate List which only contains instances of SubClass, if possible.