скомпилируется ли следующий код если оба класса будут объявлены в файле test java

скомпилируется ли следующий код если оба класса будут объявлены в файле test java

Отключение проверки зависимостей во время компиляции при компиляции классов Java

Рассмотрим следующие два класса Java:

Кроме того, предположим, что pkg.not.in.classpath.FooBar не найден в пути к классам.

Первый класс отлично скомпилируется с использованием стандартного javac.

Сообщение об ошибке в общем случае является приятным, поскольку проверка ваших зависимостей позволяет компилятору сообщить вам, если вы ошиблись в аргументе метода и т. Д.

Несмотря на то, что эта проверка зависимостей во время компиляции приятна и полезна, AFAIK не строго необходим для создания файла класса Java в приведенном выше примере.

Можете ли вы привести какой-либо пример, для которого было бы технически невозможно создать допустимый файл класса Java без выполнения проверки зависимостей во время компиляции?

Известен ли вам способ указать javac или любому другому компилятору Java пропустить проверку зависимостей во время компиляции?

Убедитесь, что ваш ответ касается обоих вопросов.

8 ответов

Можете ли вы привести какой-либо пример, для которого было бы технически невозможно сгенерировать допустимый файл класса Java без выполнения проверки зависимостей во время компиляции?

Рассмотрим этот код:

Обратите внимание, что хотя ваши два класса функционально эквивалентны, поскольку вы на самом деле не используете аргумент, они не идентичны и при компиляции будут давать другой байт-код.

Я не понимаю, как вы могли допустить это, не нарушив проверку типа Java. Как бы вы использовали объект, на который указывает ссылка, в своем методе? Чтобы продолжить ваш пример,

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

Однако я не вижу смысла делать это. Не могли бы вы предоставить дополнительную информацию о проблеме, которую пытаетесь решить?

Было бы нарушением JLS компилировать класс, не глядя на сигнатуры типов классов, от которых он зависит. Никакой совместимый компилятор Java не позволит вам это сделать.

Таким образом, игнорирование зависимостей во время компиляции приведет к замедлению разработки Java и менее надежным приложениям Java.

Java изначально выполняет проверку зависимостей во время компиляции и использует ее не только для определения типов, но и для определения вызовов методов, когда они перегружены. Я не знаю другого пути.

Что можно сделать (и это делается, скажем, для драйверов JDBC), так это отложить проверку зависимостей с помощью отражения. Вы можете получить класс из Class.forName без того, чтобы компилятор знал класс во время компиляции. В общем, однако, это означает, что код записывается в интерфейс, и во время выполнения загружается класс, реализующий интерфейс.

Сделать FooBar implements IFooBar и

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

В грамматике Java нет ничего, что могло бы отличить pkg.not.in.classpath.FooBar :

Так что есть только ваше слово, что использование FooBar там законно.

Также существует двусмысленность между классами с ограниченным объемом пакета и внутренними классами в исходном коде:

Я создал два класса: Caller и Callee

Существует JSR (JSR 292) для добавления ‘invokedynamic’ код операции, который поддерживает динамический вызов, однако в настоящее время он не поддерживается JVM.

Магия программирования

Когда исчезает магия, появляется понимание

вторник, 19 мая 2009 г.

Ответы на вопросы для собеседования по Java SE (Часть 3)

Предыдущая серия ответов: Ответы на вопросы для собеседования по Java SE (Часть 2)
Теперь помимо ответов на вопросы предоставляю ещё дополнительные вопросики для четкости полученных знаний.

-Можно ли объявить класс с модификатором protected?

12. Какой из модификаторов более строгий: protected или package-private?
Для начала надо разобраться, что такое package-private модификатор. Он ограничивает видимость до пределов пэкэджа, в котором лежит класс. И только до него! То есть, если класс лежит в пэкэдже «ru.myprog», то из пэкэджа «ru.myprog.base» он виден не будет(тоже самое для методов).
Protected модификатор, как все знают(кто хотя бы немного изучал ООП), раскрывает область видимости только для классов-наследников и для классов определенных в том же пэкэдже. Здесь мы видим отличие от C++, в котором только наследники видят protected.
Здесь можно почитать более подробно про модификаторы, а также увидеть сводную табличку http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html

Из всего этого следует, что package-private модификатор более строгий.

-Объявляем класс с модификатором public, в котором создадим метод с default модификатором. Будет ли виден этот метод из других пэкэджей?
-Скомпилируется ли данная программа:
package ru.test;

