Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why the cast is necessary in this case?

Tags:

java

class MyClass {

   private String str;
   public MyClass(String str){
      this.str = str;
   }
   public int compare(Object o) {
      return str.compareTo(((MyClass)o).str); //line No.8
   }
}

class Client {
   public static void main(String[] args) {
      MyClass m = new MyClass("abc");
      MyClass n = new MyClass("bcd");
      System.out.println(m.compare(n));
   }
}

Why in this snippet of code the cast (MyClass)o in line number 8 is necessary, despite the fact that the Client invokes a compare method with arguments which are instances of MyClass class?

When I modify the compare method in MyClass class to form like below:

   public int compare(Object o) {
      System.out.println(o.getClass());
      System.out.println(((MyClass)o).getClass());
      return str.compareTo(((MyClass)o).str);
   }

Then, the Client will produce the following result:

class MyClass
class MyClass

Thus I don't understand why the cast above is required and why I can't just do like that (without cast to MyClass):

   public int compare(Object o) {
      return str.compareTo(o.str); 
   }

Because when I do that, I get the compile time error:

str cannot be resolved or is not a field
like image 539
urajah Avatar asked Aug 31 '15 21:08

urajah


2 Answers

This comes down to what the compiler knows at compile time. At compile time it knows that what is going to be passed into this method is of type Object. That means that it can guarantee the methods that are associated with the class Object, but not the methods of type MyClass.

Because that compare method takes any argument of type Object, or a subclass, you could pass anything in. What if I make a class MyOtherClass like this..

public class MyOtherClass {
    public String notStr;
}

And I do something like..

MyOtherClass myOtherClass = new MyOtherClass();
MyClass myClass = new MyClass();

myClass.compare(myOtherClass);

Without the cast, you've now got a situation where at runtime, it attempts to access a field that is not there. The cast is put in place to guarantee that the object is of the correct type, or it will fail before it attempts to access that field.

Just as an Aside

I've been working extensively with a language called Groovy. It is a language that essentially sits on top of Java, but it supports things like dynamic binding and loose typing (which is what you're after here). If this kind of functionality is a must have for you, then I would recommend checking out the documentation.

like image 63
christopher Avatar answered Nov 02 '22 15:11

christopher


o's type in compare is an Object. This means the parameter it could be a MyClass instance, but it also could not. Object doesn't have any field called str (as that one belongs to MyClass), so there's no way to get that field from it, and so the code can't compile. If you cast to MyClass, however, it will have a field called str, and so it will be able to access it.

like image 22
eric.m Avatar answered Nov 02 '22 13:11

eric.m