Reputation: 1623
I am a Java newbie and recently I got into some thinking on the following Android
sample code:
TextView txt = (TextView) findViewById(R.id.activity_display_message);
TextView
is a child of View
class. And findViewById
returns a View
object.
I wanted to understand how and why we need to explicitly cast the returned View
to TextView
when the returned object MUST be actually a TextView
, otherwise the casting will throw a cast exception.
So, this is my attempt to simulate what is going on behind the scenes with this mockup code:
class View{}
class TextView extends View{}
public class A{
// simple hard coded check of the ID
public static View findViewById(int id){
if (id == 1){
return new View();
}
else{
return new TextView();
//return ((View)new TextView()); // This also works
}
}
public static void main(String[] args){
TextView txt = (TextView)findViewById(2); // Works fine
//TextView txt2 = findViewById(2); INCOMPATIBLE TYPES ERROR because the returned type is View
View v = findViewById(2); // Works fine
View view = new View();
//TextView test = (TextView) view; // cast error
View view2 = new TextView();
TextView test2 = (TextView) view2; // Works OK
}
}
Conclusion:
It turns out that findViewById
actually casts to View
any returned element. I guess it is because the defined return value of the method is View
and Java automatically casts the result to View
.
Please tell me if I am getting it right.
Upvotes: 3
Views: 107
Reputation: 81
Even though the method returns a View
, since TextView
is a subclass of View
it can be safely returned by the method.
Take for example the following legal assignment:
View view = new TextView(); // Legal, no compiler errors. TextView is a subclass of View, so it can be safely 'downgraded'
And the following illegal assignment:
TextView textView = new View(); // Illegal, compatibility error
It's the exact same way with returning, the TextView
is downgraded to a View
. As for your question on whether or not you can figure out if it is a TextView
that is being returned, you can make use of the instanceof
operator.
Upvotes: 0
Reputation: 3709
Reason for exception in case 1 is bcz your View class is not aware of any subclass called TextView... where as in case 2 TextView is aware that it belongs to the family of View class.
upcast – Casting a subtype object into a supertype and this is called upcast. In Java, we need not add an explicit cast and you can assign the object directly. Compiler will understand and cast the value to supertype. By doing this, we are lifting an object to a generic level. If we prefer, we can add an explicit cast and no issues.
downcast – Casting a supertype to a subtype is called downcast. This is the mostly done cast. By doing this we are telling the compiler that the value stored in the base object is of a super type. Then we are asking the runtime to assign the value. Because of downcast we get access to methods of the subtype on that object.
ClassCastExcpetion – We get ClassCastException in a downcast. In principle, we guarantee the compiler that the instance value of is subtype and ask it to cast. But during runtime, because of unforeseen circumstances, the value is not of expected subtype. In such cases, we get ClassCastException.
Upvotes: 1
Reputation: 3757
As you describe in the question, findViewById(R.id.activity_display_message);
returns a View
Object, in this case, you the programmer know that this particular View
is actually a TextView
Object, but findViewById
only promises to return a View
, or an instance of any class that descends from View
, as any class that descends from View
is still a View
, it just might have more specific details available.
All that findViewById
is guaranteed to return is something that is or extends View
. If you want to treat the returned object as though it is a specific subclass of View
, you need to cast the object returned by findViewById
to that subclass.
From your example,
View view = new View(); // This is a View, it is NOT a TextView
View textView = new TextView(); // TextView is a View, but it also has TextView stuff going on...
//TextView test = (TextView) view; // cast error
Upvotes: 1