-Возможно ли перегружать default методы?

13. Если у класса-родителя есть метод, объявленный как private, может ли наследник расширить его видимость? А если protected? А сузить видимость?
private методы никто, кроме самого класса не видит. Поэтому их наличие/отсутствие никак не отражается на классах-наследниках. Они с легкостью могут объявлять методы с такой же сигнатурой и любыми модификаторами. Но это очень плохой тон! Антипаттерн.
Также клас наследник может расширить видимость protected-метода. Такой класс называется «Паблик-Морозов»:). Из-за того, что как известный советсткий пионер, раскрывают информацию кому ни попадя! 🙂
Сузить видимость класс-наследник не может. Это будет ошибка компиляции.

В члена класса final означает константу, которая после инициализации не поменяет своего значения. Но подумайте сами, что будет, если мы объявим, например, коллекцию как final:
Сработает ли следующий код?

15. Имеет ли смысл объявлять метод private final?
Только если вы отъявленный фаталист, финалист и пессимист! 🙂

Файл класса Java

// Компиляция этой Java-программы
// результат в нескольких файлах классов.

public static void main(String[] args)

System.out.println( «Class File Structure» );

Для компиляции:

После компиляции в соответствующей папке будет 3 файла классов с именем:

Структура файла одного класса содержит атрибуты, которые описывают файл класса.
Представление структуры файла класса

Элементы файла класса следующие:

Шаг 1. Компиляция с использованием javac Sample.java.
Шаг 2: Теперь откройте файл Sample.class. Это будет выглядеть следующим образом.

скомпилируется ли следующий код если оба класса будут объявлены в файле test java

Шаг 3: Теперь удалите хотя бы один символ из этого файла Sample.class в начале файла и сохраните его.
Шаг 4: Теперь попробуйте запустить эту команду с помощью Java Sample и увидеть волшебство т.е. вы получите во время выполнения исключения (см выделенного текста ниже изображения):
скомпилируется ли следующий код если оба класса будут объявлены в файле test java

Эта демонстрация для ОС Windows выглядит следующим образом:

Шаг 1: Откройте окно командной строки и попробуйте проверить версию компилятора Java и версию JVM, используя следующие команды соответственно (выделенный текст на изображении — команды)
Выход для версии 1.8 будет:
скомпилируется ли следующий код если оба класса будут объявлены в файле test java
скомпилируется ли следующий код если оба класса будут объявлены в файле test java

скомпилируется ли следующий код если оба класса будут объявлены в файле test java

Примечание: Внутренняя версия jdk 1.5 означает 49.0, а 1.6 означает 50.0, а 1.7 означает 51.0 и т. Д. Версия файла класса, где цифры перед десятичной точкой представляют major_version, а цифры после десятичной точки представляют minor_version.

Подготовка к экзамену Oracle Certified Professional Java Programmer — Часть 1

Предисловие

Хочу продолжить делиться приобретенными знаниями и своими впечатлениями от подготовки к экзамену. Огромное спасибо всем тем, кто дал рекомендации к нулевой части этой серии! Сегодня я поговорю еще немножко о модификаторах доступа и их взаимоотношениях с наследованием и пакетами, рассмотрю varargs и перечисления, а также массивы и способы их инициализации. Я надеюсь, что хабражители снова откликнутся и дополнят то, о чем я забыл упомянуть или попросту не знал.

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

Содержание для всей серии

Методы, поля, локальные переменные и их модификаторы

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

Проверяя предложенный в рамках экзамена код, следует быть аккуратным. Всегда обращайте внимание как на модификатор доступа метода или поля, так и на модификатор доступа класса. Часто можно встретить ситуацию, когда метод имеет модификатор public, в то время как класс, его содержащий, доступен только из пакета. В этой ситуации метод из вне пакета доступен не будет. Можно легко получить минус, не обратив на эту деталь внимания.

Хочу также обратить внимание на некоторые особенности, которые возникают при использовании доступа по умолчанию и модификатора protected. Рассмотрим следующуий пример. Пусть имеется базовый класс, объявленный в пакете test. Этот класс обладает двумя полями. Первое объявлено с доступом по умолчанию, второе — protected.

Если объявить в этом пакете класс SamePackageAccess, который не будет наследоваься от BaseClass, то он все равно получит доступ и к полю defaultValue, и к полю protectedValue. Об этой особенности модификатора protected стоит помнить: члены класса, объявленные как protected, в рамках пакета доступны как через наследование, так и через ссылку. Пример:

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

