Главная страница
Навигация по странице:

  • Что такое «анонимные классы» Где они применяются

  • Каким образом из вложенного класса получить доступ к полю внешнего класса

  • Как проблема ромбовидного наследования решена в java

  • Что такое конструктор по умолчанию

  • Могут ли быть приватные конструкторы Для чего они нужны

  • Расскажите про классы-загрузчики и про динамическую загрузку классов.

  • Чем отличаются конструкторы по-умолчанию, конструктор копирования и конструктор с параметрами

  • Какие модификаторы доступа есть в Java Какие применимы к классам

  • Что означает модификатор static

  • Может ли статический метод быть переопределён или перегружен

  • Могут ли нестатические методы перегрузить статические

  • Можно ли сузить уровень доступа/тип возвращаемого значения при переопределении метода

  • Что можно изменить в сигнатуре метода при переопределении Можно ли менять модификаторы

  • Могут ли классы быть статическими

  • Что означает модификатор final К чему он может быть применим

  • Что такое абстрактные классы Чем они отличаются от обычных

  • Подготовка к собеседованию по JAVACORE. Ответы на вопросы по Core. Core 1 ооп что такое ооп


    Скачать 80.55 Kb.
    НазваниеCore 1 ооп что такое ооп
    АнкорПодготовка к собеседованию по JAVACORE
    Дата13.11.2022
    Размер80.55 Kb.
    Формат файлаdocx
    Имя файлаОтветы на вопросы по Core.docx
    ТипПрограмма
    #785648
    страница3 из 5
    1   2   3   4   5

    Что такое «локальный класс»? Каковы его особенности?

    Данные классы объявляются внутри других методов. По сути, они обладают всеми свойствами нестатического вложенного класса, только создавать их экземпляры можно только в методе, при чем метод не может быть статическим (для их создания нужен экземпляр внешнего класса, в нестатические методы неявно передается ссылка на экземпляр вызывающего объекта, а в статическом методе данной ссылки нет). Но, свои особенности у них есть:

    • Локальные классы способны работать только с final переменными метода. Все дело в том, что экземпляры локальных классов способны сохраняться в «куче» после завершения работы метода, а переменная может быть стёрта. Если же переменная объявлена final, то компилятор может сохранить копию переменной для дальнейшего использования объектом. И еще: с 8+ версий Java можно использовать не final переменные в локальных классах, но только при условии, что они не будут изменяться.

    • Локальные классы нельзя объявлять с модификаторами доступа.

    • Локальные классы обладают доступом к переменным метода.

    Локальные классы можно встретить крайне редко, так как они затрудняют прочтение кода и не обладают никакими плюсами, кроме одного – доступ к переменным метода. Я не знаю, какой можно взять пример локального класса, который бы показал их эффективное применение, так что покажу просто свой пример.
    Что такое «анонимные классы»? Где они применяются?

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

    Использование анонимных классов оправдано во многих случаях, в частности когда:


    Каким образом из вложенного класса получить доступ к полю внешнего класса?
    Через геттеры.
    Что такое перечисления (enum)?

    Кроме отдельных примитивных типов данных и классов в Java есть такой тип как enum или перечисление. Перечисления представляют набор логически связанных констант. Объявление перечисления происходит с помощью оператора enum, после которого идет название перечисления. Затем идет список элементов перечисления через запятую.

    Каждое перечисление имеет статический метод values(). Он возвращает массив всех констант перечисления.

    Метод ordinal() возвращает порядковый номер определенной константы (нумерация начинается с 0).

    Перечисления, как и обычные классы, могут определять конструкторы, поля и методы.
    Как проблема ромбовидного наследования решена в java

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

    В Java множественное наследование не поддерживается в классах, но оно поддерживается в интерфейсах. И один интерфейс может расширять множество других интерфейсов.
    Что такое конструктор по умолчанию?

    Конструктор по умолчанию (default constructor) – это конструктор, который не имеет параметров. Конструктор по умолчанию может объявляться в классе явным образом или генерироваться автоматически.

    Если в классе не объявить ни одного конструктора, то, будет генерироваться конструктор по умолчанию. То есть, конструктор по умолчанию генерируется в классе автоматически только в том случае, если класс не содержит реализации других конструкторов. Если класс содержит реализацию хотя бы одного конструктора с параметрами, то, чтобы объявить конструктор по умолчанию, его нужно объявлять в классе явным образом.
    Могут ли быть приватные конструкторы? Для чего они нужны?

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

    В шаблоне проектирования, называемом Singleton, приватный конструктор используется, чтобы гарантировать, что всегда существует только один экземпляр класса. Класс Singleton предоставляет статический метод для получения этого уникального экземпляра.
    Расскажите про классы-загрузчики и про динамическую загрузку классов.
    Загрузка классов — процесс считывания и анализа байт-кода скомпилированного java-класса и построение на его основе объекта класса java.lang.Class.

    В Java реализована динамическая модель загрузки классов, благодаря которой требуемые JVM классы могут загружаться в оперативную память не при запуске виртуальной машины, но по мере необходимости. Механизм, реализующий эту модель, — загрузчики классов, являющиеся обычными Java-объектами.

    Иерархия загрузчиков классов[править]

    В Java SE имеет место основанная на делегировании иерархия загрузчиков классов. Каждый classloader в иерархии, кроме корневого, хранит ссылку на родительский загрузчик в поле parent объекта ClassLoader. По умолчанию родительским полагается тот загрузчик, который загрузил класс данного загрузчика.

    Корнем иерархии является реализованный на уровне JVM bootstrap-загрузчик. При загрузке очередного класса bootstrap-загрузчик проверяет, не был ли данный класс загружен ранее. Если был, загрузчик возвращает созданный уже объект класса java.lang.Class, в противном случае пытается осуществить загрузку. Случается, что искомый класс не был найден, тогда выбрасывается исключение ClassNotFoundException.[1]

    Для остальных загрузчиков классов логика реализована по следующей схеме. При попытке загрузить класс с заданным именем, загрузчик проверяет в кэше, не был ли этот класс загружен ранее, и если не был, то делегирует задачу более низкоуровневому загрузчику. Тот может либо успешно вернуть объект запрашиваемого класса, либо выбросить ClassNotFoundException. Объект класса возвращается как результат загрузки, а если поймано исключение, то class loader пытается сам найти и загрузить класс и при успехе возвращает созданный объект, а при неудаче выбрасывает ClassNotFoundException.[1]

    По умолчанию JVM использует следующую иерархию:[2]

    bootstrap-загрузчик. По умолчанию он предназначен для загрузки требуемых для работы JVM классов, в частности, пакетов rt.jar[3] и i18n.jar. Запуск JVM с ключом -Xbootclasspath позволяет переопределить наборы базовых классов. Особенностью этого загрузчика является тот факт, что он недоступен из Java — вызов метода getClassLoader() на загруженном bootstrap классе вернёт null, а обратиться к нему можно только внутри класса java.lang.ClassLoader посредством приватных нативных методов.

    Extension-загрузчик. Предназначен для загрузки расширений, по умолчанию хранящихся в $JAVA_HOME/lib/ext, впрочем, этот путь может быть изменён с помощью опции java.ext.dirs. Этот загрузчик представлен классом sun.misc.Launcher$ExtClassLoader. В качестве значения поля parent установлено null, что интерпретируется как bootstrap-загрузчик.

    System-загрузчик, отвечающий за загрузку классов, находящихся в classpath. Этот загрузчик представлен классом sun.misc.Launcher$AppClassLoader и может пыть получен с помощью статического метода java.lang.ClassLoader.getSystemClassLoader(). В качестве значения поля parent хранится ссылка на объект ExtClassLoader.

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

    Кроме того, в Java определено ещё несколько загрузчиков классов, например RMIClassLoader[4] для загрузки классов с помощью RMI, а также предоставлена возможность реализовывать собственные загрузчики.

    В Java EE предлагается другой подход, учитывающий вероятность работы многочисленных не связанных между собой приложений на одном сервере. В этой версии реализована более обширная иерархия загрузчиков классов. Спецификация Java Servlet рекомендует, чтобы Web class loader пытался загрузить класс до того, как делегирует эту задачу родительскому загрузчику. Подобное поведение для Sun JRE может быть настроено в конфигурационном файле sun-web.xml с помощью параметра delegate="false" в описании загрузчика классов.
    Чем отличаются конструкторы по-умолчанию, конструктор копирования и конструктор с параметрами?

    Конструктор по умолчанию не принимает никаких параметров. Конструктор копирования принимает в качестве параметра объект класса. Конструктор с параметрами принимает на вход параметры (обычно необходимые для инициализации полей класса).

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

        //конструктор по умолчанию

        public Circle() {

        }

     

        //конструктор копирования

        public Circle(Circle circle) {

            this(circle.getName(), circle.getArea(), circle.getPerimeter()); //будет вызван конструктор с параметрами ниже

        }

        

        //конструктор с параметрами

        public Circle(String name, Double area, String perimeter) {

            this.name = name;

            this.area = area;

            this.perimeter = perimeter;

        }

    Обращаю внимание, что тема копирования (clone()) достаточно глубокая с возможностью возникновения множества неявных проблем.
    Какие модификаторы доступа есть в Java? Какие применимы к классам?

    • private (закрытый) — доступ к члену класса не предоставляется никому, кроме методов этого класса. Другие классы того же пакета также не могут обращаться к private-членам.

    • default, package, friendly, доступ по умолчанию, когда никакой модификатор не присутствует — член класса считается открытым внутри своего собственного пакета, но не доступен для кода, расположенного вне этого пакета.Т.е. если package2.Class2 extends package1.MainClass, то в Class2 методы без идентификатора из MainClass видны не будут.

    • protected (защищённый) — доступ в пределах пакета и классов наследников. Доступ в классе из другого пакета будет к методам public и protected главного класса. Т.е. если package2.Class2 extends package1.MainClass, то внутри package2.Class2 методы с идентификатором protected из MainClass будут видны.

    • public (открытый) — доступ для всех из любого другого кода проекта

    Модификаторы в списке расположены по возрастающей видимости в программе.
    Что означает модификатор static?
    Модификатора static - с англ.  "статичный", "постоянный" - делает переменную или метод "независимыми" от объекта.

    • Статический метод - это метод, который принадлежит классу, а не экземпляру (объекту)

    • Статический метод может быть вызван без необходимости создания экземпляра класса

    • Статический метод может вызывать только другие статические методы и не может вызывать нестатический метод из него

    • Статический метод может получить доступ к члену статических данных и может изменить его значение.

    • Статический метод не может ссылаться на это или супер-ключевые слова в любом случае

    Может ли статический метод быть переопределён или перегружен?
    На перегрузку (overload) статического метода не накладывается никаких ограничений. С точки зрения компилятора, методы с разным списком аргументов – разные методы. Но это не переопределение.
    Метод с модификатором static относится к классу, а не к его объектам. Для него работает статическое связывание, поэтому именно переопределение (override) в дочернем классе не работает.
    Несмотря на это, в дочернем классе можно объявить static метод с такой же сигнатурой, как в родительском. В этом случае произойдет не перегрузка и не переопределение, а перекрытие (shadowing). К такому методу нельзя применить аннотацию @Override, в нём нельзя использовать ключевое слово super.

    Если вы вызываете статический метод от переменной, а не типа, перекрытие таит в себе опасность. Без динамического связывания компилятор знает только о типе переменной, но не о типе ее значения. Если объявленный тип переменной – базовый класс, то метод-перекрытие никогда не вызовется. Поэтому при попытке такого вызова в IDE мы видим предупреждение.
    Могут ли нестатические методы перегрузить статические?

    Да. В итоге получится два разных метода. Статический будет принадлежать классу и будет доступен через его имя, а нестатический будет принадлежать конкретному объекту и доступен через вызов метода этого объекта.
    Можно ли сузить уровень доступа/тип возвращаемого значения при переопределении метода?

    При переопределении метода нельзя сузить модификатор доступа к методу (например с public в MainClass до private в Class extends MainClass). Изменить тип возвращаемого значения при переопределении метода нельзя, будет ошибка attempting to use incompatible return type. Но можно сузить возвращаемое значение, если они совместимы. Например:

    Java

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    public class Animal {

     

        public Animal eat() {

            System.out.println("animal eat");

            return null;

        }

        

        public Long calc() {

            return null;

        }

     

    }

    public class Dog extends Animal {

     

        public Dog eat() {

            return new Dog();

        }

    /*attempting to use incompatible return type

        public Integer calc() {

            return null;

        }

    */

    }


    Что можно изменить в сигнатуре метода при переопределении? Можно ли менять модификаторы

    Можно менять модификатор доступа, если расширять (package; protected; public)

    Можно менять возвращаемый тип, если выполняется Downcasting (понижающее преобразование, преобразование вниз по иерархии) то есть возвращаемый тип в переопределенном методе класса наследника должен быть НЕ шире чем в классе родителе (Object; Number; Integer)

    Можно менять имя аргументов

    Можно изменять порядок, количество или вовсе убрать секцию throws. Возможно вовсе убрать секцию throws в методе, так как она уже определена. Так же возможно добавлять новые исключения, которые наследуются от объявленных или исключения времени выполнения.

    Нельзя изменять тип аргументов и их количество (в таком случае происходит перегрузка)
    Могут ли классы быть статическими?

    Статическим классом может быть только внутренний класс. Опять же, этот класс привязан к внешнему классу, и если внешний наследуется другим классом, то этот не будет наследован. При этом данный класс можно наследовать, как и он может наследоваться от любого другого класса и имплементировать интерфейс. По сути статический вложенный класс ничем не отличается от любого другого внутреннего класса за исключением того, что его объект не содержит ссылку на создавший его объект внешнего класса. Тем не менее, благодаря этому статический класс наиболее похож на обычный не вложенный, ведь единственное различие состоит в том, что он упакован в другой класс. В некоторых случаях для нас это преимущество, так как с него у нас есть доступ к приватным статическим переменным внешнего класса.
    Что означает модификатор final? К чему он может быть применим?

    В java есть ключевое слово – final. Оно может применяться к классам, методам, переменным (в том числе аргументам методов).

    Для класса это означает, что класс не сможет иметь подклассов, т.е. запрещено наследование. Это полезно при создании immutable (неизменяемых) объектов, например, класс String объявлен, как final.

    Следует также отметить, что к абстрактным классам (с ключевым словом abstract), нельзя применить модификатор final, т.к. это взаимоисключающие понятия. Для метода final означает, что он не может быть переопределен в подклассах. Это полезно, когда мы хотим, чтобы исходную реализацию нельзя было переопределить.

    Для переменных примитивного типа это означает, что однажды присвоенное значение не может быть изменено. Для ссылочных переменных это означает, что после присвоения объекта, нельзя изменить ссылку на данный объект. Это важно! Ссылку изменить нельзя, но состояние объекта изменять можно.
    Что такое абстрактные классы? Чем они отличаются от обычных?

    Кроме обычных классов в Java есть абстрактные классы. Абстрактный класс похож на обычный класс. В абстрактном классе также можно определить поля и методы, но в то же время нельзя создать объект или экземпляр абстрактного класса. Абстрактные классы призваны предоставлять базовый функционал для классов-наследников. А производные классы уже реализуют этот функционал.

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

    Кроме обычных методов абстрактный класс может содержать абстрактные методы. Такие методы определяются с помощью ключевого слова abstract и не имеют никакой реализации.

    Производный класс обязан переопределить и реализовать все абстрактные методы, которые имеются в базовом абстрактном классе. Также следует учитывать, что если класс имеет хотя бы один абстрактный метод, то данный класс должен быть определен как абстрактный.

    Зачем нужны абстрактные классы? Допустим, мы делаем программу для обслуживания банковских операций и определяем в ней три класса: Person, который описывает человека, Employee, который описывает банковского служащего, и класс Client, который представляет клиента банка. Очевидно, что классы Employee и Client будут производными от класса Person, так как оба класса имеют некоторые общие поля и методы. И так как все объекты будут представлять либо сотрудника, либо клиента банка, то напрямую мы от класса Person создавать объекты не будем. Поэтому имеет смысл сделать его абстрактным.
    1   2   3   4   5


    написать администратору сайта