David David - 4 months ago 16
Android Question

Determine required object type from uninitialized object

I would like my code to help determine what object type is required automatically.


The code to attach a widget is often as follows:

TextView textView = (TextView) findViewById(R.id.textView);

I want to then check that textView has been found correctly in order to avoid bugs. To do this, I'm using a custom (AttachWidgetException) exception:

if(textView == null) throw new AttachWidgetException(name);


Rather than having to repeat these two lines for every widget in my code (DRY), I decided to make a function to simplify it. I incorrectly assumed I could do this:

public View attachWidget(View view, int resID, String name) throws AttachWidgetException {
view = (view.getClass) findViewById(resID);

if(view == null) throw new AttachWidgetException(name);
return view;

Called from within a Try block by:

TextView textView = attachWidget(textView, R.id.textView, "textView");


But, this doesn't work for two reasons. The caller's object is expecting a TextView not a View. I think the other reason is view is yet to be instantiated and therefore is reported as:

java.lang.Class <capture<? extends android.view.View>

… which is not an extension of View. To fix this, I need to change the line in attachWidget to:

view = findViewById(resID);

...and the calling line to:

TextView textView = (TextView) attachWidget(textView, R.id.textView, "textView");

… which makes the View input parameter useless. We can remove that at this point.


This really isn't too bad, but is there a way to do this so I don't need to manually add the cast? Can attachWidget automatically determine that it needs to return a TextView? I'm pretty sure I'm heading in the wrong direction of any possible solutions. Would generics help me in any way here?

Please forgive me if I am using incorrect terminology in my description. I would appreciate any code / terminology / methodology corrections.


You can't call view.getClass when view is null. Try doing this:

public <T extends View> T attachWidget(Class<T> type, int resID, String name) throws AttachWidgetException {
        View view = findViewById(resID);
        if (view == null) throw new AttachWidgetException(name);
    try {
        return type.cast(view);  
    } catch (ClassCastException) {
        throw new AttachWidgetException(name);

In this case, you can call like:

TextView textView = attachWidget(TextView.class, R.id.textView, "textView");