Теперь давайте посмотрим, что будет, если мы выйдем за пределы пакета. Первое, что случится — мы потеряем доступ к полю, объявленному без явного указания модификатора доступа. Его не будут видеть абсолютно все классы вне родного пакета, в том числе и прямые наследники BaseClass. Поле же с модификатором protected будет доступно через наследование всем своим подклассам. Однако даже наследник не сможет его использовать через ссылку. Кроме того, будучи однажды унаследованным классом вне пакета, поле становится закрытым для любых классов, за исключением дальнейших наследников.

Среди модификаторов, связанных с наследованием, следует также рассмотреть final. На методы final действует также, как на классы: запрещает их переопределение наследниками. При этом расширять сам класс, в котром находится final метод, по-прежнему можно.

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

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

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

Все чудесно соберется и отработает. Формального объяснения этому я не знаю, но предполагаю, что это связано с тем, что vararg-параметр является всего лишь синтаксическим сахаром и воспринимается компилятором как ссылка на массив, поэтому никаких проблем не возникает.

Перечисления

В результате выполения этого кода в стандартный поток вывода будет помещена строка «USD». Обратите внимание на метод getSomethingElse(). Он объявлен для значения USD, однако не упоминается для всего перечисления. Не смотря на то, что в объявлении стоит public, никто из вне доступ к этому методу получить не сможет. Если строку за номером 44 раскомментировать, то код даже не скомпилируется.

Немного о массивах

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

Исключения в Java

скомпилируется ли следующий код если оба класса будут объявлены в файле test java

Обработка исключительных ситуаций (exception handling) — механизм языков программирования, предназначенный для описания реакции программы на ошибки времени выполнения и другие возможные проблемы (исключения), которые могут возникнуть при выполнении программы и приводят к невозможности (бессмысленности) дальнейшей отработки программой её базового алгоритма.

Синтаксис

Здесь в методе getAreaValue мы бросаем исключение IllegalArgumentException с помощью ключевого слова throw. В данном случае в сигнатуре метода отсутствует throws IllegalArgumentException, это не сделано потому что исключение IllegalArgumentException является не проверяемым, о них мы ещё поговорим.

Общий вид конструкции для «поимки» исключительной ситуации выглядит следующим образом:

В нашем случае для площади прямоугольника:

Здесь мы поймали IllegalArgumentException и залогировали данное событие. Дело в том что «починить» такую поломку мы не можем, не будем же мы угадывать что хотел пользователь :). По этому мы пробрасываем данное исключение дальше с помощью «throw e;». Такое часто можно встретить на серверах приложений(веб-серверах).

finally

Иногда требуется гарантировать, что определенный участок кода будет выполняться независимо от того, какие исключения были возбуждены и перехвачены. Для создания такого участка кода используется ключевое слово finally. Даже в тех случаях, когда в методе нет соответствующего возбужденному исключению раздела catch, блок finally будет выполнен до того, как управление перейдет к операторам, следующим за разделом try. У каждого раздела try должен быть по крайней мере или один раздел catch или блок finally. Блок finally очень удобен для закрытия файлов и освобождения любых других ресурсов, захваченных для временного использования в начале выполнения метода. Ниже приведен пример класса с двумя методами, завершение которых происходит по разным причинам, но в обоих перед выходом выполняется код раздела finally.

В этом примере в методе procA из-за возбуждения исключения происходит преждевременный выход из блока try, но по пути «наружу» выполняется раздел finally. Другой метод procB завершает работу выполнением стоящего в try-блоке оператора return, но и при этом перед выходом из метода выполняется программный код блока finally. Ниже приведен результат, полученный при выполнении этой программы.

Иерархия исключений

Все классы обрабатывающие ошибки являются наследниками класса java.lang.Throwable. Только объекты этого класса или его наследников могут быть «брошены» JVM при возникновении какой-нибудь исключительной ситуации, а также только эти объекты могут быть «брошены» во время выполнения программы с помощью ключевого слова throw.

Прямыми наследниками класса Throwable являются Error и Exception.

При программировании на Java основное внимание следует уделять иерархии Exception. Эта иерархия также разделяется на две ветви: исключения, производные от класса RuntimeException, и остальные. Исключения типа RuntimeException возникают вследствие ошибок программирования. Все другие исключения являются следствием непредвиденного стечения обстоятельств, например, ошибок ввода-вывода, возникающих при выполнении вполне корректных программ.

