【问题标题】:static inner class - weird静态内部类 - 奇怪
【发布时间】:2011-05-05 10:04:03
【问题描述】:

我的代码:

public class MyTest {
    public class StringSorter implements Comparator<String>
    {
        public StringSorter() {}

        public int compare(String s1, String s2)
        {
            int l1 = s1.length();
            int l2 = s2.length();
            return l1-l2;
        }
    }

    public static void main(String[] args) {
        System.out.println("Hello, world!");

        StringSorter sorter = new StringSorter();
        Set<String> sets = new TreeSet<String>(sorter);
        sets.add(new String("he"));
        sets.add(new String("hel"));
        sets.add(new String("he"));
        sets.add(new String("hello"));

        for (String s: sets)
        {
            System.out.println(s);
        }
    }
}

它会报错: "MyTest.java:41: 不能从静态上下文引用的非静态变量"

删除此行将通过编译。但是,我们在“静态 main”方法中需要许多 String 对象。 String 和 StringSorter 有什么区别?

如果我将 StringSorter 更改为静态内部类,它将被编译好。静态内部类如何修复编译错误?

【问题讨论】:

  • 你应该只使用 "he" 而不是 new String("he")
  • 为什么?^^ 谢谢你的提醒。

标签: java static inner-classes


【解决方案1】:

StringSorter 是一个内部类并且总是“绑定”到外部类MyTest 的一个实例(它可以访问它的成员,调用它的方法等等)。由于您尝试从静态上下文(静态 main 方法)实例化它,因此它失败了。相反,您可以将内部类设为静态(如 static public class StringSorter)以使其工作。

或者,您可以将StringSorter 移到MyTest 之外,在这种情况下,它们是单独的类。 (如果您仍想将两个类保留在同一个文件中,则必须删除 public 修饰符,因为每个源文件只允许使用一个公共类 - 带有文件名)。

另一种选择是将您的“测试代码”从主方法移动到MyTest 的某个成员方法(因此是非静态上下文)并调用此方法...

【讨论】:

  • 我不明白你最后的提议。无法从静态的 main 方法调用 MyTest 的非静态方法。
  • 我的意思是:将所有代码从main 移动到MyTest 中的某个方法test(),并写入MyTest.mainnew MyTest().test() ...
  • 好吧,我不清楚。这样,您可以实例化 Mytest 对象,并调用实例化嵌套类。
【解决方案2】:

正如dcn所说,您必须将static关键字添加到StringComparator(见下文):

public static class StringSorter implements Comparator<String>

内部类通常是静态的,因为它们通常是实用程序类(在您的情况下也是如此;StringComparator 帮助您根据字符串的长度比较字符串)。

【讨论】:

    【解决方案3】:

    This tutorial 很好地解释了如何处理内部类。在您的代码中,您尝试使用 main 方法中的 MyTest.StringSorterMyTest.main 是静态的,因此它无法访问在其外部类中定义的非静态字段、方法、内部类。

    StringSorter设为静态时,可以从外部类的静态方法中调用这个内部类。

    当您调用原始代码时,您使用的不是MyTest 的实例。您正在使用其静态方法之一。教程中说:

    可以存在 InnerClass 的实例 仅在 OuterClass 的一个实例中 并且可以直接访问方法 及其封闭实例的字段。

    希望现在更清楚;-)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-07
      • 2011-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多