Java:抽象类中的静态方法调用抽象非静态方法?

时间:2012-12-15 16:13:24

标签: java methods static instance

我有一个抽象类A

我有大约10个扩展A

的类

A类有一个或两个静态方法,它们是静态的,因为它们属于10个类,而不是它们的实例。一种静态方法例如被称为getAllFromX,它从X获取该类的所有实例,无论它是什么,它可能是一个服务器,实际上它是,但它并不重要。所以你看,这些方法是静态的,并没有绑定到实例。

同时,类A具有非静态抽象方法,每个子类都会覆盖此方法(只返回一个字符串)。我不能使它静态,因为静态方法不能被覆盖(...)。

总结:抽象类A有一个静态方法和一个抽象的非静态方法,它被子类覆盖。我不能使第二个方法静态,因为它必须被覆盖。另一方面,我可以使第一个方法非静态,但它会非常难看和糟糕的编程风格,所以我会这样离开。

捕获?类A中的静态方法必须获取非静态方法返回的值(当然,对于继承静态方法的子类)。

使用反射来完成这项工作的“最简单”方法是什么?我的意思是......真的吗?

例如,我得到静态方法所在的类:

Class<?> cl=new Object(){}.getClass().getEnclosingClass(); (a hack I found here, thank god...)
然后我使用getConstructor来构造这个子类的对象。

然后我使用这个对象来调用非静态方法。

真的?难道不容易吗?我的意思是,如果我想设计我的程序在概念上正确...

来自C#我不喜欢(和类型擦除的东西)。这只是丑陋的。可行,但丑陋。这是一个很大的绊脚石,至少对初学者来说是这样。编辑:再次阅读后,我会添加:/ rant end。对不起,但我真的很在乎。

3 个答案:

答案 0 :(得分:1)

我认为您实际需要的是以下内容:

public class A {
    public static Set<A> getAllFromX() {
        ...
    }
}

public class B extends A {
    public static Set<B> getAllFromX() {
        ...
    }
}


public class C extends A {
    public static Set<C> getAllFromX() {
        ...
    }
}

(就像枚举中的valueOf()values()方法一样,在每个枚举子类中重新定义,因为静态方法不能被继承)

在这种情况下,每个类都有自己的静态方法,无论它想做什么。但是你的问题没有多大意义,因为它说:

  

A类中的静态方法必须获取非静态方法返回的值(当然,对于继承静态方法的子类)。

实际上,静态方法是子类继承的 。静态方法永远不会被继承。如果在A中定义静态方法foo(),并调用

B.foo();

编译器不会拒绝编译它,但会将其转换为

A.foo();

所以,在foo()中没有办法取决于调用foo()的类,因为它总是A。

答案 1 :(得分:0)

您始终可以使用反射来调用使用类名称的方法,例如

    Object objectX = ClassX.class.newInstance();
    //get your method passing argument types as second param
    Method method = ClassX.class.getDeclaredMethod("methodX", null);
    //invoke your method passing arguments as second param
    method.invoke(objectX, null);

既然你提到你的静态方法不使用任何实例,但你使用反射来获取实例,因此我真的不确定,它是如何适合你的要求的。

我认为在抽象类中将它作为一个实现的方法(非静态)是一个更好的选择。这样你实现它一次但它在所有10个扩展类中都可用。< / p>

答案 2 :(得分:0)

我认为您的问题是较大的设计之一。另一个对象应该负责检索A或其子类的实例。如您所见,依赖静态方法替换为子类不能很好地工作。在不了解问题领域的情况下,很难给出一个好的答案,但我会考虑类似于抽象工厂模式的东西。

从广义上讲:使用方法Collection getInstances()定义一个抽象类AFactory。为每个需要返回的具体子类扩展AFactory,并在适当的重写的getInstances()方法中实现该逻辑。您还可以在抽象AFactory getFactory(Class)上提供静态方法,以便在运行时获取相应的工厂子类型。