Рассмотрим основные классы исключений. скомпилируется ли следующий код если оба класса будут объявлены в файле test java скомпилируется ли следующий код если оба класса будут объявлены в файле test java

Создание своих классов исключений

Хотя встроенные исключения Java обрабатывают большинство частых ошибок, вероятно, вам потребуется создать ваши собственные типы исключений для обработки ситуаций, специфичных для ваших приложений. Это достаточно просто сделать: просто определите подкласс Exception (который, разумеется, является подклассом Throwable). Ваши подклассы не обязаны реализовывать что-либо — важно само их присутствие в системе типов, которое позволит использовать их как исключения.

Обработка нескольких исключений

Одному блоку try может соответствовать сразу несколько блоков catch с разными классами исключений.

Это удобно, если обработка ошибок не отличается.

Конструкция try-with-resources

Наследование методов бросающих исключения

Можно лишь сужать класс исключения:

Как бросить проверяемое исключение не обрабатывая его (хак)

Нет ничего невозможного. С помощью рефлексии и внутреннего API языка java можно творить магию :).

В примере используется рефлексия для получения объекта Unsafe так как другими средствами это сделать проблематично. У класса Unsafe приватный конструктор. А если попытаться вызвать статический метод getUnsafe() то будет брошено исключение SecurityException.

Заключение

Изначально я хотел сделать себе шпаргалку по иерархии классов исключений и не планировал писать статью. Но получилось так, что шпаргалка выросла в статью 🙂

Надеюсь она поможет кому-нибудь перед собеседованием, или просто вспомнить/углубить знания 🙂 Спасибо за внимание!

Если Вам понравилась статья, проголосуйте за нее

Голосов: 86 Голосовать скомпилируется ли следующий код если оба класса будут объявлены в файле test java

Источник

Магия программирования

Когда исчезает магия, появляется понимание

вторник, 19 мая 2009 г.

Ответы на вопросы для собеседования по Java SE (Часть 3)

Предыдущая серия ответов: Ответы на вопросы для собеседования по Java SE (Часть 2)
Теперь помимо ответов на вопросы предоставляю ещё дополнительные вопросики для четкости полученных знаний.

-Можно ли объявить класс с модификатором protected?

12. Какой из модификаторов более строгий: protected или package-private?
Для начала надо разобраться, что такое package-private модификатор. Он ограничивает видимость до пределов пэкэджа, в котором лежит класс. И только до него! То есть, если класс лежит в пэкэдже «ru.myprog», то из пэкэджа «ru.myprog.base» он виден не будет(тоже самое для методов).
Protected модификатор, как все знают(кто хотя бы немного изучал ООП), раскрывает область видимости только для классов-наследников и для классов определенных в том же пэкэдже. Здесь мы видим отличие от C++, в котором только наследники видят protected.
Здесь можно почитать более подробно про модификаторы, а также увидеть сводную табличку http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html

Из всего этого следует, что package-private модификатор более строгий.

-Объявляем класс с модификатором public, в котором создадим метод с default модификатором. Будет ли виден этот метод из других пэкэджей?
-Скомпилируется ли данная программа:
package ru.test;

-Возможно ли перегружать default методы?

13. Если у класса-родителя есть метод, объявленный как private, может ли наследник расширить его видимость? А если protected? А сузить видимость?
private методы никто, кроме самого класса не видит. Поэтому их наличие/отсутствие никак не отражается на классах-наследниках. Они с легкостью могут объявлять методы с такой же сигнатурой и любыми модификаторами. Но это очень плохой тон! Антипаттерн.
Также клас наследник может расширить видимость protected-метода. Такой класс называется «Паблик-Морозов»:). Из-за того, что как известный советсткий пионер, раскрывают информацию кому ни попадя! 🙂
Сузить видимость класс-наследник не может. Это будет ошибка компиляции.

В члена класса final означает константу, которая после инициализации не поменяет своего значения. Но подумайте сами, что будет, если мы объявим, например, коллекцию как final:
Сработает ли следующий код?

15. Имеет ли смысл объявлять метод private final?
Только если вы отъявленный фаталист, финалист и пессимист! 🙂

Источник

Исключения в Java

скомпилируется ли следующий код если оба класса будут объявлены в файле test java

Обработка исключительных ситуаций (exception handling) — механизм языков программирования, предназначенный для описания реакции программы на ошибки времени выполнения и другие возможные проблемы (исключения), которые могут возникнуть при выполнении программы и приводят к невозможности (бессмысленности) дальнейшей отработки программой её базового алгоритма.

