2

我有与 Java 相关的问题:

我想知道有没有办法通过使用变量来创建类(在程序中)的路径。我正在制作一个程序,该程序将从某些站点下载图片并将其展示给用户。但是,不同的站点有不同的形式,这就是为什么我必须为每个站点定义一系列特定的功能。它们不能放在同一个类中,因为执行相同工作(仅针对另一个站点)的函数必须具有相同的名称。我正在尝试尽可能简单地稍后添加对另一个站点的支持。

无论如何,问题是,我可以在程序中调用一个函数,使用一个变量来确定它的位置。

例如:code.picturesite.functionINeed();

code是包含所有编码的包,picturesite不是一个类,而是一个包含所需类名称的变量 - 这样我只能更改变量的值以调用不同的函数(或不同类中的相同函数)。

我真的不认为这是可能的(这更能让您了解问题的本质),但是还有另一种方法可以做我想要在这里实现的目标吗?

4

3 回答 3

2

是的,有办法。这叫做反射

给定一个包含类名的字符串,您可以获得这样的实例:

Class<?> c = Class.forName("com.foo.SomeClass");
Object o = c.newInstance(); // assuming there's a default constructor

如果没有默认构造函数,您可以通过c.getConstructor(param1.getClass(), param2.getClass(), etc)

给定一个包含方法名称和实例的字符串,您可以像这样调用该方法:

Method m = o.getClass().getMethod("someMethod", param1.getClass(), param2.getClass(), etc);
Object result = m.invoke(o, param1, param2, etc);
于 2012-06-01T12:54:50.733 回答
2

我没有立即在您的问题中看到任何无法解决的问题,而不是拥有一个包含类名的变量,而是拥有一个包含该类实例的变量——要在类上调用一个函数,您将拥有要知道它实现了该功能,因此您可以将该功能放在接口中。

interface SiteThatCanFoo {
    void foo();
}

class SiteA extends Site implements SiteThatCanFoo {
    public void foo() {
        System.out.println("Foo");
    }
}

然后:

Site currentSite = getCurrentSite(); // or getSiteObjectForName(siteName), or similar
if (SiteThatCanFoo.isAssignableFrom(currentSite.class)) {
    ((SiteThatCanFoo)currentSite).foo();
}
于 2012-06-01T13:15:09.203 回答
1

所以你想做这样的事情(检查ImageDownloader.getImageFrom方法)

class SiteADownloader {
    public static Image getImage(URI uri) {
        System.out.println("invoking SiteADownloader on "+uri);
        Image i = null;
        // logic for dowlnoading image from siteA
        return i;
    }
}

class SiteBDownloader {
    public static Image getImage(URI uri) {
        System.out.println("invoking SiteBDownloader on "+uri);
        Image i = null;
        // logic for dowlnoading image from siteB
        return i;
    }
}

// MAIN CLASS
class ImageDownloader {
    public static Image getImageFrom(String serverName, URI uri) {
        Image i = null;
        try {
            // load class
            Class<?> c = Class.forName(serverName + "Downloader");
            // find method to dowload img
            Method m = c.getDeclaredMethod("getImage", URI.class);
            // invoke method and store result (method should be invoked on
            // object, in case of static methods they are invoked on class
            // object stored earlier in c reference
            i = (Image) m.invoke(c, uri);
        } catch (NoSuchMethodException | SecurityException
                | IllegalAccessException | IllegalArgumentException
                | InvocationTargetException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        return i;
    }

    // time for test
    public static void main(String[] args) {
        try {
            Image img = ImageDownloader.getImageFrom("SiteB", new URI(
                    "adress"));
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }
}
于 2012-06-01T13:42:21.443 回答