I've noticed that calling equals(""); in a method of a class is not generating any error within Eclipse. I've never seen .equals called without something like string1.equals(string2);.
package voodoo;
public class Equals {
public void method(){
equals("");
}
}
What's going on here and when would calling equals() by itself ever be used?
If I put that into a JUnit to test, it runs and passes.
equals that you are calling is Object's equals method, which can be called on this reference without specifying it explicitly. In other words, your call is equivalent to
this.equals("");
This is perfectly valid, although a well-behaved implementation must always return false. Note that the return value is ignored, which is legal as well.
You can see what's going on by overriding equals with something that prints a message, as a matter of an experiment:
public class Equals {
public void method(){
equals("");
}
#Override
public boolean equals(Object other) {
System.out.println("I am being compared to '"+other+"'");
return super.equals(other);
}
}
equals is non-static and it is calling equals of Object which is similar like calling any other method of the class. Moreover, our class is child of Object. Method call is something like thisObject.equals(emptyString) note here String is also an Object. So, ultimately we are invoking currntObject.equals(object) method from child of the Object.
It is similar to,
class A {
public boolean ok(Object str) {
return false;
}
}
class B extends A {
public void method(){
ok("");
}
}
Here child has not overriden the equals so, it will call the method of it's parent and it will refer to the current instance.
Since everything is subclass of Object class, here you are calling super class (Object) equals method. And it receives Object as a parameter where "" is a string object, it compiles fine.
And it returns boolean actually, but you are ignoring it to receive. That's legal to ignore the result.
If you receive it and check, that returns false since your Equals class is not equals to an empty string.
equals(...) without explicit object calls the method on this. In your example you are comparing the instance of Equals to an empty string.
The equals() public method at Object class. All class by default a direct/indirect child class of Object class. Your Equals class doesn't inherit any class explicitly. So it is an direct subclass of Object.
And in Object class the method equals() is declared like this -
public boolean equals(Object obj){}
So your code is completely valid. You are actually calling Equals.equals() at method().
Related
I'm trying to figure out what the syntax is for calling an object inside a method..
Pseudocode:
boolean check(Object someObject) {
return someObject == theOtherObject;
}
public static void main(String args[]) {
someClass one = new someClass();
someClass two = new someClass();
one.check(two);
}
So the check method is supposed to check whether the two objects are equal, but how would I specify the other object (theOtherObject should be one)?
Thanks in advance!
One word answer: this
boolean check(Object someObject) {
return someObject == this;
}
which will test object identity only. You should override equals and use that.
if (one.equals(two)) {
// ...
}
You can have the boolean check(Object o) method inside SomeClass and check
boolean check(Object o) {
this == (SomeClass) o;
}
This would work only if both reference variables are pointing to same object. Moreover the right way to check if two objects are meaningfully equal would be to use the inherited equals and hashCode method.
Override equals and hashCode method.
Why do I need to override the equals and hashCode methods in Java?
https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-
So what you're asking for there is actually already a command in java.lang.Objects class to compare to objects.
one.equals(two)
the comparison this does is called a shallow comparison. So if that's what you're looking to do then this would work. For reference, the definitions of shallow comparison defined by geeksforgeeks.org is
Shallow comparison: The default implementation of equals method is defined in Java.lang.Object class which simply checks if two Object references (say x and y) refer to the same Object. i.e. It checks if x == y. Since Object class has no data members that define its state, it is also known as a shallow comparison.
if you're looking to do a more complicated comparison you're the best bet would be to actually override the equals command in the one class file
this article would be a good place to start to learn more about this topic.
https://www.geeksforgeeks.org/equals-hashcode-methods-java/
If the toString() method of a class is not overridden (or overloaded), and another method that returns a string is defined in the class, then what happens when I pass an instance of the class where a String is expected?
If your class extends Object, you will get the result of Object#toString(), which is what will be called. If your class extends something else, it will get the first #toString in the inheritance path.
Fun fact: It takes less time to test this than asking a question on Stack Overflow and getting an answer.
As you may know, every single class you create directly or indirectly inherits from the almighty Object class! If you don't override toString, calling toString will result in a call to the toString method of the nearest ancestor.
Suppose A inherits from B which inherits from C which inherits from D. Only C has overridden toString.
Calling toString on an object of... will result in calling the toString of...
A C
B C
C C
D Object
I hope you understand that.
Actually, not only does the toString behave like this. Every method does this as well!
Now that you know Object.toString will be called. What does it do actually?
From this answer, we know that Object.toString outputs something like this:
FullyQualifiedNameOfYourClass#12345
FullyQualifiedNameOfYourClass basically means your class name, followed by the package that it is in e.g. com.example.MyClass.
12345 is the hashcode of the object, returned by hashCode() on the object.
So will Object.toString call one of your class' methods that returns a string, if you ever declared one?
Nope. Because it just doesn't. The documentation of toString clearly says that it just returns something like FullyQualifiedNameOfYourClass#12345 and nothing else.
Even if it did, it makes no sense. What if you declared two methods that return a string? Which one should it choose? Also, reflection takes time and will slow down the whole thing.
Using the name of the class where a String is expected is not allowed. Consider the following:
class Foo {}
class Bar {
public void baz(String a) {
// Do something
}
public void binky() {
baz(Foo); // Compiler error
}
}
However, you could do the following:
class Foo {}
class Bar {
public void baz(String a) {
}
public void binky() {
Foo b = new Foo();
baz(b.toString());
}
}
Because the .toString() method of class Foo is not overridden, you will inherit the default .toString() from the Object class. This default behavior will print a string consisting of the name of the class of which the object is an instance, the at-sign character #', and the unsigned hexadecimal representation of the hash code of the object. (Thanks Kevin!)
I am practicing for an exam, and found a sample problem that I don't understand.
For the following code, find what the output is:
public class Test {
private static int count = 0;
public boolean equals(Test testje) {
System.out.println("count = " + count);
return false;
}
public static void main(String [] args) {
Object t1 = new Test();
Object t2 = new Test();
Test t3 = new Test();
Object o1 = new Object();
++count; t1.equals(t2);
++count; t1.equals(t3);
++count; t3.equals(o1);
++count; t3.equals(t3);
++count; t3.equals(t2);
}
}
The output of this code is count = 4, but I don't understand why. Can anyone help me?
The first thing you should note is that public boolean equals(Test testje) doesn't override Object's equals, since the argument is Test instead of Object, so the signatures don't match.
Therefore the main method calls equals(Test testje) exactly once - when executing t3.equals(t3); - since that's the only case in which both the static type of the instance equals is executed for and the type of the argument are the Test class.
t3.equals(t3); is the 4th equals statement (which comes after 4 increments of the static count variable), so 4 is printed.
All the other equals statements execute Object's equals, and therefore print nothing.
A more detailed explanation :
t1.equals() calls Object's equals regardless of the type of the argument, since the static (compile time) type of t1 is Object, and the Test class doesn't override that method. The Object class doesn't have an equals method with a single Test argument, so equals(Test testje) can't be called, regardless of the dynamic (runtime type) of t1.
t3.equals() can execute either Object's equals or Test's equals, since the compile time type of t3 is Test, and the Test class has two equals methods (one inherited from the Object class and the other defined in the Test class).
The method being chosen depends on the compile time type of the argument :
1. When the argument is Object (as in t3.equals(o1); or t3.equals(t2);), Object's equals is called and nothing is printed.
2. When the argument is Test, as in t3.equals(t3);, both versions of equals match that argument, but due to the rules of method overloading, the method with the most specific argument - equals(Test testje) - is chosen and the count variable is printed.
The equals method in Test takes an instance of Test.
All the previous attempts have been made with an instance of Object, which take the inherrited method from the Object class:
public boolean equals(Object o){
return this == o;
}
Since there is no print in there, it won't print any value.
Your ++count; will increment the value of count, so the moment when you actually call your
public boolean equals(Test testje){...
method, that does print that value, the value of count is 4.
t3.equals(t3) is the only line which has the right arguments that match the method signature public boolean equals (Test testje) so it's the only line in the program which actually calls that print statement. This question is designed to teach you a few things.
All class implicitly extend Object
Object.java contains an equals method which takes type Object
multiple methods with the same name can exist provided they have different arguments - this is known as method overloading
the method method overload who's signature matches the arguments at runtime is the method that gets invoked.
Essentially the trick here is that Test implicitly extends Object like all java classes do. Object contains an equals method that takes type Object. t1 and t2 are typed such that at run time the arguments never match the method signature of equals that is defined in Test. Instead it's always calling into the equals method in Object.java because either the base type Is Object in which case the only methods you have access to are the ones defined in Object.java or the derived type is Object in which case
public boolean equals(Test testje)
Cannot be entered because in that case at runtime the argument is of type Object which is a Superclass of Test, not a subclass. So instead it looks at the equals method in the Test.java's implicitly typed superclass Object.java which also contains an equals method, which just happens to have a method signature of
public boolean equals (Object o)
which in this case match our arguments at runtime so this equals method is the one that executes.
Notice in the case of t3.equals(t3) both the base type and the derived type of t3 are Test.
Test t3 = new Test ();
this means that at runtime you are calling the equals method in Test.java and the argument you are passing in is actually of type Test so the method signatures match and the code inside Test.java executes. At this point count == 4.
Bonus bit of knowledge for you:
#Override
annotation you may have seen in a few places explicitly instructs the compiler to fail if it does not find method with the exact same signature somewhere in a Superclass. This is useful to know if you definitely intend to override a method and you want to be absolutely sure that you really are overriding the method and you haven't accidentally changed the method in either the superclass or subclass but not both and Introduced a runtime error where the wrong implementation of the method is being called causing unwanted behavior.
There's two key things that you should know.
Overridden methods must have the exact signatures as their superclass have. (in your example this condition doesn't meet.)
In Java for an object, we have two types: compile type and runtime type. In the following example compile type of myobj is Object but its runtime type is Car.
public class Car{
#Override
public boolean equals(Object o){
System.out.println("something");
return false;
}
}
Object myobj = new Car();
Also you should note that myobj.equals(...) results in printing something in the console.
I really am a little confused here. Normal signature to call accessible class method or variable is (Class/Object).(method/variable). Then how do we give System.out.println()? Since System.out only gives the return type but does not belong to same class. Also in servlets, "this.getServletConfig().getInitParameter("defaultUser")" is not making sense to me, since getServletConfig() and getInitParameter are both member functions of same class, so signature becomes something like, class.method1().method2(), where method1 and method2 are member functions of same class. Can someone please explain..
Example:
Class CascMethodClassB()
{
public CascMethodClassA methodTest()
{
CascMethodClassA obj1 = new CascMethodClassA();
return obj1;
}
} /*Class CascMethodClassB ends*/
Class CascMethodClassA()
{
public int varTest;
public CascMethodClassA()
{
varTest = 7;
}
} /*Class CascMethodClassA ends*/
Class CascMethodClassC()
{
CascMethodClassB obj2 = new CascMethodClassB();
int varTestC = obj2.methodTest().varTest
public static void main(String[] args)
{
System.out.println("varTest in CascMethodClassA is: "+ varTestC);
} /*Class CascMethodClassC ends*/
}
Thankyou,
Fraggy.
Both are different cases.
In the first case, outis a public static member in the System class. The member out is of type PrintStream, so the call
System.out.println()
will call the method println() from the PrintStream object (out).
The second case, is something called method chaining. What happens is that class.method1() will return an object instance, according to Java docs it will return a ServetConfig object. So, you can again call a method from that returned object. Another way of seeing that call is (brackets are redundant, just there so you can visualize the order of the calls):
(ClassName.someMethod1()).someMethod2();
System.out is a public class variable of type PrintStream, not a
method. Therefore you can invoke the println method on it, which returns void.
this.getServletConfig().getInitParameter("defaultUser") makes
perfect sense once you understand chaining method invocations. In
this case, you are:
calling the present instance of Servlet
getting its instance field's value of type ServletConfig
getting whichever String value is returned by invoking the getInitParameter method on the ServletConfig object
Finally, a method's signature is made of the method's name and parameter types
Each non-void method returns a type, which may be a different type to the declaring class, so the chained method/field will have the methods of the returned type (not the class it's called from or the class that the first method is defined in).
For example, to break down System.out.printkln():
System.out // out is a public field of type PrintStream
.println() // println() is a method of PrintStream, not System
Guys I know this question is silly but just to make sure:
Having in my class method:
boolean equals(Document d)
{
//do something
}
I'm overloading this method nor overriding right? I know that this or similiar question will be on upcoming egzam and would be stupid to not get points for such a simple mistake;
Based on the code provided, we can't tell for sure whether you're overloading or overriding it.
You are most likely overloading the equals(Object o) method.
class A {
void method() {..}
}
class B extends A {
// this is overriding
void method() {..}
}
And
// this is overloading
class A {
void method(boolean b) {..}
void method(String arg) {..}
void method(int arg) {..}
}
P.S. you are using a bracket convention that is not widely accepted on the java world. In Java it is more common to place opening the curly bracket on the same.
You are not even overloading, since the other method is called equals. But if you add that s, you will be overloading equals. Although, to be precise, we talk about overloading if two (or more) methods with the same name but different signature are defined in the same class. In your case, it is trickier, since your equals with its different signature partly hides the original equals. Which is usually a bad thing, because this almost always leads to hard to understand behaviour, thus subtle bugs. Whenever someone calls equals on an instance of your class, depending on the parameter type the call may go to a different implementation of the method.
class Document {
public boolean equals(Document d)
{
//do something
}
}
Document doc1 = new Document();
Document doc2 = new Document();
String string = new String();
doc1.equals(doc2); // calls Document.equals
doc1.equals(string); // calls Object.equals!
You would be overriding Object.equals if you defined your method with the exact same signature as the original, i.e.
public boolean equals(Object obj) ...
In this case, both of the above calls to equals correctly execute Document.equals.
From the code you posted it could be either. If equal is defined in a superclass with the same parameter declarations then you are overriding it. If there is already a method called equal, but with different parameter types, you are overloading it.
On a related note, if you are using Java 5 and above and your intent is to override then it is highly recommended to use the #Override annotation before the method definition to indicate your intention. The wrong usage of this annotation (i.e. when you want to override and are not doing so) would flag a compile error.
As of Java 6 you can use the #Override annotation while defining methods that are
declared in an interface the class in implementing.
Overloading: same method name, same parameter list, different classes
Overriding: same method name, different parameter list, same or different classes.
Class A {
bool Equals(Document d) {...}
bool Equals(A a) {...} // overloaded method
}
Class B extends A {
bool Equals(Document d) {...} // overridden method
bool Equals(B b) {...} // overloaded method
}
One thing to note, the return type does not matter, it's the name of the method and the parameter list that make all the difference.