0

我正在尝试使用 Nullness Checker 来构建 JPanel 的子类。

class MyView<R extends @NonNull Object> extends JPanel {
  // ...
  // constructor calls this method:
  @RequiresNonNull({"labelPanel", "fieldPanel", "checkBoxPanel"})
  private void makeTopPanel(@UnderInitialization MyView<R> this) {
    JPanel topPanel = new JPanel(new BorderLayout());
    topPanel.add(labelPanel, BorderLayout.LINE_START);
    topPanel.add(fieldPanel, BorderLayout.CENTER);
    topPanel.add(checkBoxPanel, BorderLayout.LINE_END);

    // Error here: [method.invocation.invalid] call to add(java.awt.Component,java.lang.Object)
    // not allowed on the given receiver.
    add(topPanel, BorderLayout.PAGE_START);
    setBorder(new MatteBorder(1, 0, 0, 0, Color.black));
  }
}

错误消息说:

error: [method.invocation.invalid] call to add(java.awt.Component,java.lang.Object) not allowed 
on the given receiver.
  found   : @UnderInitialization @NonNull Container
  required: @Initialized @NonNull Container

问题似乎是 add 方法假定this已初始化。但是在构造函数中调用 Container 的 add 方法是非常安全的。所以为了防止这个错误,我想创建一个带有带注释的隐式参数的存根文件:

package java.awt;
public class Container extends Component {
  public void add(@UnknownInitialization Container, @NonNull Component, @NonNull Object);
}

它似乎没有将add()这里的方法识别为java.awt.Container.add(Component, Object)方法。

这是完整的存根文件:

import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.initialization.qual.UnknownInitialization;
import javax.swing.border.Border;
import java.awt.Component;
import java.awt.Container;

package javax.swing;

public class Timer {
  public Timer(int delay, @Nullable ActionListener listener);
}

public class JOptionPane {
  public static void showMessageDialog(@Nullable Component parentComponent,
          Object message, String title, int messageType)
          throws HeadlessException;
}

package java.awt;
public class Container extends Component {
  public void setBorder(@UnknownInitialization JComponent this, @Nullable Border border);
  public void add(@UnknownInitialization Container this, @NonNull Component, @NonNull Object);
}

我知道我可以使用注释来抑制警告,但存根文件感觉像是一种更简洁的方法。有没有办法修复这个存根文件?

4

1 回答 1

0

有两个问题。

第一个问题是您的存根文件格式不正确

线

  public void add(@UnknownInitialization Container this, @NonNull Component, @NonNull Object);

应该

  public void add(@UnknownInitialization Container this, @NonNull Component comp, @NonNull Object constraints);

因为 Java 方法声明需要形式参数名称。

此外,它缺少一个import声明:

import org.checkerframework.checker.nullness.qual.NonNull;

第二个问题是您一定没有传递-Astubs=...命令行参数,否则您会收到有关格式错误的存根文件的警告。(你没有说你是如何调用javac的,这将有助于诊断你的问题。)

当我纠正这些问题时,检查器框架按预​​期工作。运行命令

$CHECKERFRAMEWORK/checker/bin/javac -processor nullness -g MyView.java

发出警告,并且

$CHECKERFRAMEWORK/checker/bin/javac -processor nullness -g MyView.java -Astubs=mystub.astub

不发出警告。

更正的文件(即,它们是完整的并且更小)出现在下面。

MyView.java:

import java.awt.BorderLayout;
import javax.swing.JPanel;
import org.checkerframework.checker.initialization.qual.UnderInitialization;

class MyView extends JPanel {

  MyView() {
    makeTopPanel();
  }

  private void makeTopPanel(@UnderInitialization MyView this) {
    JPanel topPanel = new JPanel(new BorderLayout());
    add(topPanel, BorderLayout.PAGE_START);
  }
}

mystub.astub:

import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.initialization.qual.UnknownInitialization;
import javax.swing.border.Border;
import java.awt.Component;
import java.awt.Container;

package javax.swing;

public class Timer {
  public Timer(int delay, @Nullable ActionListener listener);
}

public class JOptionPane {
  public static void showMessageDialog(@Nullable Component parentComponent,
          Object message, String title, int messageType)
          throws HeadlessException;
}

package java.awt;
public class Container extends Component {
  public void setBorder(@UnknownInitialization JComponent this, @Nullable Border border);
  public void add(@UnknownInitialization Container this, @NonNull Component comp, @NonNull Object constraints);
}
于 2020-03-05T16:54:57.017 回答