I am trying to compare part with the c class given from the constructor but for some reason my IDE pops a warning that it will always be false.
Class<? extends Part> c;
public Slot(Class<? extends Part> c){
this.c = c;
}
public boolean addItem(Part part){
return part instanceof c;
}
Why is this instanceof statement always false and what is the correct syntax to compare part with c?
You should call the following Class method:
Class.isInstance(Object obj)
When you call "instanceof c", "c" should be a Class, not a variable. In your example, c is a variable whose type is Class.
Instead of this
if(part instanceof c) return true;
Try this
if(c.isAssignableFrom(part.getClass())) return true;
This is different than Class.isInstance(Object), because isAssignableFrom also returns true when part is the same type as or a sub-class of c.
So if you need to know if this is the exact same type use isInstance, if it could also be a sub-class, then use isAssignableFrom.
It's about understanding the operator instanceof and the Class class.
Type Comparison Operator instanceof:
At run time, the result of the instanceof operator is true if the
value of the RelationalExpression is not null and the reference could
be cast to the ReferenceType without raising a ClassCastException.
Otherwise the result is false.
This means that your code if (part instanceof c) ... will always return false, as part can never be cast to Class.
If you have a look at Class.inInstance(Object obj), you find that
This method is the dynamic equivalent of the Java language instanceof operator.
In other words:
If you know the checked type in compile-time, you use instanceof.
If you do not know the checked type in compile-time, but in run-time (so you have it stored in a variable of the Class type), you use Class.inInstance(Object obj).
Related
I'm a beginner in Java programming. Currently I'm reading about Inheritance and the equals method at this page.
I understand the explanations until this point:
Compare the classes of this and otherObject. If the semantics of
equals can change in subclasses, use the getClass test:
if (getClass() != otherObject.getClass()) return false;
If the same semantics holds for all subclasses, you can use an instanceof test:
if (!(otherObject instanceof ClassName)) return false;
I don't understand what 'semantics of equals' mean. Can someone share scenarios where we use getClass() and instanceof please?
Thank you for reading.
Simply put, getClass() returns the immediate class of the object. for example,
class A { }
class B extends A { }
if we create two objects from A and B,
A objA = new A();
B objB = new B();
now we can check how getClass work
System.out.println(objA.getClass()); //Prints "class A"
System.out.println(objB.getClass()); //Prints "class B"
So,
objA.getClass() == objB.getClass()
returns false. But
System.out.println(objB instanceof A); //Prints true
This is because instanceof returns true even if a superclass is given of the provided object.
So, when you design your equals() method, if you want to check the given object(otherObject) is instantiated from the same immediate Class, use the
if (getClass() != otherObject.getClass()) return false;
If it is okay that the given object(otherObject) is made even from a subclass of a Class (ClassName) you provide, use
if (!(otherObject instanceof ClassName)) return false;
Simply, "semantics of equals" means "The purpose you expect from equals() method". So you can use the appropriate method according to your need.
changing semantics of equals
It means that may be the equals method can be overwritten in subclasses, in such scenarios use getClass to check whether objects belong to same class.
In general, getClass vs instance of
We use getClass when we need to know the class of a particular object. Consider cases when there is linear chain of Inheritance as follows:
MainClass -> SubClassLevel1 -> SubClassLevel2
and initialize as
MainClass mc = new SubClassLevel2();
Here to know that which class in the hierarchy is the class of our object.
Now, instance of method is used in the cases where you have to merely check that whether x is an instance of class Y or not. It returns boolean.
Hope this answers your query :)
In my GameObject class I have the following method to check if the GameObject would be colliding with another object if it moved to the specified position:
public boolean collisionAt(Vector2d position, Class<? extends GameObject>... exclusions) {
if (getBounds() == null)
return false;
Rectangle newBounds = getBounds().clone();
newBounds.setPosition(position);
// Check collisions
for (GameObject object : new ArrayList<>(gameObjects)) {
if (object.getBounds() != null && newBounds.intersects(object.getBounds()) && object != this) {
boolean b = true;
for (Class<? extends GameObject> exclusion : exclusions) {
if (object.getClass().isInstance(exclusion))
b = false;
}
if (b)
return true;
}
}
return false;
}
I want to allow the program to define exclusions, for example if I don't want this method to return true if it collides with a Spell. But for some reason the Class.isInstance() line always returns false. I even tried this:
System.out.println(Spell.class.isInstance(Spell.class));
and the console outputs false! What's going on here?
The isInstance tests if the given object is an instance of the Class, not if the given Class is a subclass of the Class.
You have your invocation backwards. You need to test if the gameObject is an instance of one of the exclusion classes.
if (exclusion.isInstance(gameObject))
From official Javadocs
public boolean isInstance(Object obj)
Determines if the specified Object is assignment-compatible with the object represented by this Class. This method is the dynamic equivalent of the Java language instanceof operator. The method returns true if the specified Object argument is non-null and can be cast to the reference type represented by this Class object without raising a ClassCastException. It returns false otherwise.
You need to pass in the object of class rather than the class itself.
Example
SomeClass object = new SomeClass();
System.out.println(SomeClass.class.isInstance(object));
You need to pass in an instance of the class in question rather than a class literal. E.g.
Spell spell = new Spell();
System.out.println(Spell.class.isInstance(spell));
isInstance determines if the specified Object is assignment-compatible with the object represented by this Class. You're passing it a class when it expects an object.
The opposite should work:
Spell.class.isInstance(spell)
I don't understand why the following would NOT cause an error.
boolean condition = <whatever>;
return condition ? Collections.singleton("a field") : Collections.EMPTY_LIST;
Collections.singleton() returns a java.util.Set which obviously is NOT the same type as EMPTY_LIST.
Should that really NOT cause a type-mismatch error?
Both Collections.singleton() and Collections.EMPTY_LIST implement Collection (and extend Object for that matter). No type conversions are necessary to return the result of the ternary operator as a Collection or an Object.
The java compiler finds the most specific type that matches both parts. It gets tricky with primitive types, but only void is flatly forbidden. See the Java Language Specification on the conditional operator.
Starting point
This code by itself is not the whole picture – it contains a "return" statement, but we do not see the method signature, and thus do not see the return type.
boolean condition = true;
return condition ? Collections.singleton("a field") : Collections.EMPTY_LIST;
Method: return type Object
It would be totally fine to mix object types with a method return type of Object. For example, here's a method returning either a HashMap or an Integer. This is allowed because the method return type is Object, and both of those return types are Objects.
private static Object returnObject() {
boolean condition = true;
return condition ? new HashMap<>() : Integer.valueOf(1);
}
You could put the original code in a method with return type Object, and the compiler would be fine with it.
Actual object types
The type of Collections.singleton("a field") is Set<String>,
and Set has the following definition, showing it extends Collection:
public interface Set<E> extends Collection<E>
The type of Collections.EMPTY_LIST is List which has this definition, showing it extends Collection, too:
public interface List<E> extends Collection<E>
Both the set and the list share a common parent: Collection.
Method: return type Collection
If you put the original lines of code along with a method signature having return type "Collection", that would be allowed by the compiler since both possible return values are Collections.
private static Collection returnCollection() {
boolean condition = true;
return condition ? Collections.singleton("a field") : Collections.EMPTY_LIST;
}
Third option: Iterable
As shown above, the method can have a return type of either Collection or Object.
Additionally, you could specify the return type as
Iterable,
since Iterable is the parent of Collection.
I'm going through a book on data structures. Currently I'm on graphs, and the below code is for the vertex part of the graph.
class Vertex<E>{
//bunch of methods
public boolean equals(Object o){
//some code
}
}
When I try to implement this equals method my compiler complains about not checking the type of the parameter and just allowing any object to be sent it. It also does seem a bit strange to me why that parameter shouldn't be a Vertex instead of an Object. Is there a reason why the author does this or is this some mistake or antiquated example?
#Override
public boolean equals(Object obj)
{
if (!(obj instanceof Vertex)) return false;
else return // blah blah
}
equals(Object) is the method defined in the root - Object. If you don't match the signature exactly, Object's version will be called when someone checks if two objects are equal. Not what you want.
You've probably seen other methods (like Comparator) where you can use the exact time. That's because those APIs were generic-ified with Java 5. Equals can't be because it is valid to call equals with two separate types. It should return false, but it is valid.
equals is a method inherited from Object, is defined to be flexible enough so that you can take any object and test if it is equal to any other object (as it rightfully should be able to do), so how could it be any other way?
Edit 1
Comment from jhlu87:
so is it not good form to write an equals method that has an input parameter of vertex?
You are welcome to create your own overload to any method, including equals, but doing so without changing the name could risk confusing many who would assume that your equals is the one that inherits from Object. If it were my code and I wanted a more specific equals method, I'd name it slightly different from just "equals" just to avoid confusion.
If your method doesn't take an argument of type Object, it isn't overriding the default version of equals but rather overloading it. When this happens, both versions exist and Java decides which one to use based on the variable type (not the actual object type) of the argument. Thus, this program:
public class Thing {
private int x;
public Thing(int x) {
this.x = x;
}
public boolean equals(Thing that) {
return this.x == that.x;
}
public static void main(String[] args) {
Thing a = new Thing(1);
Thing b = new Thing(1);
Object c = new Thing(1);
System.out.println(a.equals(b));
System.out.println(a.equals(c));
}
}
confusingly prints true for the first comparison (because b is of type Thing) and false for the second (because c is of type Object, even though it happens to contain a Thing).
It's because this method existed before generics, so for backward compatabitity it has to stay this way.
The standard workaround to impose type is:
return obj instanceof MyClass && <some condition>;
It is because the author is overriding equals. Equals is specified in java.lang.Object and is something that all classes inherrits from.
See the javadoc for java.lang.Object
This question already has answers here:
How to determine an object's class?
(13 answers)
Closed 9 years ago.
Is there an easy way to verify that an object belongs to a given class? For example, I could do
if(a.getClass() = (new MyClass()).getClass())
{
//do something
}
but this requires instantiating a new object on the fly each time, only to discard it. Is there a better way to check that "a" belongs to the class "MyClass"?
The instanceof keyword, as described by the other answers, is usually what you would want.
Keep in mind that instanceof will return true for superclasses as well.
If you want to see if an object is a direct instance of a class, you could compare the class. You can get the class object of an instance via getClass(). And you can statically access a specific class via ClassName.class.
So for example:
if (a.getClass() == X.class) {
// do something
}
In the above example, the condition is true if a is an instance of X, but not if a is an instance of a subclass of X.
In comparison:
if (a instanceof X) {
// do something
}
In the instanceof example, the condition is true if a is an instance of X, or if a is an instance of a subclass of X.
Most of the time, instanceof is right.
If you ever need to do this dynamically, you can use the following:
boolean isInstance(Object object, Class<?> type) {
return type.isInstance(object);
}
You can get an instance of java.lang.Class by calling the instance method Object::getClass on any object (returns the Class which that object is an instance of), or you can use class literals (for example, String.class, List.class, int[].class). There are other ways as well, through the reflection API (which Class itself is the entry point for).
Use the instanceof operator:
if(a instanceof MyClass)
{
//do something
}
I agree with the use of instanceof already mentioned.
An additional benefit of using instanceof is that when used with a null reference instanceof of will return false, while a.getClass() would throw a NullPointerException.
Try operator instanceof.
The usual way would be:
if (a instanceof A)
However, there are cases when you can't do this, such as when A in a generic argument.
Due to Java's type erasure, the following won't compile:
<A> boolean someMethod(Object a) {
if (a instanceof A)
...
}
and the following won't work (and will produce an unchecked cast warning):
<A> void someMethod(Object a) {
try {
A casted = (A)a;
} catch (ClassCastException e) {
...
}
}
You can't cast to A at runtime, because at runtime, A is essentially Object.
The solutions to such cases is to use a Class instead of the generic argument:
void someMethod(Object a, Class<A> aClass) {
if (aClass.isInstance(a)) {
A casted = aClass.cast(a);
...
}
}
You can then call the method as:
someMethod(myInstance, MyClass.class);
someMethod(myInstance, OtherClass.class);