Здравствуйте уважаемые знатоки). Недавно в процессе изучения 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 это так же компилируется и работает.
Помогите пожалуйста в этом всем разобраться.
В Java, класс, объявленный в другом классе, называется вложенным классом.
Существует два типа вложенных классов: статические и нестатические.
Статический вложенный класс (static nested class) – это класс, объявленный с модификатором static
.
Нестатический вложенный класс (также называется внутренним классом, 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, например: Шилдт, Хорстманн, Эккель.
Как меняется крипторынок и к чему готовиться владельцам криптообменников
Возможно ли добавить новую запись(нового пользователя) в таблицу, которую извлекли из базы данных? При нажатии кнопки должны открываться...
В tomcat-usersxml задаются пользователи с определенными правами
Такой вопрос, в проекте я использую метод для проверки работы сервиса,я вынес его в отдельный класс с аннотацией @Module: