Объекты статических классов

418
18 февраля 2017, 05:34

Здравствуйте уважаемые знатоки). Недавно в процессе изучения Java(путем прохождения javarush) наткнулся на вот такой код, вызвавший у меня когнитивный диссонанс:

public class Solution {
    public static void main(String[] args) throws Exception {
        EnglishTranslator englishTranslator = new EnglishTranslator();
        System.out.println(englishTranslator.translate());
    }
    public static abstract class Translator {
        public abstract String getLanguage();
        public String translate() {
            return "Я переводчик с " + getLanguage();
        }
    }
    public static class EnglishTranslator extends Translator {
        @Override
        public String getLanguage() {
            return "английского";
        }
    }
}

Он компилируется и нормально работает. Внимание вопрос: Зачем мы создаем экземпляр статического класса??

Следующий код не компилируется:

public class Solution {
    public static void main(String[] args) throws Exception {
        //EnglishTranslator englishTranslator = new EnglishTranslator();
        System.out.println(EnglishTranslator.translate()); //non-static method translate() cannot be
                                                           //referenced from a static context
    }
    public static abstract class Translator {
        public abstract String getLanguage();
        public String translate() {
            return "Я переводчик с " + getLanguage();
        }
    }
    public static class EnglishTranslator extends Translator {
        @Override
        public String getLanguage() {
            return "английского";
        }
    }
}

Если мы убираем модификатор static у класса EnglishTranslator, то получаем следующую ошибку:

Solution.this cannot be referenced from a static context

Так же мы можем вынести Translator и EnglishTranslator за Solution и убрать у них модификатор static это так же компилируется и работает.

Помогите пожалуйста в этом всем разобраться.

Answer 1

В Java, класс, объявленный в другом классе, называется вложенным классом.

Существует два типа вложенных классов: статические и нестатические.

  1. Статический вложенный класс (static nested class) – это класс, объявленный с модификатором static.

  2. Нестатический вложенный класс (также называется внутренним классом, inner class) – это, собственно, класс, объявленный без модификатора static.

Зачем мы создаем экземпляр статического класса?

Нестатический вложенный класс (внутренний класс) неявно содержит ссылку на экземпляр внешнего класса, за счет этого достигается доступ к нестатическим полям внешнего класса из внутреннего класса.

Так как внутренний класс содержит ссылку на экземпляр внешнего класса, то экземпляр внутреннего класса можно создать только в нестатических методах (или блоках) внешнего класса.

Так как Вы создаете экземпляр вложенного класса в статическом методе внешнего класса, т.е. без создания экземпляра внешнего класса, то этот вложенный класс должен быть статическим.

Следующий код не компилируется:

В этом случае Вы пытаетесь вызвать нестатический метод translate() без создания экземпляра класса, чего делать нельзя.

Казалось бы, решение этой проблемы заключаться в объявлении методов translate() и getLanguage() статическими, однако в данном случае этот вариант не сработает, так как метод getLanguage() является абстрактным методом, а абстрактный метод нельзя объявить статическим.

Если мы убираем модификатор static у класса EnglishTranslator, то получаем следующую ошибку:

Solution.this cannot be referenced from a static context

Если Вы уберете модификатор static у класса EnglishTranslator, то этот класс станет внутренним классом, а внутренний класс, как было сказано выше, неявно содержит ссылку на экземпляр внешнего класса.

Вы создаете экземпляр класса EnglishTranslator в статическом методе внешнего класса, который может быть вызван без создания экземпляра внешнего класса, следовательно, сослаться на this внешнего класса в этом методе Вы не сможете, откуда следует, что в этом методе невозможно создать экземпляр внутреннего класса EnglishTranslator.

Так же мы можем вынести Translator и EnglishTranslator за Solution и убрать у них модификатор static это так же компилируется и работает.

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

И самое главное

Изучать язык Java (собственно, как и любой другой язык программирования) без чтения соответствующих классических книг – это очень и очень плохая идея.

Статьи в интернете (которые могут быть некорректными, например, в некоторых из них ошибочно указано, что в Java объекты передаются при вызове по ссылке), всякие там видео-уроки (это вообще для ленивых, типа как фильм посмотреть с пачкой чипсов и банкой колы) – это не то, с помощью чего следует изучать подобные фундаментальные вещи.

Да, про некоторые моменты можно почитать какие-то статьи, но в приоритете всегда должно быть авторитетное пособие.

По поводу JavaRush – да, ребята предоставляют неплохую практику по языку, но перед выполнением этих практических вещей просто необходимо освоить теорию по выбранной теме в книге.

Так что советую Вам всегда держать под рукой (не только держать, но и вникать :)) что-нибудь из классики по Java, например: Шилдт, Хорстманн, Эккель.

READ ALSO
Как добавить новую запись к таблице, извлеченной из базы данных java?

Как добавить новую запись к таблице, извлеченной из базы данных java?

Возможно ли добавить новую запись(нового пользователя) в таблицу, которую извлекли из базы данных? При нажатии кнопки должны открываться...

332
Управление пользователями Tomcat с помощью Spring Security

Управление пользователями Tomcat с помощью Spring Security

В tomcat-usersxml задаются пользователи с определенными правами

294
Java, эквивалент LINQ Select, Stream API

Java, эквивалент LINQ Select, Stream API

Имеется List объектов класса Person

300
Перенос проекта на dagger2

Перенос проекта на dagger2

Такой вопрос, в проекте я использую метод для проверки работы сервиса,я вынес его в отдельный класс с аннотацией @Module:

353