【问题标题】:Instantiate new object from Class of parameter从参数类实例化新对象
【发布时间】:2021-04-13 14:55:55
【问题描述】:

我正在构建一个包含多个按顺序创建的 JFrame 的游戏。对于其中两个框架(大厅和实际游戏框架),我将 F11 等用户输入用于全屏模式。要进入或离开这个全屏模式,我显然必须处理当前帧并创建一个新帧,因为 setUndecorated() 的设置只能在使帧可见之前设置。

由于 JFrame 中的其他 UI 元素会成为焦点,因此我必须使用键绑定。因此,我开设了一个进入或离开全屏模式的课程。为了阐明是否应该全屏创建 JFrame,我传递了一个 int windowState 作为参数。由于应该可以实例化两个不同的屏幕,因此我不能简单地调用类本身,而是需要查看传递给 Action 事件的帧。

这是我目前尝试做的:

public class EnterFullscreen extends AbstractAction{

    private static final long serialVersionUID = 1773898497666165938L;
    
    private JFrame frame;
    private Class<?> frameType;
    private Constructor<?> c;
    
    public EnterFullscreen(JFrame frame) {
        
        this.frame = frame;
        
        try {
            frameType = frame.getClass();
            c = frameType.getConstructor(String.class);
        } catch (NoSuchMethodException | SecurityException e) {
            e.printStackTrace();
        }
        
    }
    
    @Override
    public void actionPerformed(ActionEvent e) {
        
        try {
            
            frame.setVisible(false);
            if (frame.isUndecorated()) {
                c.newInstance(0);
            } else {
                c.newInstance(1);
            }

            frame.dispose();
            
        } catch (InstantiationException | IllegalAccessException | IllegalArgumentException
                | InvocationTargetException e1) {
            e1.printStackTrace();
        }
        
    }
    
}

错误信息:

java.lang.NoSuchMethodException: de.munchkin.frontend.Lobby.<init>(java.lang.String)
    at java.lang.Class.getConstructor0(Class.java:3082)
    at java.lang.Class.getConstructor(Class.java:1825)
    at de.munchkin.keybindings.EnterFullscreen.<init>(EnterFullscreen.java:24)
    at de.munchkin.frontend.Lobby.<init>(Lobby.java:45)
    at de.munchkin.frontend.MatchCreation.lambda$1(MatchCreation.java:169)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
    at java.awt.Component.processMouseEvent(Component.java:6539)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
    at java.awt.Component.processEvent(Component.java:6304)
    at java.awt.Container.processEvent(Container.java:2239)
    at java.awt.Component.dispatchEventImpl(Component.java:4889)
    at java.awt.Container.dispatchEventImpl(Container.java:2297)
    at java.awt.Component.dispatchEvent(Component.java:4711)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4904)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4535)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4476)
    at java.awt.Container.dispatchEventImpl(Container.java:2283)
    at java.awt.Window.dispatchEventImpl(Window.java:2746)
    at java.awt.Component.dispatchEvent(Component.java:4711)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:760)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:84)
    at java.awt.EventQueue$4.run(EventQueue.java:733)
    at java.awt.EventQueue$4.run(EventQueue.java:731)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:730)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at de.munchkin.keybindings.EnterFullscreen.actionPerformed(EnterFullscreen.java:40)
    at javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1668)
    at javax.swing.JComponent.processKeyBinding(JComponent.java:2882)
    at javax.swing.JComponent.processKeyBindings(JComponent.java:2943)
    at javax.swing.JComponent.processKeyEvent(JComponent.java:2845)
    at java.awt.Component.processEvent(Component.java:6316)
    at java.awt.Container.processEvent(Container.java:2239)
    at java.awt.Component.dispatchEventImpl(Component.java:4889)
    at java.awt.Container.dispatchEventImpl(Container.java:2297)
    at java.awt.Component.dispatchEvent(Component.java:4711)
    at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1954)
    at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:835)
    at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:1103)
    at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:974)
    at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:800)
    at java.awt.Component.dispatchEventImpl(Component.java:4760)
    at java.awt.Container.dispatchEventImpl(Container.java:2297)
    at java.awt.Window.dispatchEventImpl(Window.java:2746)
    at java.awt.Component.dispatchEvent(Component.java:4711)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:760)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:84)
    at java.awt.EventQueue$4.run(EventQueue.java:733)
    at java.awt.EventQueue$4.run(EventQueue.java:731)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:730)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

问题是我收到此错误但找不到问题所在,因为我认为我正在做有关此主题的大多数其他 SO 文章所描述的内容: Article 1 Article 2 等等

这些文章中描述的是我需要获取构造函数并在其上调用newInstance(),如果我没有记错的话,我就是这样做的。

那么,我需要做些什么不同的事情才能让它发挥作用?我并没有真正看到与上面链接的其他 SO 帖子中提出的解决方案有任何区别。

【问题讨论】:

  • 1) 你是否在某个地方扩展了 JFrame 类? getClass() 返回对象的运行时类型(动态类型);如果您只是使用普通的 JFrame,那么 getClass() 将只返回类型 JFrame。 2) getConstructor(String.class) 尝试检索接受 String 作为参数的构造函数。然而,当您稍后使用它时,您会传递一个整数(0 或 1)。 3)我对你的目标有点困惑,但反思可能是不必要的;可能有简单的设计模式和语言机制可以实现您想要的结果(例如工厂、多态等)
  • 我能够通过在类上调用getConstructors() 并使用返回数组中的第一个值来使其工作 - 但是数组中也只存储了一个构造函数。我也不会将此作为问题的最终答案,因为这仍然不能回答我将如何通过调用 getConstructor() 来做到这一点。
  • @Nerdizzle 我的大厅和游戏框架都扩展了 JFrame。这两个类的构造函数都采用原始 int 而不是 Integer,因此这可能是我无法获得正确构造函数的原因,因为我已经尝试将 String.class 替换为 Integer.class 但结果在同一个错误中。我之所以使用反射来做这件事,是因为这是我想到的第一件事。我不确定如何以不同的方式解决这个问题。
  • 好吧,您可以只使用类似于传统clone() 范例但默认构造克隆的多态函数。这将需要一个介于JFrame 和类层次结构中的游戏/大厅框架之间的类,您将在其中抽象地定义此函数。毕竟,您是在尝试基于对象的动态类型来实现行为;这就是多态性的全部意义所在。

标签: java class generics instance instantiation


【解决方案1】:

堆栈跟踪表明您的类Lobby 没有一个带有String 类型参数的构造函数。

根据您的用法,例如c.newInstance(0),我假设您的构造函数采用 int/Integer。 所以,你应该写:

    c = frameType.getConstructor(Integer.class);

【讨论】:

  • 这有效,但只是部分有效,即我需要将参数从原始类型 int 更改为 Integer,否则无法找到采用 Integer 类参数的构造函数。但是在使用原语时是否有可能接受使用包装器来获取正确的构造函数?
  • 如果你在构造函数中使用原始 int,它应该是:frameType.getConstructor(int.class);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多