【问题标题】:How to get class object without an instance or class name如何获取没有实例或类名的类对象
【发布时间】:2023-03-23 00:35:01
【问题描述】:

我有一个抽象类MyClass,它带有一个静态方法,可以用许多MyClassDescendant 对象填充给定集合。此方法应调用MyClassDescendant 的静态getRandom() 方法来获取对象实例。

我当前的代码如下所示:

public static void populate(Collection<MyClass> coll, Class<? extends MyClass> cl, int num) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
    for (int i = 0; i < num; i++) {
        Method m;
        m = cl.getMethod("getRandom");
        coll.add((MyClass)(m.invoke(null)));
    }
}

那我这样称呼它:

MyClass.populate((Collection<MyClass>)(Collection<?>)collection, MyClassDescendant.class, 3);

此代码有效,但很难看。我真正想要达到的效果是这样的:

MyClassDescendant.populate(collection, 3);

如果不是静态方法,我会使用this.getClass()。我知道MyClass.class 适用于静态方法,但我不希望class 适用于MyClass,而是适用于特定的MyClassDescendant(后代类型很少)。

有没有办法在没有实例或类名的情况下获取类对象?

【问题讨论】:

  • 由于基类中的方法populate()是静态的,所以在派生类中不能被覆盖。相反,您可以在每个派生类中实现它,以使用该类的实例填充集合。
  • 是的,可以,但我想避免在多个类中复制粘贴几乎相同的代码。
  • 你总是在静态上下文中调用它吗?
  • 你不能覆盖静态方法,你只能隐藏它们......如果你真的想覆盖它们,你需要让它成为非静态的
  • 您要么必须复制代码,要么必须将类提供给方法,因为集合没有任何关于其项目类型的信息,因为泛型是通过类型擦除实现的Java。

标签: java class static


【解决方案1】:

由于您处于静态上下文中,因此您必须复制一些代码,但您可以进行委托。

public class MyClassDescendant extends MyClass {
    public static void populate(Collection<MyClass> coll, int count) {
        MyClass.populate(coll, MyClassDescendant.class, count);
    }
}

现在你可以打电话了 MyClassDescendant.populate(collection, 3);

【讨论】:

    【解决方案2】:

    尝试以这种方式重构您的方法:

    public static <T extends Base> void populate(Collection<T> coll, int num) throws Exception{
        for (T item : coll) {
            Method m;
            m = item.getClass().getMethod("getRandom");
            coll.add((T)(m.invoke(null)));
        }
    }
    

    对于 cmets 之一,您还可以使用 template method 设计模式通过将 getRandom() 方法抽象化并在您的填充方法中调用它来利用继承。

    【讨论】:

    • 您将遇到并发修改异常,因为您正在修改当前正在迭代的集合。此外,如果集合为空,则永远不会调用 getRandom。
    • @LeonardBrünings 这完全取决于传入的是哪种Collection。您的第二条评论是正确的,似乎这是预期的功能。
    • 如果我明白你在那里做了什么,这个方法将遍历集合中的每个元素并创建其类的一个新的随机实例。这不是我想做的。该集合应包含 多种 类型的 MyClass 后代,populate() 应添加 a number 个特定类的实例。
    • @gronostaj 感谢您澄清您对这种方法的期望。
    【解决方案3】:

    如果 get random 是一个静态方法,你不能直接调用它吗?

    public interface MyClassInterface { 
        MyClass getRandom();
    }
    
    public abstract class MyClass implements MyClassInterface {
        public static void populate(Collection<MyClass> coll, int num) {
            for (int i = 0; i < num; i++) {            
                coll.add((MyClass)MyClassDescendant.getRandom());
            }
        }
    }
    
    public class MyClassDescendant extends MyClass {
        public MyClass getRandom() {
            // implementation of getRandom
        }
    }
    

    【讨论】:

    • MyClassDescendant 不是唯一的后代,它们的类型很少。 MyClass 中的静态抽象方法 getRandom() 可以解决问题(我认为),但 Java 不允许使用静态抽象方法。
    • 如果想要多个孩子,每个孩子都有一个 getRandom 方法,你应该创建一个接口并让 MyClass 实现它。
    猜你喜欢
    • 2011-02-05
    • 1970-01-01
    • 2010-11-27
    • 1970-01-01
    • 2023-03-14
    • 2020-06-28
    • 2014-01-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多