【问题标题】:Making a new specific object from a class generic从类泛型创建新的特定对象
【发布时间】:2013-07-02 16:01:02
【问题描述】:

好的,所以我环顾四周,我想我可能会解决这个问题。我在大学选修过 C++ 课程,我喜欢修补,但我仍在学习 Java。

所以我使用 ListAdapter 来放置用户可以从中选择的不同片段的列表,然后他们选择的片段位于 ListAdapter 所在的位置。它只需要数组,没什么大不了的。

/**
 * An array of POJOs used to hold the info about the fragments we'll be
 * swapping between This should be inserted into an array adapter of some
 * sort before being passed onto ListAdapter
 */
private static final FragmentDetails[] FRAGMENT_DETAILS = {
        new FragmentDetails(R.string.action_extraInfo,
                R.string.extraInfo_description,
                ExtraInfoFragment.class),
        new FragmentDetails(R.string.action_largeTach,
                R.string.largeTach_description, 
                LargeTachFragment.class),
                ...
            };
/**
 * @author PyleC1
 * 
 *         A POJO that holds a class object and its resource info
 */
public static class FragmentDetails {
    private final Class<? extends Fragment> fragmentClass;
    private int titleId;
    private int descriptionId;
/**
     * @param titleId
     *            The resource ID of the string for the title
     * @param descriptionId
     *            The resource ID of the string for the description
     * @param fragmentClass
     *            The fragment's class associated with this list position
     */
    FragmentDetails(int titleId, int descriptionId,
            Class<? extends Fragment> fragmentClass) {
            super();
        this.titleId = titleId;
        this.descriptionId = descriptionId;
        this.fragmentClass = fragmentClass;
    }

    ...
}

无论如何,我通过一个名为 CustomArrayAdapter 的简单 get/set 类来运行它,并在附加片段时将其发送到 ListAdapter。

public void onAttach(Activity activity) {
    super.onAttach(activity);

    ListAdapter listAdapter = new CustomArrayAdapter(getActivity(),
        FRAGMENT_DETAILS);
    setListAdapter(listAdapter);

}

到目前为止一切顺利。当我尝试对 onListItemClick 侦听器进行编程时,问题就出现了。我似乎找不到从类信息中创建真实对象的方法。我环顾四周,发现 .getClass().newInstance() 函数应该与 new 大致相似,所以我尝试了这个。

public void onListItemClick(ListView l, View v, int position, long id) {
    FragmentDetails details = (FragmentDetails) getListAdapter().getItem(position);

        FragmentManager fragmentManager = ...
        FragmentTransaction fragmentTransaction = ...

        fragmentTransaction.add(R.id.fragment_container, 
                                details.fragmentClass.newInstance());
}

这样做会在编译器中引发非法访问异常。我知道类似的东西在 C++ 中是可以接受的。也许是一个类指针?但这可能是 Java 中完全错误的方式。也许不是类型安全的?

我唯一的另一个想法是删除

Class<? extends Fragment> fragmentClass

来自数组的泛型并仅使用 switch 语句(可能来自标题 id)来硬编码片段事务,尽管这似乎有点不雅。如果你想启动新的活动,它工作得很好,你可以像这样将泛型类传递给意图:

Class<? extends Foo> bar = someFooClass.getClass();
new Intent(this, bar);

但是片段不接受这个。

【问题讨论】:

    标签: java android class generics


    【解决方案1】:

    根据documentation

    IllegalAccessException - if the class or its nullary constructor is not accessible.
    

    因此,如果您想使用反射实例化您的片段,所有可能的类&lt;? extends Fragment&gt; 都需要提供public 无参数构造函数。

    【讨论】:

    • 非常感谢。我似乎找不到答案,我知道这很简单。我还必须添加一个 try catch 块并对对象进行类型转换。 Object foo; try { foo = details.fragmentClass.newInstance(); } catch ... 然后我可以打电话:fragmentTransaction.add(R.id.fragment_container, (Fragment)foo); 没有问题
    • 由于newInstance() 是通用的,如果您的fragmentClass 仍然使用&lt;? extends Fragment&gt; 参数化,则应该可以将details.fragmentClass.newInstance(); 直接分配给Fragment 类型的变量。
    • 就在检查这个,就像你说的那样。我真正的工作阻碍了一段时间。哈哈。感谢所有的帮助。我接受了你的回答,希望我不需要做任何其他事情。我为那个 oracle 页面添加了书签。官方的 java 文档应该是一个很好的资源。希望我早点知道他们。 eclipse 中的文档非常糟糕,假设您非常了解 java,而 android 文档也没有更好。
    猜你喜欢
    • 1970-01-01
    • 2014-04-04
    • 2013-06-27
    • 1970-01-01
    • 2021-09-29
    • 2021-10-10
    • 1970-01-01
    • 1970-01-01
    • 2021-05-26
    相关资源
    最近更新 更多