4

This version of View.findViewById() returns the most specific concrete subtype of View:

protected <T extends View> T findViewById(@IdRes int id) {
    return (T) getRootView().findViewById(id);
}

How does it work? Specifically, how can the type be inferred at compile-time when the id is looked up at runtime? Does it have to do with the annotation?

This differs from questions with similar titles, which are about the use of findViewById():

I would like to know why it works.

Community
  • 1
  • 1
Ellen Spertus
  • 6,576
  • 9
  • 50
  • 101
  • `findViewById()` returns a View Object. That Object is then cast to whatever T is determined to be. Is that what you mean? – TheWanderer Feb 26 '19 at 21:35

1 Answers1

4

It can't be inferred. It uses a cast - return (T). The caller is responsible for ensuring that the type T matches the type of view being located. If they get this wrong, the operation will fail with a ClassCastException.

The type can be either explicitly specified, i.e.

this.<TextView>findViewById(R.id.someTextView)

(excuse my syntax if I've got this wrong - I mostly deal in Kotlin now)

or it can be inferred from the destination:

TextView foundView = findViewById(R.id.someTextView)

but in either case, the responsibility lies with the caller.

The Android toolchain may do further work to cross-reference layout XML with the code, and produce warnings or failures within your IDE, but this is a compile-time layer on top of what Java performs at runtime.

It has nothing to do with the @IdRes annotation, which is there to assert - again at compile time - that the id parameter is a reference to the ID of some XML-based entity, and not simply any integer value.

Rob Pridham
  • 4,780
  • 1
  • 26
  • 38