статический внутренний класс - странный - PullRequest
1 голос
/ 05 мая 2011

Мой код:

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: нестатическая переменная, на которую нельзя ссылаться из статического контекста»

Удалить эту строку пройдет компиляция. Однако нам нужно много объектов String в методе static main. В чем разница между String и StringSorter?

Если я изменю StringSorter на статический внутренний класс, он будет скомпилирован нормально. Как статический внутренний класс исправляет ошибку компиляции?

Ответы [ 3 ]

2 голосов
/ 05 мая 2011

StringSorter является внутренним классом и всегда «привязан» к экземпляру внешнего класса MyTest (он может обращаться к своим членам, вызывать его методы и т. Д.). Так как вы пытаетесь создать его экземпляр из статического контекста (метод static main), он не работает. Вместо этого вы можете сделать внутренний класс статическим (например, static public class StringSorter), чтобы он работал.

В качестве альтернативы вы можете переместить StringSorter за пределы MyTest, и в этом случае они являются отдельными классами. (Если вы хотите сохранить оба класса в одном и том же файле, вы должны удалить модификатор public, поскольку для каждого исходного файла разрешен только один открытый класс - с именем файла).

Другой альтернативой может быть перемещение вашего «тестового кода» из основного метода в некоторый метод-член MyTest (следовательно, нестатический контекст) и вызов этого метода ...

0 голосов
/ 05 мая 2011

Этот урок объясняет, как правильно работать с внутренними классами.В своем коде вы пытаетесь использовать MyTest.StringSorter из основного метода.MyTest.main является статическим, поэтому он не может получить доступ к нестатическим полям, методам, внутренним классам, которые определены в его внешнем запросе.

Если сделать StringSorter статическим, этот внутренний класс можно вызывать из статических методов внешнего класса.

Когда вы вызываете исходный код, вы не работаете с экземпляромMyTest.Вы используете один из его статических методов.в учебном пособии сказано, что:

Экземпляр InnerClass может существовать только внутри экземпляра OuterClass и имеет прямой доступ к методам и полям его включающего экземпляра.

Надеюсь, теперь стало понятнее; -)

0 голосов
/ 05 мая 2011

Как сказал dcn, вы должны добавить ключевое слово static к StringComparator (см. Ниже):

public static class StringSorter implements Comparator<String>

Внутренние классы обычно статические , потому что они обычно служебные классы (то же самое в вашем случае; StringComparator помогает вам сравнивать строки на основе их длины).

...