Синтаксис

Здесь в методе getAreaValue мы бросаем исключение IllegalArgumentException с помощью ключевого слова throw. В данном случае в сигнатуре метода отсутствует throws IllegalArgumentException, это не сделано потому что исключение IllegalArgumentException является не проверяемым, о них мы ещё поговорим.

Общий вид конструкции для «поимки» исключительной ситуации выглядит следующим образом:

В нашем случае для площади прямоугольника:

Здесь мы поймали IllegalArgumentException и залогировали данное событие. Дело в том что «починить» такую поломку мы не можем, не будем же мы угадывать что хотел пользователь :). По этому мы пробрасываем данное исключение дальше с помощью «throw e;». Такое часто можно встретить на серверах приложений(веб-серверах).

finally

Иногда требуется гарантировать, что определенный участок кода будет выполняться независимо от того, какие исключения были возбуждены и перехвачены. Для создания такого участка кода используется ключевое слово finally. Даже в тех случаях, когда в методе нет соответствующего возбужденному исключению раздела catch, блок finally будет выполнен до того, как управление перейдет к операторам, следующим за разделом try. У каждого раздела try должен быть по крайней мере или один раздел catch или блок finally. Блок finally очень удобен для закрытия файлов и освобождения любых других ресурсов, захваченных для временного использования в начале выполнения метода. Ниже приведен пример класса с двумя методами, завершение которых происходит по разным причинам, но в обоих перед выходом выполняется код раздела finally.

В этом примере в методе procA из-за возбуждения исключения происходит преждевременный выход из блока try, но по пути «наружу» выполняется раздел finally. Другой метод procB завершает работу выполнением стоящего в try-блоке оператора return, но и при этом перед выходом из метода выполняется программный код блока finally. Ниже приведен результат, полученный при выполнении этой программы.

Иерархия исключений

Все классы обрабатывающие ошибки являются наследниками класса java.lang.Throwable. Только объекты этого класса или его наследников могут быть «брошены» JVM при возникновении какой-нибудь исключительной ситуации, а также только эти объекты могут быть «брошены» во время выполнения программы с помощью ключевого слова throw.

Прямыми наследниками класса Throwable являются Error и Exception.

При программировании на Java основное внимание следует уделять иерархии Exception. Эта иерархия также разделяется на две ветви: исключения, производные от класса RuntimeException, и остальные. Исключения типа RuntimeException возникают вследствие ошибок программирования. Все другие исключения являются следствием непредвиденного стечения обстоятельств, например, ошибок ввода-вывода, возникающих при выполнении вполне корректных программ.

Рассмотрим основные классы исключений. скомпилируется ли следующий код если оба класса будут объявлены в файле test java скомпилируется ли следующий код если оба класса будут объявлены в файле test java

Создание своих классов исключений

Хотя встроенные исключения Java обрабатывают большинство частых ошибок, вероятно, вам потребуется создать ваши собственные типы исключений для обработки ситуаций, специфичных для ваших приложений. Это достаточно просто сделать: просто определите подкласс Exception (который, разумеется, является подклассом Throwable). Ваши подклассы не обязаны реализовывать что-либо — важно само их присутствие в системе типов, которое позволит использовать их как исключения.

Обработка нескольких исключений

Одному блоку try может соответствовать сразу несколько блоков catch с разными классами исключений.

Это удобно, если обработка ошибок не отличается.

Конструкция try-with-resources

Наследование методов бросающих исключения

Можно лишь сужать класс исключения:

Как бросить проверяемое исключение не обрабатывая его (хак)

Нет ничего невозможного. С помощью рефлексии и внутреннего API языка java можно творить магию :).

В примере используется рефлексия для получения объекта Unsafe так как другими средствами это сделать проблематично. У класса Unsafe приватный конструктор. А если попытаться вызвать статический метод getUnsafe() то будет брошено исключение SecurityException.

Заключение

Изначально я хотел сделать себе шпаргалку по иерархии классов исключений и не планировал писать статью. Но получилось так, что шпаргалка выросла в статью 🙂

Надеюсь она поможет кому-нибудь перед собеседованием, или просто вспомнить/углубить знания 🙂 Спасибо за внимание!

Если Вам понравилась статья, проголосуйте за нее

Голосов: 86 Голосовать скомпилируется ли следующий код если оба класса будут объявлены в файле test java

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *