【问题标题】:How can the following line of code can create an object without the new operator?下面这行代码如何在没有 new 操作符的情况下创建对象?
【发布时间】:2017-01-25 21:32:39
【问题描述】:

我了解到,new 是创建对象所必需的。那么,这行代码(来自 java swing)是如何工作的?

GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();

【问题讨论】:

  • 它正在调用一个方法。该方法中的某些内容知道如何检索或创建GraphicsEnvironment 对象并将其返回给您。该方法负责对象的制作方式;你不是在创造它。
  • 你不是在创建一个对象;那个函数是。
  • 所以GraphicsEnvironment类必须有一个'static'修饰符,因为只有静态类的方法可以直接使用类名来调用。
  • @trotsky 不行,只能使用类名直接调用静态方法
  • 这是一个名为“工厂模式”的设计模式示例

标签: java swing


【解决方案1】:

这是因为getLocalGraphicsEnvironment 方法的static 实现返回GraphicsEnvironment 类型。来自class itself, definition as -

/**
 * Returns the local <code>GraphicsEnvironment</code>.
 * @return the local <code>GraphicsEnvironment</code>
 */
public static synchronized GraphicsEnvironment getLocalGraphicsEnvironment() {
    if (localEnv == null) {
        localEnv = createGE();
    }

    return localEnv;
}

localEnv 被声明为 -

private static GraphicsEnvironment localEnv;

【讨论】:

  • 但是 that 是如何创建对象的呢? ;)
  • 是的..确切地说..创建对象的方法必须相同的代码,对吧?
  • createGE() 是这样做的。长话短说,仅仅因为你没有看到 new 运算符并不意味着它没有在方法调用链的某个地方被调用。虽然在这种情况下,不会直接调用 new,因为对象是使用反射创建的
【解决方案2】:

这是来自createGE()的代码:

private static GraphicsEnvironment createGE() {
    GraphicsEnvironment ge;
    String nm = AccessController.doPrivileged(new GetPropertyAction("java.awt.graphicsenv", null));
    try {
        // long t0 = System.currentTimeMillis();
        Class<GraphicsEnvironment> geCls;
        try {
            // First we try if the bootclassloader finds the requested
            // class. This way we can avoid to run in a privileged block.
            geCls = (Class<GraphicsEnvironment>)Class.forName(nm);
        } catch (ClassNotFoundException ex) {
            // If the bootclassloader fails, we try again with the
            // application classloader.
            ClassLoader cl = ClassLoader.getSystemClassLoader();
            geCls = (Class<GraphicsEnvironment>)Class.forName(nm, true, cl);
        }
        ge = geCls.newInstance();
        // long t1 = System.currentTimeMillis();
        // System.out.println("GE creation took " + (t1-t0)+ "ms.");
        if (isHeadless()) {
            ge = new HeadlessGraphicsEnvironment(ge);
        }
    } catch (ClassNotFoundException e) {
        throw new Error("Could not find class: "+nm);
    } catch (InstantiationException e) {
        throw new Error("Could not instantiate Graphics Environment: "
                        + nm);
    } catch (IllegalAccessException e) {
        throw new Error ("Could not access Graphics Environment: "
                         + nm);
    }
    return ge;
}

虽然它实际上从未直接调用 new 来创建对象,但它确实使用反射为您创建了 GraphicsEnvironment。在这种情况下,对 newInstance() 的调用会创建一个您正在使用的类的新实例,除非您正在运行 Headless;此时直接使用new 关键字创建。

【讨论】:

    猜你喜欢
    • 2011-07-07
    • 2011-11-08
    • 2021-09-16
    • 2014-10-02
    • 1970-01-01
    • 1970-01-01
    • 2016-07-03
    • 1970-01-01
    • 2013-08-08
    相关资源
    最近更新 更多