Java: различия между версиями
imported>ВМНС |
Нет описания правки |
||
| Строка 1: | Строка 1: | ||
{{ | {{о|языке программирования|прикладной платформе на основе данного языка|Java (программная платформа)}} | ||
{{не путать|JavaScript}} | |||
{{Карточка языка программирования | |||
| логотип = [[Файл:Java logo.svg|121px]] | |||
| класс = [[Java Virtual Machine#Среда исполнения|язык JVM]], [[мультипарадигменный язык программирования|мультипарадигменный]]: [[объектно-ориентированное программирование|объектно-ориентированный]], | |||
[[аспектно-ориентированное программирование|аспектно-ориентированный]], | |||
[[обобщённое программирование|обобщённый]], [[Отражение (программирование)|рефлективный]] | |||
| дата выпуска = [[23 мая]] [[1995 год|1995]] | |||
| расширение = .java, .class, [[JAR|.jar]], .jad, .jmod, [[WAR (тип файла)|.war]], [[EAR|.ear]] | |||
| последняя версия = Java SE 24<ref>{{Cite web|title=Oracle Releases Java 24|url=https://www.oracle.com/news/announcement/oracle-releases-java-24-2025-03-18/|access-date=2025-03-27}}</ref> | |||
| дата выпуска последней версии = 18.03.2025 | |||
| повлиял на = [[Ада (язык программирования)|Ada]], [[C Sharp|C#]], [[Chapel (язык программирования)|Chapel]], [[Clojure]], [[ECMAScript]], [[Fantom]], [[Gambas]], [[Groovy]], [[Hack (язык программирования)|Hack]], [[Haxe]], [[Visual J Sharp|J#]], [[Kotlin]], [[PHP]], [[Python]], [[Scala (язык программирования)|Scala]], [[Seed7]], [[Vala]], [[JavaScript]] | |||
| сайт = https://java.com | |||
| Последняя версия = Java SE 24 | |||
}} | |||
'''Java'''<ref group="прим.">Произносится на английском как {{IPA|/ˈdʒɑːvə/}}, «Джава». В русском языке помимо «Джава» встречается транслитерация «Ява», но правообладатели торговой марки предпочитают первую транслитерацию.</ref> — [[сильная и слабая типизация|строго]] [[статическая типизация|типизированный]] [[объектно-ориентированный язык программирования]] общего назначения, разработанный компанией [[Sun Microsystems]] (в последующем приобретённой компанией [[Oracle]]). Разработка ведётся сообществом, организованным через [[Java Community Process]]; язык и основные реализующие его технологии распространяются по лицензии [[GPL]]. Права на [[Торговая марка|торговую марку]] принадлежат корпорации [[Oracle]]. | |||
Приложения Java обычно [[транслятор|транслируются]] в специальный [[байт-код]], поэтому они могут работать на любой [[Компьютерная архитектура|компьютерной архитектуре]], для которой существует реализация [[Java Virtual Machine|виртуальной Java-машины]]. Дата официального выпуска — 23 мая 1995 года. Java занимает высокие места в рейтингах популярности языков программирования (2-е место в рейтингах [[IEEE Spectrum]] (2020)<ref>{{Cite news|title=Top Programming Languages 2020|url=https://spectrum.ieee.org/at-work/tech-careers/top-programming-language-2020|work=IEEE Spectrum|access-date=2021-02-14|language=en|archive-date=2021-01-18|archive-url=https://web.archive.org/web/20210118190122/https://spectrum.ieee.org/at-work/tech-careers/top-programming-language-2020}}</ref> и [[Индекс TIOBE|TIOBE]] (2021<ref>{{Cite web|url=https://www.tiobe.com/tiobe-index/|title=TIOBE Index {{!}} TIOBE — The Software Quality Company|publisher=www.tiobe.com|access-date=2018-11-19|archive-date=2018-02-25|archive-url=https://web.archive.org/web/20180225101948/https://www.tiobe.com/tiobe-index/|url-status=live}}</ref>)). | |||
== История создания == | |||
[[Файл:James Gosling 2008.jpg|thumb|[[Гослинг, Джеймс|Джеймс Гослинг]]]] | |||
Изначально язык назывался Oak («Дуб»), разрабатывался [[Гослинг, Джеймс|Джеймсом Гослингом]] для программирования бытовых электронных устройств. Из-за того, что язык с таким названием уже существовал, Oak был переименован в Java<ref>{{Книга|автор=Buyya|заглавие=Object-oriented Programming with Java: Essentials and Applications|ссылка=https://books.google.ru/books?id=rXGMFYXFDwMC&pg=PA34&dq=James+gosling+oak&hl=ru&sa=X&ved=0ahUKEwiB9PfT-s3eAhXMqIsKHSC7BIkQ6AEILDAA|издательство=Tata McGraw-Hill Education|год=2009|страниц=678|isbn=9780070669086|access-date=2018-11-12|archive-date=2018-11-12|archive-url=https://web.archive.org/web/20181112101707/https://books.google.ru/books?id=rXGMFYXFDwMC&pg=PA34&dq=James+gosling+oak&hl=ru&sa=X&ved=0ahUKEwiB9PfT-s3eAhXMqIsKHSC7BIkQ6AEILDAA#v=onepage&q=James%20gosling%20oak&f=false|url-status=live}}</ref>. Назван в честь марки [[кофе]] Java, которая, в свою очередь, получила наименование одноимённого острова ([[Ява]]), поэтому на официальной эмблеме языка изображена чашка с горячим кофе. Существует и другая версия происхождения названия языка, связанная с [[Аллюзия|аллюзией]] на кофемашину как пример бытового устройства, для программирования которого изначально язык создавался. В соответствии с этимологией в русскоязычной литературе с конца двадцатого и до первых лет двадцать первого века название языка нередко переводилось как Ява, а не транскрибировалось. | |||
В результате работы проекта мир увидел принципиально новое устройство, [[карманный персональный компьютер]] Star7<ref>{{Cite web |url=https://temofeev.ru/info/articles/star7-s-chego-nachinalas-java/ |title=Star7: с чего начиналась Java |access-date=2022-10-02 |archive-date=2022-10-02 |archive-url=https://web.archive.org/web/20221002075116/https://temofeev.ru/info/articles/star7-s-chego-nachinalas-java/ |url-status=live }}</ref>, который опередил своё время более чем на 10 лет, но из-за большой стоимости в 50 долларов не смог произвести переворот в мире технологии и был забыт. | |||
Устройство Star7 не пользовалось популярностью, в отличие от языка программирования Java и его окружения. Следующим этапом жизни языка стала разработка интерактивного телевидения. Однако в 1994 году стало очевидным, что интерактивное телевидение было ошибкой. | |||
С середины 1990-х годов язык стал широко использоваться для написания клиентских приложений и [[Сервер (программное обеспечение)|серверного]] программного обеспечения. Тогда же определённое распространение получила технология [[Java-апплет]]ов — графических Java-приложений, встраиваемых в веб-страницы; с развитием возможностей [[Динамический сайт|динамических веб-страниц]] в 2000-е годы технология стала применяться редко. | |||
В [[Веб-разработка|веб-разработке]] применяется [[Spring Framework]]; для документирования используется утилита [[Javadoc]]. | |||
== Основные особенности языка == | |||
Программы на Java [[транслятор|транслируются]] в [[байт-код Java]], выполняемый [[Java Virtual Machine|виртуальной машиной Java]] (JVM) — программой, обрабатывающей байтовый код и передающей инструкции оборудованию как [[интерпретатор]]. | |||
[[Файл:Duke (Java mascot) waving.svg|thumb|150px|Дюк — талисман Java]] | |||
Достоинством подобного способа выполнения программ является полная независимость байт-кода от [[Операционная система|операционной системы]] и оборудования, что позволяет выполнять Java-приложения на любом устройстве, для которого существует соответствующая виртуальная машина. Другой важной особенностью технологии Java является гибкая система безопасности, в рамках которой исполнение программы полностью контролируется виртуальной машиной. Любые операции, которые превышают установленные полномочия программы (например, попытка несанкционированного доступа к данным или соединения с другим компьютером), вызывают немедленное прерывание. | |||
Часто к недостаткам концепции виртуальной машины относят снижение производительности. Ряд усовершенствований немного увеличил скорость выполнения программ на Java: | |||
* применение технологии трансляции [[Байт-код Java|байт-кода]] в [[машинный код]] непосредственно во время работы программы ([[JIT]]-технология) с возможностью сохранения версий класса в машинном коде, | |||
* обширное использование [[платформенно-ориентированный код|платформенно-ориентированного кода]] (native-код) в стандартных библиотеках, | |||
* аппаратные средства, обеспечивающие ускоренную обработку байт-кода (например, технология [[Jazelle]], поддерживаемая некоторыми процессорами [[ARM (архитектура)|архитектуры ARM]]). | |||
По данным сайта shootout.alioth.debian.org, для семи разных задач время выполнения на Java составляет в среднем в полтора-два раза больше, чем для C/C++, но при этом в некоторых случаях Java быстрее, а в отдельных случаях в 7 раз медленнее<ref name="slow_java">{{Cite web |url=http://shootout.alioth.debian.org/u32q/benchmark.php?test=all&lang=java |title=Java 6 -server speed ÷ C++ GNU g++ speed {{!}} Computer Language Benchmarks Game |access-date=2010-03-04 |archive-url=https://web.archive.org/web/20110614210615/http://shootout.alioth.debian.org/u32q/benchmark.php?test=all&lang=java |archive-date=2011-06-14 |url-status=dead }}</ref>. С другой стороны, для большинства из них потребление памяти Java-машиной было в 10—30 раз больше, чем программой на C/C++. Также примечательно исследование, проведённое компанией [[Google (компания)|Google]], согласно которому отмечается существенно более низкая производительность и бо́льшее потребление памяти в тестовых примерах на Java в сравнении с аналогичными программами на [[C++]]<ref>{{cite web | |||
|url = https://www.theregister.co.uk/2011/06/03/google_paper_on_cplusplus_java_scala_go/ | |||
|title = Google pits C++ against Java, Scala, and Go | |||
|author = Metz, Cade | |||
|date = 2011-06-03 | |||
|work = | |||
|publisher = [[The Register]] | |||
|access-date = 2011-06-05 | |||
|lang = en | |||
|archive-url = https://www.webcitation.org/6170nFPxZ?url=http://www.theregister.co.uk/2011/06/03/google_paper_on_cplusplus_java_scala_go/ | |||
|archive-date = 2011-08-21 | |||
}}</ref><ref>[https://days2011.scala-lang.org/sites/days2011/files/ws3-1-Hundt.pdf Loop Recognition in C++/Java/Go/Scala]{{Refsize|0.3}} {{Wayback|url=https://days2011.scala-lang.org/sites/days2011/files/ws3-1-Hundt.pdf |date=20111116151424 }}</ref><ref>{{Cite web |url=http://www.opennet.ru/opennews/art.shtml?num=30784 |title=В Google провели сравнение производительности C++, Java, Go и Scala |access-date=2011-06-05 |archive-date=2011-06-08 |archive-url=https://web.archive.org/web/20110608232010/http://www.opennet.ru/opennews/art.shtml?num=30784 |url-status=live }}</ref>. | |||
Идеи, заложенные в концепцию и различные реализации среды виртуальной машины Java, вдохновили множество энтузиастов на расширение перечня языков, которые могли бы быть использованы для создания программ, исполняемых на виртуальной машине<ref>{{cite web | |||
|author = Robert Tolksdorf. | |||
|url = http://www.is-research.de/info/vmlanguages/ | |||
|title = Programming languages for the Java Virtual Machine JVM | |||
|publisher = is-research GmbH | |||
|access-date = 2009-06-05 | |||
|lang = en | |||
|description = Онлайн-каталог альтернативных языков и языковых расширений для JVM | |||
|archive-url = https://www.webcitation.org/6170nqDc9?url=http://www.is-research.de/info/vmlanguages/ | |||
|archive-date = 2011-08-21 | |||
}}</ref>. Эти идеи нашли также выражение в спецификации общеязыковой инфраструктуры [[Common Language Infrastructure|CLI]], заложенной в основу платформы [[.NET Framework|.NET]] компанией [[Microsoft]]. | |||
== Классификация платформ Java == | |||
Внутри Java существует несколько основных семейств технологий: | |||
* [[Java SE]] — Java Standard Edition — основное издание Java. Содержит компиляторы, [[API]], [[Java Runtime Environment]]; подходит для создания пользовательских приложений, в первую очередь — для настольных систем. | |||
* [[Jakarta EE]] (ранее — Java EE (Enterprise Edition)) представляет собой набор спецификаций для создания [[программное обеспечение|ПО]] уровня предприятия. В 2017-м проект Java EE был передан [[Eclipse Foundation]], и тогда же его наименование изменилось на текущее<ref>{{Cite news|title=Opening Up Java EE - An Update|first=David|last=Delabassee|url=https://blogs.oracle.com/theaquarium/opening-up-ee-update|access-date=2018-11-25|archive-date=2018-11-26|archive-url=https://web.archive.org/web/20181126010151/https://blogs.oracle.com/theaquarium/opening-up-ee-update}}</ref><ref>{{Cite news|title=And the Name Is…|url=https://eclipse-foundation.blog/2018/02/26/and-the-name-is/|work=Life at Eclipse|date=2018-02-26|access-date=2018-11-25|language=en|archive-date=2018-11-26|archive-url=https://web.archive.org/web/20181126010008/https://eclipse-foundation.blog/2018/02/26/and-the-name-is/}}</ref>. Модули Java EE удалены из Java SE с 11-й версии<ref>{{Cite web|url=http://openjdk.java.net/jeps/320|title=JEP 320: Remove the Java EE and CORBA Modules|publisher=openjdk.java.net|access-date=2018-11-25|archive-date=2018-11-24|archive-url=https://web.archive.org/web/20181124235611/http://openjdk.java.net/jeps/320|url-status=live}}</ref>. | |||
* [[Java ME]] — Java Micro Edition, создана для использования в устройствах, ограниченных по вычислительной мощности, например, в [[мобильный телефон|мобильных телефонах]], [[Карманный персональный компьютер|КПК]], [[Встраиваемая система|встроенных системах]]; | |||
* [[Java Card]] — технология предоставляет безопасную среду для приложений, работающих на [[смарт-карта]]х и других устройствах с очень ограниченным объёмом памяти и возможностями обработки. | |||
== Java и Microsoft == | |||
Компанией [[Microsoft]] была разработана собственная реализация [[JVM]] под названием {{Не переведено 3|Microsoft Java Virtual Machine|4=Microsoft Java Virtual Machine}} (MSJVM)<ref name="msjvm" />, включавшаяся в состав различных [[Операционная система|операционных систем]], начиная с [[Windows 98]] (также входила в [[Internet Explorer]] от версии 3 и выше, что позволяло использовать MSJVM в ОС [[Windows 95]] и [[Windows NT 4.0|Windows NT 4]] после установки IE3+ на данные ОС). | |||
MSJVM имела существенные отличия от Sun Java, во многом ломающие основополагающую концепцию переносимости программ между разными платформами: | |||
* отсутствие поддержки [[Интерфейс программирования приложений|программного интерфейса]] [[Remote Procedure Call|вызова удалённых методов]] ([[RMI]]); | |||
* отсутствие поддержки технологии [[JNI]]; | |||
* наличие нестандартных расширений, таких, как средства интеграции Java и [[DCOM]], работающих только на платформе Windows. | |||
Тесная интеграция Java с DCOM и [[Windows API|Win32]] поставила под вопрос [[Кроссплатформенность|кроссплатформенную]] парадигму языка. Впоследствии это явилось поводом для судебных исков со стороны [[Sun Microsystems]] к Microsoft. Суд принял сторону компании Sun Microsystems. В конечном счёте между двумя компаниями была достигнута договорённость о возможности продления срока официальной поддержки пользователей нестандартной Microsoft JVM до конца 2007 года<ref name=msjvm>{{cite web | |||
|date = 2003-09-12 | |||
|url = http://www.microsoft.com/About/Legal/EN/US/Interoperability/Java/Default.aspx | |||
|title = Microsoft Java Virtual Machine Support | |||
|publisher = Microsoft | |||
|access-date = 2010-10-09 | |||
|lang = en | |||
|description = Официальное заявление Microsoft о программе поддержки MSJVM | |||
|archive-url = https://www.webcitation.org/6170oubDn?url=http://www.microsoft.com/About/Legal/EN/US/Interoperability/Java/Default.aspx | |||
|archive-date = 2011-08-21 | |||
}}</ref>. | |||
В 2005 году компанией Microsoft для платформы [[.NET Framework|.NET]] был представлен Java-подобный язык [[Visual J Sharp|J#]], не соответствующий официальной спецификации языка Java и исключённый впоследствии из стандартного инструментария разработчика [[Microsoft Visual Studio]], начиная с Visual Studio 2008<ref>{{cite web | |||
|date = 2007-11 | |||
|url = http://msdn.microsoft.com/ru-ru/library/7xsxf8e2(VS.90).aspx | |||
|title = Visual J# | |||
|publisher = Microsoft | |||
|access-date = 2010-10-10 | |||
|lang = ru | |||
|description = Официальная информация Microsoft об исключении J# из комплекта Visual Studio 2008 | |||
|archive-url = https://www.webcitation.org/6170pJXt3?url=http://msdn.microsoft.com/ru-ru/library/7xsxf8e2(VS.90).aspx | |||
|archive-date = 2011-08-21 | |||
}}</ref>. | |||
== Java и Android == | |||
{{Main|Android}} | |||
Язык Java активно используется для создания мобильных приложений под операционную систему Android. При этом программы компилируются в нестандартный байт-код для использования их виртуальной машиной [[Dalvik virtual machine|Dalvik]] (начиная с [[Android Lollipop|Android 5.0 Lollipop]] виртуальная машина заменена на [[Android Runtime|ART]]). Для такой компиляции используется дополнительный инструмент, а именно [[Android SDK]] ([[SDK|Software Development Kit]]), разработанный компанией [[Google (компания)|Google]]. | |||
Разработку приложений можно вести в среде [[Android Studio]], [[NetBeans]], в среде [[Eclipse (среда разработки)|Eclipse]]. | |||
== Применения платформы Java == | |||
Следующие успешные проекты реализованы с привлечением Java ([[J2EE]]) технологий: [[RuneScape]], [[Amazon]]<ref>{{cite web | |||
|author = Todd Hoff. | |||
|date = 2007-09-18 | |||
|url = http://highscalability.com/amazon-architecture | |||
|title = Amazon Architecture | |||
|access-date = 2009-06-06 | |||
|lang = en | |||
|description = Обсуждение архитектуры Amazon с использованием Java-технологий | |||
|archive-date = 2009-02-28 | |||
|archive-url = https://web.archive.org/web/20090228222248/http://highscalability.com/amazon-architecture | |||
|url-status = live | |||
}}</ref><ref>{{cite web | |||
|url = http://aws.amazon.com/ec2/ | |||
|title = Amazon Elastic Compute Cloud (Amazon EC2) | |||
|publisher = Amazon Web Services LLC | |||
|access-date = 2009-06-06 | |||
|lang = en | |||
|description = Описание технологии и возможностей Amazon EC2 как веб-сервиса | |||
|archive-url = https://www.webcitation.org/6170rMoFx?url=http://aws.amazon.com/ec2/ | |||
|archive-date = 2011-08-21 | |||
}}</ref>, [[eBay]]<ref>{{cite web | |||
|author = Todd Hoff. | |||
|date = 2008-05-27 | |||
|url = http://highscalability.com/ebay-architecture | |||
|title = eBay Architecture | |||
|access-date = 2009-09-06 | |||
|lang = en | |||
|description = Обсуждение архитектуры eBay на платформе Java | |||
|archive-url = https://www.webcitation.org/6170rzVA7?url=http://highscalability.com/ebay-architecture | |||
|archive-date = 2011-08-21 | |||
}}</ref><ref>{{cite web | |||
|author = Randy Shoup, Dan Pritchett. | |||
|date = 2006-11-29 | |||
|url = http://www.addsimplicity.com/downloads/eBaySDForum2006-11-29.pdf | |||
|title = The eBay Architecture | |||
|work = SD Forum 2006 | |||
|publisher = ??? | |||
|access-date = 2009-06-06 | |||
|lang = en | |||
|description = Презентация по истории развития архитектуры eBay | |||
|archive-url = https://www.webcitation.org/6170saktV?url=http://www.addsimplicity.com/downloads/eBaySDForum2006-11-29.pdf | |||
|archive-date = 2011-08-21 | |||
}}</ref>, [[LinkedIn]]<ref>{{cite web | |||
|author = Brian Guan. | |||
|date = 2008-06-11 | |||
|url = http://blog.linkedin.com/2008/06/11/grails-at-linkedin/ | |||
|title = The LinkedIn Blog. Blog Archive. Grails at LinkedIn | |||
|publisher = LinkedIn.com | |||
|access-date = 2009-06-05 | |||
|lang = en | |||
|description = История создания системы LinkedIn на основе Java-технологии Grails | |||
|archive-url = https://www.webcitation.org/6170ueU7e?url=http://blog.linkedin.com/2008/06/11/grails-at-linkedin/ | |||
|archive-date = 2011-08-21 | |||
}}</ref>, [[Yahoo!]]<ref>{{cite web | |||
|url = http://developer.yahoo.com/hadoop/ | |||
|title = Hadoop and Distributed Computing at Yahoo! | |||
|publisher = Yahoo! | |||
|access-date = 2009-06-21 | |||
|lang = en | |||
|description = Стартовая страница Java-технологии распределённого обслуживания Hadoop на портале разработчиков Yahoo! | |||
|archive-url = https://www.webcitation.org/6170vguJb?url=http://developer.yahoo.com/hadoop/ | |||
|archive-date = 2011-08-21 | |||
}}</ref>. | |||
Следующие компании в основном фокусируются на Java- ([[J2EE]]-) технологиях: [[SAP]], [[IBM]], [[Oracle]]. В частности, [[Система управления базами данных|СУБД]] [[Oracle Database]] включает JVM как свою составную часть, обеспечивающую возможность непосредственного программирования СУБД на языке Java, включая, например, [[хранимая процедура|хранимые процедуры]]<ref>{{cite web | |||
|url = http://www.oracle.com/technology/tech/java/jsp/index.html | |||
|title = OracleJVM and Java Stored Procedures | |||
|publisher = Oracle Inc. | |||
|access-date = 2009-06-05 | |||
|lang = en | |||
|description = Раздел портала Oracle, посвящённый технологиям Java в составе сервера СУБД Oracle | |||
|archive-url = https://www.webcitation.org/6170wCzk5?url=http://www.oracle.com/technetwork/topics/index.html | |||
|archive-date = 2011-08-21 | |||
}}</ref>. | |||
Также существует Java библиотека классов для сериализации объектов в XML (или JSON) формат — [[XStream]]. | |||
=== Производительность === | |||
Программы, написанные на Java, имеют репутацию более медленных и занимающих больше оперативной памяти, чем написанные на языке C<ref name="slow_java"/>. Тем не менее, скорость выполнения программ, написанных на языке Java, была существенно улучшена с выпуском в 1997—1998 годах JIT-компилятора в версии 1.1 в дополнение к другим особенностям языка для поддержки лучшего анализа кода (такие, как внутренние классы, класс <code>StringBuffer</code><ref group="док.">{{Javadoc:SE|java.base/java/lang|StringBuffer}}</ref>, упрощённые логические вычисления и так далее). Кроме того, была произведена оптимизация виртуальной машины Java — с 2000 года для этого используется виртуальная машина [[HotSpot]]. По состоянию на февраль 2012 года код Java 7 приблизительно в 1,8 раза медленнее кода, написанного на языке Си<ref>{{cite web | |||
|url = http://shootout.alioth.debian.org/u32q/which-programming-languages-are-fastest.php?gcc=on&javasteady=on&java=on&csharp=on&javaxint=on&calc=chart | |||
|title = Ubuntu: Intel® Q6600® quad-core Computer Language Benchmarks | |||
|archive-url = https://www.webcitation.org/68bfPITT0?url=http://shootout.alioth.debian.org/u32q/which-programming-languages-are-fastest.php?gcc=on | |||
|archive-date = 2012-06-22 | |||
}}</ref>. | |||
Некоторые платформы предлагают аппаратную поддержку выполнения для Java<ref>{{Статья|автор=Wolfgang Puffitsch, Martin Schoeberl|заглавие=picoJava-II in an FPGA|ссылка=http://orbit.dtu.dk/files/4176066/pjfpga.pdf|язык=en|издание=DTU Library|тип=|год=2007|месяц=|число=|том=|номер=|страницы=|issn=|access-date=2018-12-02|archive-date=2018-12-02|archive-url=https://web.archive.org/web/20181202202734/http://orbit.dtu.dk/files/4176066/pjfpga.pdf|url-status=live}}</ref>. К примеру, микроконтроллеры, выполняющие код Java на аппаратном обеспечении вместо программной JVM, а также основанные на ARM процессоры, которые поддерживают выполнение байт-кода Java через опцию Jazelle. | |||
== Основные возможности == | |||
* [[Сборка мусора (программирование)|Автоматическое управление памятью]]; | |||
* Расширенные возможности обработки [[Обработка исключений|исключительных ситуаций]]; | |||
* Богатый набор средств фильтрации ввода-вывода; | |||
* Набор стандартных [[Коллекция (программирование)|коллекций]]: [[Индексный массив|массив]], [[Список (информатика)|список]], [[стек]] и т.п; | |||
* Наличие простых средств создания сетевых приложений (в том числе — с использованием [[Сетевой протокол|протокола]] [[RMI]]); | |||
* Наличие классов, позволяющих выполнять [[HTTP]]-запросы и обрабатывать ответы; | |||
* Встроенные в язык средства создания многопоточных приложений, которые потом были портированы на многие языки, например, [[Python]]; | |||
* Унифицированный доступ к [[База данных|базам данных]]: | |||
** на уровне отдельных [[SQL]]-запросов — на основе [[JDBC]], [[SQLJ]]; | |||
** на уровне концепции объектов, обладающих способностью к хранению в базе данных — на основе {{нп1|Java Data Objects||en|Java Data Objects}} и [[Java Persistence API]]; | |||
* Поддержка [[Обобщённое программирование|обобщений]] (с версии 1.5); | |||
* Поддержка [[Лямбда-исчисление|лямбд]], [[Замыкание (программирование)|замыканий]], возможностей [[Функциональное программирование|функционального программирования]] (с Java 8). | |||
== Основные идеи == | |||
=== Примитивные типы === | |||
В языке Java только 8 примитивных (скалярных, простых) [[Тип данных|типов]]: <code>[[Логический тип|boolean]]</code>, <code>[[Байт|byte]]</code>, <code>[[символьный тип|char]]</code>, <code>[[short]]</code>, <code>[[целый тип|int]]</code>, <code>[[Long (тип данных)|long]]</code>, <code>[[число одинарной точности|float]]</code>, <code>[[Число двойной точности|double]]</code>. Существует также вспомогательный девятый примитивный тип — <code>[[void]]</code>, однако переменные и поля такого типа не могут быть объявлены в коде, а сам тип используется только для описания соответствующего ему класса, для использования при [[Отражение (программирование)|рефлексии]]: например, с помощью класса <code>Void</code><ref group="док.">{{Javadoc:SE|java.base/java/lang|Void}}</ref> можно узнать, является ли определённый метод типа <code>void</code>: <code>Hello.class.getMethod("main", String[].class).getReturnType() == Void.TYPE</code>. | |||
Длины и диапазоны значений примитивных типов определяются стандартом, а не реализацией, и приведены в таблице. Тип char сделали двухбайтовым для удобства локализации (один из идеологических принципов Java): когда складывался стандарт, уже существовал [[Unicode]]-16, но не Unicode-32. Поскольку в результате не осталось однобайтового типа, добавили новый тип byte, причём в Java, в отличие от других языков, он не является беззнаковым. Типы <code>float</code> и <code>double</code> могут иметь специальные значения <math>+\infty</math>, <math>-\infty</math> и «не число» ([[NaN]]). Для типа double они обозначаются <code>Double.POSITIVE_INFINITY</code>, <code>Double.NEGATIVE_INFINITY</code>, <code>Double.NaN</code>; для типа <code>float</code> — так же, но с приставкой <code>Float</code> вместо <code>Double</code>. Минимальные и максимальные значения, принимаемые типами <code>float</code> и <code>double</code>, тоже стандартизованы. | |||
{| class="wikitable" | |||
! Тип | |||
! Длина (в байтах) || Диапазон или набор значений | |||
|- | |||
| boolean || 1 в массивах, 4 в переменных<ref>JVM не имеет поддержки для переменных типа boolean, поэтому они представляются в виде значений типа int. Однако массивы boolean[] поддерживаются. [http://java.sun.com/docs/books/jvms/second_edition/html/Overview.doc.html#22909 VM Spec The Structure of the Java Virtual Machine] {{Wayback|url=http://java.sun.com/docs/books/jvms/second_edition/html/Overview.doc.html#22909 |date=20111124105915 }}</ref>|| true, false | |||
|- | |||
| byte || 1 || −128..127 | |||
|- | |||
| char || 2 || 0..2<sup>16</sup>−1, или 0..65535 | |||
|- | |||
| short || 2 || −2<sup>15</sup>..2<sup>15</sup>−1, или −32768..32767 | |||
|- | |||
| int || 4 || −2<sup>31</sup>..2<sup>31</sup>−1, или −2147483648..2147483647 | |||
|- | |||
| long || 8 || −2<sup>63</sup>..2<sup>63</sup>−1, или примерно −9.2·10<sup>18</sup>..9.2·10<sup>18</sup> | |||
|- | |||
|- | |||
| float || 4 || -(2-2<sup>−23</sup>)·2<sup>127</sup>..(2-2<sup>−23</sup>)·2<sup>127</sup>, или примерно −3.4·10<sup>38</sup>..3.4·10<sup>38</sup>, а также <math>-\infty</math>, <math>\infty</math>, NaN | |||
|- | |||
| double || 8 || -(2-2<sup>−52</sup>)·2<sup>1023</sup>..(2-2<sup>−52</sup>)·2<sup>1023</sup>, или примерно −1.8·10<sup>308</sup>..1.8·10<sup>308</sup>, а также <math>-\infty</math>, <math>\infty</math>, NaN | |||
|} | |||
Такая жёсткая стандартизация была необходима, чтобы сделать язык платформенно-независимым, что является одним из идеологических требований к Java. Тем не менее, одна небольшая проблема с платформенной независимостью всё же осталась. Некоторые процессоры используют для промежуточного хранения результатов 10-байтовые [[Регистр процессора|регистры]] или другими способами улучшают точность вычислений. Для того, чтобы сделать Java максимально совместимой между разными системами, в ранних версиях любые способы повышения точности вычислений были запрещены. Однако это приводило к снижению быстродействия. Выяснилось, что ухудшение точности ради платформенной независимости мало кому нужно, тем более если за это приходится платить замедлением работы программ. После многочисленных протестов этот запрет отменили, но добавили ключевое слово <code>strictfp</code>, запрещающее повышение точности. Начиная с Java 17, запрет на повышение точности снова начал действовать, а ключевое слово <code>strictfp</code> было объявлено устаревшим<ref>{{cite web |url=https://openjdk.org/jeps/306 |lang=en |title=JEP 306: Restore Always-Strict Floating-Point Semantics |url-status=live |access-date=2022-11-21 |archive-url=https://web.archive.org/web/20221121205320/https://openjdk.org/jeps/306 |archive-date=2022-11-21}}</ref>. | |||
=== | ==== Преобразования при математических операциях ==== | ||
В языке Java действуют следующие правила: | |||
# Если один [[операнд]] имеет тип <code>double</code>, другой тоже преобразуется к типу <code>double</code>. | |||
# Иначе, если один операнд имеет тип <code>float</code>, другой тоже преобразуется к типу <code>float</code>. | |||
# Иначе, если один операнд имеет тип <code>long</code>, другой тоже преобразуется к типу <code>long</code>. | |||
# Иначе оба операнда преобразуются к типу <code>int</code>. | |||
{{ | Данный способ неявного преобразования встроенных типов полностью совпадает с преобразованием типов в [[Си (язык программирования)|Си]]/[[C++]]<ref>{{книга|автор=[[Бьярн Страуструп]].|заглавие=Язык программирования C++|оригинал=The C++ Programming Language|место=М.—СПб.|издательство= Бином, Невский диалект|год=2008||страниц=1104|isbn=5-7989-0226-2; ISBN 5-7940-0064-3; ISBN 0-201-70073-5|тираж=5000}}</ref>. | ||
=== | === Объектные переменные, объекты, ссылки и указатели === | ||
В языке Java имеются только динамически создаваемые объекты. [[Переменная (программирование)|Переменные]] объектного типа и объекты в Java — совершенно разные сущности. Переменные объектного типа являются [[Ссылка (программирование)|ссылками]], то есть аналогами [[Указатель (тип данных)|указателей]] на динамически создаваемые объекты. Это подчёркивается [[Синтаксис (программирование)|синтаксисом]] описания переменных. Так, код на [[C++]] может выглядеть следующим образом: | |||
<source lang="java" line="1">double a[10][20]; | |||
Foo b(30);</source> | |||
Но то же самое на Java будет выглядеть совсем по-другому: | |||
<source lang="java" line="1"> | |||
double[][] a = new double[10][20]; | |||
Foo b = new Foo(30); | |||
</source> | |||
При присваиваниях, передаче в [[Подпрограмма|подпрограммы]] и сравнениях объектные переменные ведут себя как указатели, то есть присваиваются, копируются и сравниваются [[Адрес памяти|адреса]] объектов. А при доступе с помощью объектной переменной к полям данных или методам объекта не требуется никаких специальных операций [[Указатель (тип данных)#Действия над указателями|разыменовывания]] — этот доступ осуществляется так, как если бы объектная переменная была самим объектом. | |||
=== | Объектными являются переменные любого типа, кроме примитивного. Явных указателей в Java нет. В отличие от указателей C, C++ и других языков программирования, ссылки в Java в высокой степени безопасны благодаря жёстким ограничениям на их использование. | ||
* Нельзя преобразовывать объект типа <code>int</code> или любого другого примитивного типа в указатель или ссылку и наоборот. | |||
* Над ссылками запрещено выполнять операции <code>++</code>, <code>−−</code>, <code>+</code>, <code>−</code> или любые другие арифметические и логические операции (<code>&&</code>, <code>||</code>, <code>^^</code>). | |||
* Преобразование типов между ссылками жёстко регламентировано. За исключением ссылок на массивы, разрешено преобразовывать ссылки только между наследуемым типом и его наследником, причём преобразование наследуемого типа в наследующий должно быть явно задано, а во время выполнения производится проверка его осмысленности. Преобразования ссылок на массивы разрешены лишь тогда, когда разрешены преобразования их базовых типов, а также нет конфликтов размерности. | |||
* В Java нет операций взятия адреса (<code>&</code>) или взятия объекта по адресу (<code>*</code>). [[Амперсанд#Прочие применения|Амперсанд]] (<code>&</code>) означает всего лишь «побитовое и» (двойной амперсанд — «логическое и»). Однако для булевых типов одиночный амперсанд означает «логическое и», отличающееся от двойного тем, что цепь проверок не прекращается при получении в выражении значения <code>false</code><ref>{{Cite web|url=https://docs.oracle.com/javase/specs/jls/se11/html/jls-15.html#jls-15.23|title=Java Language Specification|author=[[Гослинг, Джеймс|Джеймс Гослинг]], Билл Джой, Гай Стил, Гилад Брача, Алекс Бакли, Даниел Смит|website=|subtitle=Chapter 15. Expressions|date=|publisher=docs.oracle.com|lang=en|access-date=2018-12-01|archive-date=2018-12-01|archive-url=https://web.archive.org/web/20181201135332/https://docs.oracle.com/javase/specs/jls/se11/html/jls-15.html#jls-15.23|url-status=live}}</ref>. Например, <code>a == b && foo() == bar()</code> не повлечёт вызовов <code>foo()</code> и <code>bar()</code> в случае, если <code>a != b</code>, тогда как использование <code>&</code> — повлечёт в любом случае. | |||
Благодаря таким специально введённым ограничениям в Java невозможно прямое манипулирование памятью на уровне физических адресов (хотя определено значение ссылки, не указывающей ни на что: <code>null</code>). | |||
Если нужен указатель на примитивный тип, используются классы-обёртки примитивных типов: <code>Boolean</code>, <code>Byte</code>, <code>Character</code>, <code>Short</code>, <code>Integer</code>, <code>Long</code>, <code>Float</code>, <code>Double</code>. | |||
==== | ==== Дублирование ссылок и клонирование ==== | ||
При присваивании не происходит копирования объекта, так как объектные переменные — ссылочные. Так, если написать | |||
<source lang="java" line="1"> | |||
Foo foo, bar; | |||
. . . | |||
bar = foo; | |||
</source> | |||
то произойдёт копирование адреса из переменной <code>foo</code> в переменную <code>bar</code>. То есть <code>foo</code> и <code>bar</code> будут указывать на одну и ту же область памяти, то есть на один и тот же объект; попытка изменить поля объекта, на который ссылается переменная <code>foo</code>, будет менять объект, с которым связана переменная <code>bar</code>, и наоборот. Если же необходимо получить именно ещё одну ''копию'' исходного объекта, пользуются или [[Метод (языки программирования)|методом]] (функцией-членом, в терминологии C++) <code>clone()</code>, создающим копию объекта, или (реже) копирующим [[Конструктор (объектно-ориентированное программирование)|конструктором]] (конструкторы в Java не могут быть виртуальными, поэтому экземпляр класса-потомка будет неправильно скопирован конструктором класса-предка; метод клонирования вызывает нужный конструктор и тем самым позволяет обойти это ограничение). | |||
==== | Метод <code>clone()</code><ref group="док.">{{Javadoc:SE|name=clone()|java.base/java/lang|Object|clone()}}</ref> требует, чтобы класс реализовывал [[Интерфейс (объектно-ориентированное программирование)|интерфейс]] <code>Cloneable</code><ref group="док.">{{Javadoc:SE|java/lang|Cloneable}}</ref>. Если класс реализует интерфейс <code>Cloneable</code>, по умолчанию <code>clone()</code> копирует все поля (''мелкая копия''). Если требуется не копировать, а клонировать поля (а также их поля и так далее), надо переопределять метод <code>clone()</code>. Определение и использование метода <code>clone()</code> часто является нетривиальной задачей<ref>{{Cite web|url=https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Object.html|title=Java API Reference|author=|website=|subtitle=Class Object|date=|publisher=docs.oracle.com|lang=en|access-date=2018-11-26|archive-date=2018-11-26|archive-url=https://web.archive.org/web/20181126222346/https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Object.html|url-status=live}}</ref>. | ||
==== | ==== Инициализация переменных ==== | ||
Все переменные или требуют явного определения, или автоматически заполняются нулями (0, <code>null</code>, <code>false</code>). Таким образом, исчезают [[гейзенбаг]]и, связанные со случайным использованием неинициализированной памяти, характерные для низкоуровневых языков вроде [[Си (язык программирования)|Си]]. | |||
=== | ==== Сборка мусора ==== | ||
{{ | В языке Java невозможно явное удаление объекта из памяти — вместо этого реализована [[Сборка мусора (программирование)|сборка мусора]]. Традиционным приёмом, дающим сборщику мусора «намёк» на необходимость освобождения памяти, является присваивание переменной значения <code>null</code>, что может оказаться эффективным при необходимости освободить более не требующийся объект, ссылка на который хранится в долгоживущем объекте<ref>{{Книга|автор=Scott Oaks|заглавие=Java Performance: The Definitive Guide: Getting the Most Out of Your Code|ссылка=https://books.google.ru/books?id=aIhUAwAAQBAJ&pg=PA195&lpg=PA195&dq=elementData%5B--size%5D+=+null;+//+Let+gc+do+its+work&source=bl&ots=E6Zs7rX4hE&sig=g8RiFVjoILKL2o7mWRNrUWt_ytw&hl=ru&sa=X&ved=2ahUKEwiBjvCGv_7eAhWUhaYKHfNaA-wQ6AEwCHoECAUQAQ|издательство="O'Reilly Media, Inc."|год=2014-04-10|страниц=425|isbn=9781449363543|access-date=2021-08-09|archive-date=2021-07-21|archive-url=https://web.archive.org/web/20210721005409/https://books.google.ru/books?id=aIhUAwAAQBAJ&pg=PA195&lpg=PA195&dq=elementData%5B--size%5D+%3D+null%3B+%2F%2F+Let+gc+do+its+work&source=bl&ots=E6Zs7rX4hE&sig=g8RiFVjoILKL2o7mWRNrUWt_ytw&hl=ru&sa=X&ved=2ahUKEwiBjvCGv_7eAhWUhaYKHfNaA-wQ6AEwCHoECAUQAQ#v=onepage&q=elementData%5B--size%5D%20=%20null;%20//%20Let%20gc%20do%20its%20work&f=false|url-status=live}}</ref>. Это, однако, не значит, что объект, заменённый значением <code>null</code>, будет немедленно удалён, но есть гарантия, что этот объект будет удалён в будущем. Данный приём всего лишь устраняет ссылку на объект, то есть отвязывает указатель от объекта в памяти. При этом следует учитывать, что объект не будет удалён сборщиком мусора, пока на него указывает хотя бы одна ссылка из используемых переменных или объектов. Существуют также методы для инициации принудительной сборки мусора, но не гарантируется, что они будут вызваны исполняющей средой, и их не рекомендуется использовать для обычной работы. Помимо периодических сборок мусора стоит отметить так называемую «общую сборку мусора» (STW, {{lang-en|Stop The World}}), которая может привести ко временному «подвисанию» исполняемой программы<ref>{{Cite web|url=https://www.ibm.com/docs/en/sdk-java-technology/8?topic=management-garbage-collection-gc|title=Garbage collection|date=2024-02-12|access-date=2025-02-06}}</ref>. | ||
| | |||
| | В Java используется несколько сборщиков мусора (Serial GC, Parallel GC, G1, ZGC), какой из них используется по умолчанию — зависит от версии [[Интегрированная среда разработки|IDE]]. Чтобы выбрать какой-то определённый, нужно запустить [[JRE]] с ключом командной строки «-XX:+Use<имя сборщика>GC -jar <имя-jar-файла.jar>», например, вызов «java -XX:+UseG1GC -jar Application.java» приведёт к сборке мусора его сборщиком G1<ref>{{Cite web|url=https://www.baeldung.com/jvm-garbage-collectors|title=JVM Garbage Collectors|date=2024-05-11|access-date=2025-02-04}}</ref>. | ||
| | |||
| | |||
| | |||
| | |||
| | |||
| | |||
}} | |||
=== | === Классы и функции === | ||
Java не является процедурным языком: любая функция может существовать только внутри класса. Это подчёркивает терминология языка Java, где нет понятий «функция» или «функция-член» ({{lang-en|member function}}), а только ''метод''. В методы превратились и стандартные функции. Например, в Java нет функции <code>sin()</code>, а есть метод <code>Math.sin()</code> класса <code>Math</code> (содержащего, кроме <code>sin()</code>, методы <code>cos()</code>, <code>exp()</code>, <code>sqrt()</code>, <code>abs()</code> и многие другие). | |||
Как и в языке [[Си (язык программирования)|C]], любая исполняемая программа на Java должна иметь [[Си (язык программирования)#Точка входа программы|точку входа]], которой является метод main — он должен/может быть единственным в программе и, в отличие от Си, всегда статическим. При этом, начиная с Java 21, в которой были экспериментально введены безымянные классы, допускается определять этот метод, не определяя имени главного класса. | |||
Конструкторы в Java не считаются методами. Деструкторов в Java не существует, а метод <code>finalize()</code> ни в коем случае нельзя считать аналогом деструктора. | |||
==== Конструкторы ==== | |||
Конструктор — это специальный метод, который обязательно вызывается при создании нового объекта, то есть объект (экземпляр класса) не может быть создан без вызова конструктора класса. Не всегда удобно инициализировать все переменные класса при создании его экземпляра, поэтому переменные экземпляра часто объявляют внутри тела конструктора, а инициализируют как аргументы конструктора при создании экземпляра класса. Иногда проще, чтобы какие-то значения были бы созданы по умолчанию при создании объекта. В таком случае переменные объявляются и инициализируются внутри тела конструктора. | |||
Конструктор инициализирует объект непосредственно во время создания. Имя конструктора совпадает с именем класса, включая регистр, а по синтаксису конструктор похож на метод без возвращаемого значения.<syntaxhighlight lang="java" line="1"> | |||
private int Cat(); // так выглядит метод по имени Cat | |||
Cat(); // так выглядит конструктор класса Cat | |||
</syntaxhighlight>В отличие от метода, конструктор никогда ничего не возвращает. | |||
Конструктор определяет действия, выполняемые при создании объекта класса, и является важной частью класса. Как правило, программисты стараются явно указать конструктор. Если явного конструктора нет, то Java автоматически создаст его (пустым) для использования по умолчанию. | |||
== | В качестве примера можно рассмотреть некий класс <code>Box</code>, представляющий собой описание коробки. Конструктор класса просто установит начальные размеры для коробки.<syntaxhighlight lang="java" line="1"> | ||
{ | class Box { | ||
int width; // ширина коробки | |||
int height; // высота коробки | |||
int depth; // глубина коробки | |||
{ | // Конструктор | ||
Box(int a, int b) { | |||
width = a; | |||
height = b; | |||
depth = 10; | |||
} | |||
// вычисляем объём коробки | |||
{ | int getVolume() { | ||
return width * height * depth; | |||
} | |||
} | |||
</syntaxhighlight> | |||
=== | ==== Статические методы и поля ==== | ||
{{ | В Java (как и в C++) используются ''статические поля и'' ''статические методы'' ({{lang-en|static method}} — в теории программирования их также называют методами класса), которые задаются при помощи ключевого слова <code>static</code>. Статические поля (переменные класса) имеют тот же смысл, что и в C++: каждое такое поле является собственностью класса, поэтому для доступа к статическим полям не требуется создавать экземпляры соответствующего класса. | ||
= | Например, математические функции, реализованные в классе <code>Math</code><ref group="док.">{{Javadoc:SE|java.base/java/lang|Math}}</ref>, представляют собой как раз статические методы данного класса. Поэтому их можно вызывать напрямую из класса, не создавая его экземпляра, например: | ||
<source lang="java" line="1">double x = Math.sin(1);</source> | |||
Создание экземпляра статического класса запрещают с помощью приватного конструктора. Например, создание экземпляра класса <code>Math</code> приведёт к ошибке на этапе компиляции: | |||
<source lang="java" line="1">Math m = new Math(); // Error: Math() has private access in java.lang.Math | |||
double x = m.sin(1); // Метода sin у объекта не существовало бы, т. к. он статичный</source> | |||
Поскольку статические методы существуют независимо от объектов (экземпляров класса), они не имеют доступа к обычным (не статическим) полям и методам данного класса. В частности, при реализации статического метода недопустимо использовать идентификатор <code>this</code>. | |||
==== | Возможность статического импорта позволяет вызывать статические функции и константы без указания класса. Пример без статического импорта: | ||
<source lang="java" line="1"> | |||
double x = Math.sin(Math.tan(Math.sqrt(y)) + Math.floor(24.5)) + Math.cos(42 * Math.PI);</source> | |||
Тот же пример, но со статическим импортом: | |||
<source lang="java" line="1"> | |||
import static java.lang.Math.*; | |||
... | |||
double x = sin(tan(sqrt(y)) + floor(24.5)) + cos(42 * PI);</source> | |||
==== | ==== Завершённость (final) ==== | ||
# | Ключевое слово <code>final</code> (финальный) имеет разные значения при описании поля, метода или класса. | ||
# | # Финальное '''поле''' класса инициализируется при описании или в конструкторе класса (а статическое поле — в статическом блоке инициализации). Впоследствии его значение не может быть изменено. Если статическое поле класса или переменная проинициализированы константным выражением, они рассматриваются компилятором как [[константа (программирование)|именованная константа]]; в таком случае их значение может быть использовано в [[Switch (оператор)|операторах <code>switch</code>]] (для констант типов <code>int</code> и <code>String</code>, в том числе — элементов [[Перечисляемый тип#Java|перечислений]]), а также для условной компиляции (для констант типа <code>boolean</code>) при использовании с [[Условный оператор|оператором <code>if</code>]]. | ||
# Значения '''локальных переменных''', а также '''параметров метода''', помеченных ключевым словом <code>final</code>, не могут быть изменены после присвоения. При этом их значения могут использоваться внутри [[Внутренний класс#Анонимные (безымянные) классы|анонимных классов]]. | |||
# '''Метод''' класса, отмеченный словом <code>final</code>, не может быть переопределён при наследовании. В случае '''статического''' метода с модификатором <code>final</code> метод не может быть скрыт (hide) методом дочернего класса при наследовании. | |||
# [[Листовой класс|Финальный '''класс''']] не может иметь наследников. | |||
==== | ==== Абстрактность ==== | ||
В Java методы, не объявленные явно как <code>static</code>, <code>final</code> или <code>private</code>, являются [[Виртуальный метод|виртуальными]] в терминологии C++: при вызове метода, по-разному определённого в базовом и наследующем классах, всегда производится проверка времени выполнения. | |||
[[Абстрактный метод|Абстрактным методом]] (модификатор <code>abstract</code>) в Java называется метод, для которого заданы параметры и тип возвращаемого значения, но не задано тело. Абстрактный метод определяется в классах-наследниках. Аналог абстрактного метода в C++ — чисто виртуальная функция (pure virtual function). Для того чтобы в классе можно было описывать абстрактные методы, сам класс тоже должен быть описан как абстрактный. Объекты абстрактного класса создавать нельзя. | |||
| | |||
=== | ==== Интерфейсы ==== | ||
Высшей степенью абстрактности в Java является интерфейс (модификатор <code>interface</code>). Интерфейс содержит преимущественно абстрактные методы, имеющие всеобщий уровень доступа: описатели <code>abstract</code> и <code>public</code> для них даже не требуются. Однако с версий Java 8 и 9 были введены возможности использования в интерфейсах | |||
— Java 8: статических (<code>static</code>) методов и методов по умолчанию (<code>default</code>); | |||
— Java 9: методов, имеющих уровень доступа <code>private</code>. | |||
Эти методы содержат тело, а значит абстрактными не являются, но в конкретной реализации интерфейса <code>default</code>-методы могут быть переопределены. | |||
Интерфейс в Java не считается классом, хотя, по сути, является полностью абстрактным классом. | |||
Класс может наследовать/''расширять'' (<code>extends</code>) другой класс или ''реализовывать'' (<code>implements</code>) интерфейс. Интерфейсы же могут наследовать/расширять другие интерфейсы. В Java класс не может наследовать более одного класса, зато может реализовывать несколько интерфейсов. Множественное наследование интерфейсов не запрещено — один интерфейс может наследоваться от нескольких. | |||
С версии Java 15 (экспериментально, официально — с версии Java 17) добавлена возможность использования запечатанных (<code>sealed</code>) классов/интерфейсов, при объявлении которых, с помощью ключевого слова <code>permits</code>, можно указывать, какие классы/интерфейсы могут наследовать данный запечатанный класс/интерфейс. | |||
Интерфейсы можно использовать в качестве типов параметров методов. Нельзя создавать экземпляры интерфейсов. | |||
=== | ===== Маркерные интерфейсы ===== | ||
В Java есть интерфейсы, которые не содержат методов для реализации, а специальным образом обрабатываются JVM: <code>Cloneable</code>, <code>Serializable</code>, <code>RandomAccess</code>, <code>Remote</code>. | |||
=== | ==== Шаблоны в Java (generics) ==== | ||
{{anchor|generics}} | |||
Начиная с версии Java 5.0 в языке появился механизм [[обобщённое программирование|обобщённого программирования]] — шаблоны, внешне близкие к шаблонам C++. С помощью специального синтаксиса в описании классов и методов можно указать параметры-типы, которые внутри описания могут использоваться в качестве типов полей, параметров и возвращаемых значений методов. | |||
== | <source lang="java" line="1"> | ||
// Объявление обобщённого класса | |||
class GenericClass<E> { | |||
E getFirst() { ... } | |||
void add(E obj) { ... } | |||
} | |||
== | // Использование обобщённого класса в коде | ||
GenericClass<String> obj = new GenericClass<>(); | |||
obj.add("qwerty"); | |||
String p = obj.getFirst(); | |||
</source> | |||
Допускается обобщённое объявление классов, интерфейсов и методов. Кроме того, синтаксис поддерживает ограниченные объявления типов-параметров: указание в объявлении конструкции вида <code><T extends A & B & C...></code> требует, чтобы тип-параметр T реализовывал интерфейсы A, B, C и так далее. | |||
В отличие от шаблонов C#, шаблоны Java не поддерживаются средой исполнения — компилятор просто создаёт байт-код, в котором никаких шаблонов уже нет. Реализация шаблонов в Java принципиально отличается от реализации аналогичных механизмов в C++: компилятор не порождает для каждого случая использования шаблона отдельный вариант класса или метода-шаблона, а просто создаёт одну реализацию байт-кода, содержащую необходимые проверки и преобразования типов. Это приводит к ряду ограничений использования шаблонов в программах на Java. | |||
# | |||
==== | ==== Проверка принадлежности к классу ==== | ||
В Java можно явно проверить, к какому классу принадлежит объект. Выражение <code>foo instanceof Foo</code> равно <code>true</code>, если объект <code>foo</code> принадлежит классу <code>Foo</code> или его наследнику, или реализует интерфейс <code>Foo</code> (или, в общем виде, наследует класс, который реализует интерфейс, который наследует <code>Foo</code>). | |||
= | Далее функция <code>getClass()</code><ref group="док.">{{Javadoc:SE|name=getClass()|java.base/java/lang|Object|getClass()}}</ref>, определённая для всех объектов, выдаёт объект типа <code>Class<?></code>. Для каждого класса создаётся не более одного описывающего его объекта типа <code>Class</code>, поэтому эти объекты можно сравнивать. Так, например, <code>foo.getClass() == bar.getClass()</code> будет истинно, если объекты <code>foo</code> и <code>bar</code> принадлежат к одному классу. | ||
{{ | |||
| | |||
| | |||
| | |||
| | |||
Кроме того, объект типа <code>Class<?></code> любого типа можно получить так: <code>Integer.class</code>, <code>Object.class</code>. | |||
Прямое сравнение классов не всегда является оптимальным средством проверки на принадлежность к классу. Зачастую вместо него используют функцию <code>isAssignableFrom()</code>. Эта функция определена у объекта типа <code>Class</code> и принимает объект типа <code>Class<?></code> в качестве параметра. Таким образом, вызов <code>Foo.class.isAssignableFrom(Bar.class)</code> вернёт <code>true</code> в случае, если <code>Foo</code> является предком класса <code>Bar</code>. Так как все объекты являются потомками типа <code>Object</code>, вызов <code>Object.class.isAssignableFrom()</code> всегда вернёт <code>true</code>. | |||
== | В паре с упомянутыми функциями объекта типа <code>Class</code> используются также функции <code>isInstance</code><ref group="док.">{{Javadoc:SE|name=isInstance()|java.base/java/lang|Class|isInstance(java.lang.Object)}}</ref> (эквивалентно <code>instanceof</code>), а также <code>cast()</code> (преобразует параметр в объект выбранного класса). | ||
=== Обработка ошибок === | |||
Обработка ошибок в Java похожа на обработку ошибок в [[C++]] за исключением необходимости в блоке <code>finally</code>. Данное отличие обусловлено тем, что Java не может придерживаться концепции [[Получение ресурса есть инициализация|RAII]] из-за наличия сборщика мусора, а автоматическое освобождение ресурсов в деструкторе может идти в непредсказуемом порядке через произвольные промежутки времени. | |||
Осуществляется обработка ошибок с помощью операторов <code>try</code>, <code>catch</code> и <code>finally</code>. Выбрасываемая ошибка описывается объектом определённого класса, наследующегося от <code>Throwable</code><ref group="док.">{{Javadoc:SE|java.base/java/lang|Throwable}}</ref> и соответствующего типу ошибки. Внутрь блока <code>try</code> помещается код, который может выбросить исключение, а блок <code>catch</code> отлавливает заданные программистом типы ошибок. При этом можно указывать более одного блока <code>catch</code> для обработки различных классов ошибок, или multi-catch для обработки нескольких ошибок. Блок <code>finally</code> является необязательным, но при наличии выполняется независимо от возникновения ошибки и предназначен для освобождения выделенных в ходе работы блока <code>try</code> ресурсов. | |||
{{ | |||
= {{ | Начиная с Java 7 поддерживается интерфейс <code>AutoCloseable</code><ref group="док.">{{Javadoc:SE|java.base/java/lang|AutoCloseable}}</ref>, который позволяет реализовывать классы, автоматически освобождающие ресурсы. Объекты подобных классов требуется создавать в круглых скобках перед блоком <code>try</code>. Простым примером автоматического освобождения ресурсом может служить чтение содержимого файла: | ||
<syntaxhighlight lang="java" line="1"> | |||
import java.io.*; | |||
=== | public class Main { | ||
{{ | public static void main(String[] args) throws IOException { | ||
if (args.length < 2) { | |||
System.err.println("Не указано имя файла."); | |||
} | return; | ||
} | |||
String filename = args[1]; | |||
// Открытый файл будет автоматически закрыт по ошибке | |||
try (BufferedReader reader = new BufferedReader(new FileReader(filename))) { | |||
String line; | |||
for (int n = 1; (line = reader.readLine()) != null; ++n) { | |||
System.out.println(n + ": " + line); | |||
} | |||
} catch (FileNotFoundException e) { | |||
System.err.println("Указанный файл не найден."); | |||
} | |||
// finally { | |||
// reader.close(); // автоматическое закрытие ресурса | |||
// } | |||
} | |||
} | |||
</syntaxhighlight> | |||
{{ | Java придерживается концепции обязательного указания классов ошибок, которые может выбросить метод. Делается это с помощью ключевого слова <code>throws</code> после описания метода. Если в методе не указать класс исключения (или его предка), которое может быть выброшено из метода, то это вызовет ошибку компиляции. Концепция должна была позволить делать код самодокументируемым, обозначая, какие исключения может выбросить тот или иной метод, но на практике редко себя оправдывает, поскольку в силу разных обстоятельств программист может указать в качестве выбрасываемого исключения класс <code>Exception</code> либо заключить проблемные части метода в блок <code>try</code>...<code>catch</code> для игнорирования отдельных ошибок, либо — в блок <code>try</code>...<code>finally</code>, скрывая все возможные ошибки. Недостатком концепции также является и то, что программист сам должен определять и прописывать исключения, которые может выбрасывать метод<ref>{{Cite web|url=https://www.artima.com/intv/handcuffs.html|title=The Trouble with Checked Exceptions|publisher=www.artima.com|access-date=2018-12-21|archive-date=2019-01-08|archive-url=https://web.archive.org/web/20190108114501/https://www.artima.com/intv/handcuffs.html|url-status=live}}</ref>. | ||
=== | === Пространство имён === | ||
{{ | {{main|Пространство имён (программирование)}} | ||
Идея пространств имён воплощена в [[Package (Java)|Java-пакетах]]. | |||
Название Java-пакета создаётся [[латинский алфавит|латиницей]] (используется нижний и верхний регистр) с [[цифры|цифрами]] (они не должны быть первыми в строке) и знаком подчёркивания (он не должен быть первым и последним в строке), не являющейся инструкциями языка (например, <code>if</code>, <code>null</code>), разделённой точками. | |||
Правильные примеры названий: | |||
* <code>project.types.net.media</code> | |||
* <code>a0.a_b.canrepeat.canrepeat.UPPERCASE.RaNdOmCaSe</code> (хотя нежелательно, из-за нечитабельности) | |||
Неправильные примеры названий: | |||
* <code>doubledots..something</code> (две точки подряд) | |||
* <code>нестандартный.язык</code> (не латиница) | |||
* <code>0first.characret.is.number</code> (число в начале) | |||
* <code>contains.white space</code> (пробел вместо точки) | |||
* <code>true.asd</code> (содержит <code>true</code>, см. выше) | |||
Пакеты содержат классы, интерфейсы, перечисления, аннотации (и т. д.), имена которых тоже создаются латиницей (используется нижний и верхний регистр) с цифрами (они не должны стоять первыми в строке). Публичный класс, интерфейс (и т. д.) в одном файле может быть только один. Имя публичного класса, интерфейса (и т. д.) в файле должно совпадать с названием файла. Каждый класс имеет своё пространство имён для функций, переменных и подклассов, подинтерфейсов (и т. д.), причём получить подкласс класса можно с помощью <code>OuterClass.InnerClass</code>, а можно — с помощью <code>OuterClass$InnerClass</code>, поэтому использование символа доллара в названии класса не рекомендуется. | |||
== | == Примеры программ == | ||
Код программы «[[Hello, world!]]». | |||
<source lang="java" line="1"> | |||
class HelloWorld { | |||
public static void main(String[] args) { | |||
System.out.println("Hello, world!"); | |||
} | |||
} | |||
</source> | |||
=== | [[обобщённое программирование|Обобщения]]: | ||
{{Hider hiding | |||
|title=Пример использования обобщений | |||
|content= | |||
<source lang="java"> | |||
import java.util.List; | |||
import java.util.ArrayList; | |||
= | public class Sample { | ||
public static void main(String[] args) { | |||
// Создание объекта по шаблону. | |||
List<String> strings = new ArrayList<>(); | |||
strings.add("Hello"); | |||
strings.add("world"); | |||
strings.add("!"); | |||
for (var string : strings) { | |||
System.out.print(string + " "); | |||
} | |||
} | |||
} | |||
</source> | |||
}} | |||
=== | [[Отражение (программирование)|Рефлексия]]: | ||
{{Hider hiding | |||
|title=Пример использования рефлексии | |||
|content= | |||
<source lang="java"> | |||
import java.lang.reflect.Field; | |||
import java.lang.reflect.Method; | |||
{{ | class TestClass { | ||
private int value; | |||
public int getValue() { return value; } | |||
public void setValue(int valueIn) { this.value = valueIn; } | |||
} | |||
{{ | public class Main { | ||
public static void main(String[] args) { | |||
var testClass = new TestClass(); | |||
for (var field: testClass.getClass().getDeclaredFields()) { | |||
System.out.printf("name:%s, type:%s \n", field.getName(), field.getType().getCanonicalName()); | |||
} | |||
for (var method : testClass.getClass().getDeclaredMethods()) { | |||
System.out.printf("name:%s, return type:%s \n", method.getName(), method.getReturnType().getCanonicalName()); | |||
} | |||
} | |||
} | |||
</source> | |||
}} | }} | ||
{{ | [[Аннотация (Java)|Аннотации]]: | ||
{{Hider hiding | |||
|title=Пример использования аннотаций | |||
|content= | |||
<source lang="java"> | |||
import java.lang.annotation.ElementType; | |||
import java.lang.annotation.Retention; | |||
import java.lang.annotation.RetentionPolicy; | |||
import java.lang.annotation.Target; | |||
@Retention(RetentionPolicy.RUNTIME) | |||
{ | @Target(ElementType.TYPE) | ||
public @interface MyAnnotation { | |||
public boolean value() default false; | |||
} | |||
= | @MyAnnotation(value=true) | ||
public class TestClass { | |||
} | |||
public class Main { | |||
public static void main(String[] args) { | |||
var testClass = new TestClass(); | |||
== | var myAnnotation = testClass.getClass().getAnnotation(MyAnnotation.class); | ||
if (myAnnotation != null) { | |||
System.out.printf("value:%s \n", myAnnotation.value()); | |||
} | |||
} | |||
} | |||
</source> | |||
}} | }} | ||
=== | == Средства разработки ПО == | ||
* [[JDK]] — помимо набора библиотек для платформ [[Java SE]] и [[Java EE]], содержит компилятор командной строки javac и набор утилит, так же работающих в режиме командной строки. | |||
* [[NetBeans IDE]] — свободная интегрированная среда разработки для всех платформ Java — [[Java ME]], [[Java SE]] и [[Java EE]]. Пропагандируется [[Oracle]], владельцем технологии Java, как базовое средство для разработки ПО на языке Java и других языках ([[Си (язык программирования)|C]], [[C++]], [[PHP]], [[Fortran]] и др.). | |||
* [[Eclipse (среда разработки)|Eclipse IDE]] — свободная интегрированная среда разработки для [[Java SE]], [[Java EE]] и [[Java ME]]<ref>{{cite web | |||
|url = http://www.eclipse.org/pulsar/ | |||
|title = Pulsar - Eclipse Mobile Tools Platform | |||
|publisher = Eclipse | |||
|access-date = 2011-03-23 | |||
|lang = en | |||
|description = Проект eclipse для мобильных разработчиков | |||
|archive-url = https://www.webcitation.org/6170xVuSz?url=http://www.eclipse.org/pulsar/ | |||
|archive-date = 2011-08-21 | |||
}}</ref>. Пропагандируется [[IBM]], одним из важнейших разработчиков корпоративного ПО, как базовое средство для разработки ПО на языке Java и других языках ([[Си (язык программирования)|C]], [[C++]], [[Ruby]], [[Fortran]] и др.). | |||
* [[IntelliJ IDEA]] — среда разработки для платформ [[Java SE]], [[Java EE]] и [[Java ME]]. Разработчик — компания [[JetBrains]]. Распространяется в двух версиях: свободной бесплатной (Community Edition) и коммерческой проприетарной (Ultimate Edition). | |||
* [[JDeveloper]] — среда разработки для платформ [[Java SE]], [[Java EE]] и [[Java ME]]. Разработчик — компания [[Oracle]]. | |||
* [[BlueJ]] — среда разработки программного обеспечения на языке Java, созданная в основном для использования в обучении, но также подходящая для разработки небольших программ. | |||
* [[Geany]] — [[свободное программное обеспечение|свободная]] [[среда разработки программного обеспечения]], написанная с использованием [[Библиотека времени исполнения|библиотеки]] [[GTK2]]. | |||
== См. также == | |||
{{навигация| | |||
Викисловарь = Java}} | |||
* [[Сравнение C Sharp и Java|Сравнение C# и Java]] | |||
* [[Список Java API]] | |||
* [[Java User Group]]s | |||
== Примечания == | |||
=== Комментарии === | |||
{{примечания|group="прим."}} | |||
=== Документация === | |||
{{примечания|group="док."}} | |||
=== | === Источники === | ||
{{примечания|3}} | |||
=== | == Литература == | ||
* | * {{книга | ||
|заглавие = Java. Полное руководство, 10-е издание | |||
|оригинал = Java. The Complete Reference, 10th Edition | |||
|автор = Герберт Шилдт | |||
|страниц = 1488 | |||
|isbn = 978-5-6040043-6-4 | |||
|год = 2018 | |||
|место = М. | |||
|издательство = [[Диалектика (издательство)|«Диалектика»]] | |||
}} | |||
* {{книга | |||
|заглавие = Java SE 9. Базовый курс | |||
|оригинал = Core Java SE 9 for the Impatient | |||
|автор = Кей С. Хорстманн | |||
|страниц = 576 | |||
|isbn = 978-5-6040043-0-2, 978-0-13-469472-6 | |||
|год = 2018 | |||
|место = М. | |||
|издательство = [[Вильямс (издательство)|«Вильямс»]] | |||
}} | |||
* {{книга | |||
|заглавие = Java SE 8. Вводный курс | |||
|оригинал = Java SE 8 for the Really Impatient | |||
|автор = Кей С. Хорстманн | |||
|страниц = 208 | |||
|isbn = 978-5-8459-1900-7 | |||
|год = 2014 | |||
|место = М. | |||
|издательство = [[Вильямс (издательство)|«Вильямс»]] | |||
}} | |||
* {{книга | |||
|заглавие = Руководство для программиста на Java: 75 рекомендаций по написанию надёжных и защищённых программ | |||
|оригинал = Java Coding Guidelines: 75 Recommendations for Reliable and Secure Programs | |||
|автор = Фрэд Лонг, Дхрув Мохиндра, Роберт С. Сикорд, Дин Ф. Сазерленд, Дэвид Свобода | |||
|страниц = 256 | |||
|isbn = 978-5-8459-1897-0 | |||
|год = 2014 | |||
|место = М. | |||
|издательство = [[Вильямс (издательство)|«Вильямс»]] | |||
}} | |||
* {{книга | |||
|заглавие = Java. Библиотека профессионала, том 1. Основы. 10-е издание | |||
|оригинал = Core Java. Volume I - Fundamentals (Tenth Edition) | |||
|автор = Кей С. Хорстманн | |||
|страниц = 864 | |||
|isbn = 978-5-8459-2084-3 | |||
|год = 2017 | |||
|место = М. | |||
|издательство = [[Вильямс (издательство)|«Вильямс»]] | |||
}} | |||
* {{книга | |||
|заглавие = Java. Библиотека профессионала, том 2. Расширенные средства программирования. 10-е издание | |||
|оригинал = Core Java. Volume II - Advanced Feature (Tenth Edition) | |||
|автор = Кей С. Хорстманн | |||
|страниц = 976 | |||
|isbn = 978-5-9909445-0-3 | |||
|год = 2017 | |||
|место = М. | |||
|издательство = [[Вильямс (издательство)|«Вильямс»]] | |||
}} | |||
* {{книга | |||
|заглавие = Java 9 для чайников | |||
|оригинал = Java For Dummies, 7th edition | |||
|автор = Барри Берд | |||
|страниц = 624 | |||
|isbn = 978-5-9500296-1-5, 978-1-119-23555-2 | |||
|год = 2018 | |||
|место = М. | |||
|издательство = [[Диалектика (издательство)|«Диалектика»]] | |||
}} | |||
* {{книга | |||
|заглавие = Java 9. Полный обзор нововведений | |||
|оригинал = Java 9 Revealed | |||
|автор = Кишори Шаран | |||
|страниц = 544 | |||
|isbn = 978-5-97060-575-2 | |||
|год = 2018 | |||
|место = М. | |||
|издательство = [[ДМК Пресс (издательство)|«ДМК Пресс»]] | |||
}} | |||
* {{книга | |||
|заглавие = Язык программирования Java SE 8. Подробное описание, 5-е издание | |||
|оригинал = The Java Language Specification, Java SE 8 Edition (5th Edition) (Java Series) | |||
|автор = Джеймс Гослинг, Билл Джой, Гай Стил, Гилад Брача, Алекс Бакли | |||
|страниц = 672 | |||
|isbn = 978-5-8459-1875-8 | |||
|год = 2015 | |||
|место = М. | |||
|издательство = [[Вильямс (издательство)|«Вильямс»]] | |||
}} | |||
* {{книга | |||
|автор = Джошуа Блох. | |||
|заглавие = Java. Эффективное программирование | |||
|оригинал = Effective Java | |||
|издание=3-е | |||
|место = М. | |||
|издательство = [[Диалектика (издательство)|Диалектика]] | |||
|год = 2019 | |||
|страниц = 464 | |||
|isbn = 978-5-6041394-4-8 | |||
}} | |||
* {{книга | |||
|автор = Бенджамин Дж. Эванс, Джеймс Гоф, Крис Ньюленд | |||
|заглавие = Java: оптимизация программ. Практические методы повышения производительности приложений в JVM | |||
|оригинал = | |||
|издание= | |||
|место = М. | |||
|издательство = [[Диалектика (издательство)|Диалектика]] | |||
|год = 2019 | |||
|страниц = 448 | |||
|isbn = 978-5-907114-84-5 | |||
}} | |||
* {{книга | |||
|автор = Монахов Вадим. | |||
|заглавие = Язык программирования Java и среда NetBeans | |||
|ссылка = | |||
|издание = 3-е изд | |||
|место = СПб. | |||
|издательство = [[БХВ-Петербург]] | |||
|год = 2011 | |||
|страниц = 704 | |||
|isbn = 978-5-9775-0671-7 | |||
}} | |||
* {{книга | |||
|автор = Брюс Эккель. | |||
|заглавие = Философия Java | |||
|оригинал = Thinking in Java | |||
|издание = 4-е изд | |||
|место = СПб. | |||
|издательство = [[Питер (издательство)|Питер]] | |||
|год = 2018 | |||
|страниц = 1168 | |||
|isbn = 978-5-496-01127-3 | |||
}} | |||
== Ссылки == | |||
* [https://www.java.com/ru/ Официальный сайт Java] | |||
* [https://docs.oracle.com/en/java/javase/ Официальная документация Java] | |||
* [https://docs.oracle.com/javase/specs/index.html Спецификация языка и JVM] | |||
{{ | {{Внешние ссылки}} | ||
{{ | {{Java}} | ||
[[Категория:Java| ]] | |||
[[Категория:Языки веб-программирования]] | |||
[[Категория:Языки программирования с автоматическим управлением памятью]] | |||
Текущая версия от 11:19, 22 марта 2026
Шаблон:О Шаблон:Не путать Шаблон:Карточка языка программирования Java<ref group="прим.">Произносится на английском как {{#if: | /ˈdʒɑːvə/ | /ˈdʒɑːvə/ }}, «Джава». В русском языке помимо «Джава» встречается транслитерация «Ява», но правообладатели торговой марки предпочитают первую транслитерацию.</ref> — строго типизированный объектно-ориентированный язык программирования общего назначения, разработанный компанией Sun Microsystems (в последующем приобретённой компанией Oracle). Разработка ведётся сообществом, организованным через Java Community Process; язык и основные реализующие его технологии распространяются по лицензии GPL. Права на торговую марку принадлежат корпорации Oracle.
Приложения Java обычно транслируются в специальный байт-код, поэтому они могут работать на любой компьютерной архитектуре, для которой существует реализация виртуальной Java-машины. Дата официального выпуска — 23 мая 1995 года. Java занимает высокие места в рейтингах популярности языков программирования (2-е место в рейтингах IEEE Spectrum (2020)<ref>Шаблон:Cite news</ref> и TIOBE (2021<ref>Шаблон:Cite web</ref>)).
История создания

Изначально язык назывался Oak («Дуб»), разрабатывался Джеймсом Гослингом для программирования бытовых электронных устройств. Из-за того, что язык с таким названием уже существовал, Oak был переименован в Java<ref>Шаблон:Книга</ref>. Назван в честь марки кофе Java, которая, в свою очередь, получила наименование одноимённого острова (Ява), поэтому на официальной эмблеме языка изображена чашка с горячим кофе. Существует и другая версия происхождения названия языка, связанная с аллюзией на кофемашину как пример бытового устройства, для программирования которого изначально язык создавался. В соответствии с этимологией в русскоязычной литературе с конца двадцатого и до первых лет двадцать первого века название языка нередко переводилось как Ява, а не транскрибировалось.
В результате работы проекта мир увидел принципиально новое устройство, карманный персональный компьютер Star7<ref>Шаблон:Cite web</ref>, который опередил своё время более чем на 10 лет, но из-за большой стоимости в 50 долларов не смог произвести переворот в мире технологии и был забыт.
Устройство Star7 не пользовалось популярностью, в отличие от языка программирования Java и его окружения. Следующим этапом жизни языка стала разработка интерактивного телевидения. Однако в 1994 году стало очевидным, что интерактивное телевидение было ошибкой.
С середины 1990-х годов язык стал широко использоваться для написания клиентских приложений и серверного программного обеспечения. Тогда же определённое распространение получила технология Java-апплетов — графических Java-приложений, встраиваемых в веб-страницы; с развитием возможностей динамических веб-страниц в 2000-е годы технология стала применяться редко.
В веб-разработке применяется Spring Framework; для документирования используется утилита Javadoc.
Основные особенности языка
Программы на Java транслируются в байт-код Java, выполняемый виртуальной машиной Java (JVM) — программой, обрабатывающей байтовый код и передающей инструкции оборудованию как интерпретатор.

Достоинством подобного способа выполнения программ является полная независимость байт-кода от операционной системы и оборудования, что позволяет выполнять Java-приложения на любом устройстве, для которого существует соответствующая виртуальная машина. Другой важной особенностью технологии Java является гибкая система безопасности, в рамках которой исполнение программы полностью контролируется виртуальной машиной. Любые операции, которые превышают установленные полномочия программы (например, попытка несанкционированного доступа к данным или соединения с другим компьютером), вызывают немедленное прерывание.
Часто к недостаткам концепции виртуальной машины относят снижение производительности. Ряд усовершенствований немного увеличил скорость выполнения программ на Java:
- применение технологии трансляции байт-кода в машинный код непосредственно во время работы программы (JIT-технология) с возможностью сохранения версий класса в машинном коде,
- обширное использование платформенно-ориентированного кода (native-код) в стандартных библиотеках,
- аппаратные средства, обеспечивающие ускоренную обработку байт-кода (например, технология Jazelle, поддерживаемая некоторыми процессорами архитектуры ARM).
По данным сайта shootout.alioth.debian.org, для семи разных задач время выполнения на Java составляет в среднем в полтора-два раза больше, чем для C/C++, но при этом в некоторых случаях Java быстрее, а в отдельных случаях в 7 раз медленнее<ref name="slow_java">Шаблон:Cite web</ref>. С другой стороны, для большинства из них потребление памяти Java-машиной было в 10—30 раз больше, чем программой на C/C++. Также примечательно исследование, проведённое компанией Google, согласно которому отмечается существенно более низкая производительность и бо́льшее потребление памяти в тестовых примерах на Java в сравнении с аналогичными программами на C++<ref>Шаблон:Cite web</ref><ref>Loop Recognition in C++/Java/Go/ScalaШаблон:Refsize Шаблон:Wayback</ref><ref>Шаблон:Cite web</ref>.
Идеи, заложенные в концепцию и различные реализации среды виртуальной машины Java, вдохновили множество энтузиастов на расширение перечня языков, которые могли бы быть использованы для создания программ, исполняемых на виртуальной машине<ref>Шаблон:Cite web</ref>. Эти идеи нашли также выражение в спецификации общеязыковой инфраструктуры CLI, заложенной в основу платформы .NET компанией Microsoft.
Классификация платформ Java
Внутри Java существует несколько основных семейств технологий:
- Java SE — Java Standard Edition — основное издание Java. Содержит компиляторы, API, Java Runtime Environment; подходит для создания пользовательских приложений, в первую очередь — для настольных систем.
- Jakarta EE (ранее — Java EE (Enterprise Edition)) представляет собой набор спецификаций для создания ПО уровня предприятия. В 2017-м проект Java EE был передан Eclipse Foundation, и тогда же его наименование изменилось на текущее<ref>Шаблон:Cite news</ref><ref>Шаблон:Cite news</ref>. Модули Java EE удалены из Java SE с 11-й версии<ref>Шаблон:Cite web</ref>.
- Java ME — Java Micro Edition, создана для использования в устройствах, ограниченных по вычислительной мощности, например, в мобильных телефонах, КПК, встроенных системах;
- Java Card — технология предоставляет безопасную среду для приложений, работающих на смарт-картах и других устройствах с очень ограниченным объёмом памяти и возможностями обработки.
Java и Microsoft
Компанией Microsoft была разработана собственная реализация JVM под названием Шаблон:Не переведено 3 (MSJVM)<ref name="msjvm" />, включавшаяся в состав различных операционных систем, начиная с Windows 98 (также входила в Internet Explorer от версии 3 и выше, что позволяло использовать MSJVM в ОС Windows 95 и Windows NT 4 после установки IE3+ на данные ОС).
MSJVM имела существенные отличия от Sun Java, во многом ломающие основополагающую концепцию переносимости программ между разными платформами:
- отсутствие поддержки программного интерфейса вызова удалённых методов (RMI);
- отсутствие поддержки технологии JNI;
- наличие нестандартных расширений, таких, как средства интеграции Java и DCOM, работающих только на платформе Windows.
Тесная интеграция Java с DCOM и Win32 поставила под вопрос кроссплатформенную парадигму языка. Впоследствии это явилось поводом для судебных исков со стороны Sun Microsystems к Microsoft. Суд принял сторону компании Sun Microsystems. В конечном счёте между двумя компаниями была достигнута договорённость о возможности продления срока официальной поддержки пользователей нестандартной Microsoft JVM до конца 2007 года<ref name=msjvm>Шаблон:Cite web</ref>.
В 2005 году компанией Microsoft для платформы .NET был представлен Java-подобный язык J#, не соответствующий официальной спецификации языка Java и исключённый впоследствии из стандартного инструментария разработчика Microsoft Visual Studio, начиная с Visual Studio 2008<ref>Шаблон:Cite web</ref>.
Java и Android
Язык Java активно используется для создания мобильных приложений под операционную систему Android. При этом программы компилируются в нестандартный байт-код для использования их виртуальной машиной Dalvik (начиная с Android 5.0 Lollipop виртуальная машина заменена на ART). Для такой компиляции используется дополнительный инструмент, а именно Android SDK (Software Development Kit), разработанный компанией Google.
Разработку приложений можно вести в среде Android Studio, NetBeans, в среде Eclipse.
Применения платформы Java
Следующие успешные проекты реализованы с привлечением Java (J2EE) технологий: RuneScape, Amazon<ref>Шаблон:Cite web</ref><ref>Шаблон:Cite web</ref>, eBay<ref>Шаблон:Cite web</ref><ref>Шаблон:Cite web</ref>, LinkedIn<ref>Шаблон:Cite web</ref>, Yahoo!<ref>Шаблон:Cite web</ref>.
Следующие компании в основном фокусируются на Java- (J2EE-) технологиях: SAP, IBM, Oracle. В частности, СУБД Oracle Database включает JVM как свою составную часть, обеспечивающую возможность непосредственного программирования СУБД на языке Java, включая, например, хранимые процедуры<ref>Шаблон:Cite web</ref>.
Также существует Java библиотека классов для сериализации объектов в XML (или JSON) формат — XStream.
Производительность
Программы, написанные на Java, имеют репутацию более медленных и занимающих больше оперативной памяти, чем написанные на языке C<ref name="slow_java"/>. Тем не менее, скорость выполнения программ, написанных на языке Java, была существенно улучшена с выпуском в 1997—1998 годах JIT-компилятора в версии 1.1 в дополнение к другим особенностям языка для поддержки лучшего анализа кода (такие, как внутренние классы, класс StringBuffer<ref group="док.">Шаблон:Javadoc:SE</ref>, упрощённые логические вычисления и так далее). Кроме того, была произведена оптимизация виртуальной машины Java — с 2000 года для этого используется виртуальная машина HotSpot. По состоянию на февраль 2012 года код Java 7 приблизительно в 1,8 раза медленнее кода, написанного на языке Си<ref>Шаблон:Cite web</ref>.
Некоторые платформы предлагают аппаратную поддержку выполнения для Java<ref>Шаблон:Статья</ref>. К примеру, микроконтроллеры, выполняющие код Java на аппаратном обеспечении вместо программной JVM, а также основанные на ARM процессоры, которые поддерживают выполнение байт-кода Java через опцию Jazelle.
Основные возможности
- Автоматическое управление памятью;
- Расширенные возможности обработки исключительных ситуаций;
- Богатый набор средств фильтрации ввода-вывода;
- Набор стандартных коллекций: массив, список, стек и т.п;
- Наличие простых средств создания сетевых приложений (в том числе — с использованием протокола RMI);
- Наличие классов, позволяющих выполнять HTTP-запросы и обрабатывать ответы;
- Встроенные в язык средства создания многопоточных приложений, которые потом были портированы на многие языки, например, Python;
- Унифицированный доступ к базам данных:
- на уровне отдельных SQL-запросов — на основе JDBC, SQLJ;
- на уровне концепции объектов, обладающих способностью к хранению в базе данных — на основе Шаблон:Нп1 и Java Persistence API;
- Поддержка обобщений (с версии 1.5);
- Поддержка лямбд, замыканий, возможностей функционального программирования (с Java 8).
Основные идеи
Примитивные типы
В языке Java только 8 примитивных (скалярных, простых) типов: boolean, byte, char, short, int, long, float, double. Существует также вспомогательный девятый примитивный тип — void, однако переменные и поля такого типа не могут быть объявлены в коде, а сам тип используется только для описания соответствующего ему класса, для использования при рефлексии: например, с помощью класса Void<ref group="док.">Шаблон:Javadoc:SE</ref> можно узнать, является ли определённый метод типа void: Hello.class.getMethod("main", String[].class).getReturnType() == Void.TYPE.
Длины и диапазоны значений примитивных типов определяются стандартом, а не реализацией, и приведены в таблице. Тип char сделали двухбайтовым для удобства локализации (один из идеологических принципов Java): когда складывался стандарт, уже существовал Unicode-16, но не Unicode-32. Поскольку в результате не осталось однобайтового типа, добавили новый тип byte, причём в Java, в отличие от других языков, он не является беззнаковым. Типы float и double могут иметь специальные значения <math>+\infty</math>, <math>-\infty</math> и «не число» (NaN). Для типа double они обозначаются Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NaN; для типа float — так же, но с приставкой Float вместо Double. Минимальные и максимальные значения, принимаемые типами float и double, тоже стандартизованы.
| Тип | Длина (в байтах) | Диапазон или набор значений |
|---|---|---|
| boolean | 1 в массивах, 4 в переменных<ref>JVM не имеет поддержки для переменных типа boolean, поэтому они представляются в виде значений типа int. Однако массивы boolean[] поддерживаются. VM Spec The Structure of the Java Virtual Machine Шаблон:Wayback</ref> | true, false |
| byte | 1 | −128..127 |
| char | 2 | 0..216−1, или 0..65535 |
| short | 2 | −215..215−1, или −32768..32767 |
| int | 4 | −231..231−1, или −2147483648..2147483647 |
| long | 8 | −263..263−1, или примерно −9.2·1018..9.2·1018 |
| float | 4 | -(2-2−23)·2127..(2-2−23)·2127, или примерно −3.4·1038..3.4·1038, а также <math>-\infty</math>, <math>\infty</math>, NaN |
| double | 8 | -(2-2−52)·21023..(2-2−52)·21023, или примерно −1.8·10308..1.8·10308, а также <math>-\infty</math>, <math>\infty</math>, NaN |
Такая жёсткая стандартизация была необходима, чтобы сделать язык платформенно-независимым, что является одним из идеологических требований к Java. Тем не менее, одна небольшая проблема с платформенной независимостью всё же осталась. Некоторые процессоры используют для промежуточного хранения результатов 10-байтовые регистры или другими способами улучшают точность вычислений. Для того, чтобы сделать Java максимально совместимой между разными системами, в ранних версиях любые способы повышения точности вычислений были запрещены. Однако это приводило к снижению быстродействия. Выяснилось, что ухудшение точности ради платформенной независимости мало кому нужно, тем более если за это приходится платить замедлением работы программ. После многочисленных протестов этот запрет отменили, но добавили ключевое слово strictfp, запрещающее повышение точности. Начиная с Java 17, запрет на повышение точности снова начал действовать, а ключевое слово strictfp было объявлено устаревшим<ref>Шаблон:Cite web</ref>.
Преобразования при математических операциях
В языке Java действуют следующие правила:
- Если один операнд имеет тип
double, другой тоже преобразуется к типуdouble. - Иначе, если один операнд имеет тип
float, другой тоже преобразуется к типуfloat. - Иначе, если один операнд имеет тип
long, другой тоже преобразуется к типуlong. - Иначе оба операнда преобразуются к типу
int.
Данный способ неявного преобразования встроенных типов полностью совпадает с преобразованием типов в Си/C++<ref>Шаблон:Книга</ref>.
Объектные переменные, объекты, ссылки и указатели
В языке Java имеются только динамически создаваемые объекты. Переменные объектного типа и объекты в Java — совершенно разные сущности. Переменные объектного типа являются ссылками, то есть аналогами указателей на динамически создаваемые объекты. Это подчёркивается синтаксисом описания переменных. Так, код на C++ может выглядеть следующим образом: <source lang="java" line="1">double a[10][20]; Foo b(30);</source> Но то же самое на Java будет выглядеть совсем по-другому: <source lang="java" line="1"> double[][] a = new double[10][20]; Foo b = new Foo(30); </source> При присваиваниях, передаче в подпрограммы и сравнениях объектные переменные ведут себя как указатели, то есть присваиваются, копируются и сравниваются адреса объектов. А при доступе с помощью объектной переменной к полям данных или методам объекта не требуется никаких специальных операций разыменовывания — этот доступ осуществляется так, как если бы объектная переменная была самим объектом.
Объектными являются переменные любого типа, кроме примитивного. Явных указателей в Java нет. В отличие от указателей C, C++ и других языков программирования, ссылки в Java в высокой степени безопасны благодаря жёстким ограничениям на их использование.
- Нельзя преобразовывать объект типа
intили любого другого примитивного типа в указатель или ссылку и наоборот. - Над ссылками запрещено выполнять операции
++,−−,+,−или любые другие арифметические и логические операции (&&,||,^^). - Преобразование типов между ссылками жёстко регламентировано. За исключением ссылок на массивы, разрешено преобразовывать ссылки только между наследуемым типом и его наследником, причём преобразование наследуемого типа в наследующий должно быть явно задано, а во время выполнения производится проверка его осмысленности. Преобразования ссылок на массивы разрешены лишь тогда, когда разрешены преобразования их базовых типов, а также нет конфликтов размерности.
- В Java нет операций взятия адреса (
&) или взятия объекта по адресу (*). Амперсанд (&) означает всего лишь «побитовое и» (двойной амперсанд — «логическое и»). Однако для булевых типов одиночный амперсанд означает «логическое и», отличающееся от двойного тем, что цепь проверок не прекращается при получении в выражении значенияfalse<ref>Шаблон:Cite web</ref>. Например,a == b && foo() == bar()не повлечёт вызововfoo()иbar()в случае, еслиa != b, тогда как использование&— повлечёт в любом случае.
Благодаря таким специально введённым ограничениям в Java невозможно прямое манипулирование памятью на уровне физических адресов (хотя определено значение ссылки, не указывающей ни на что: null).
Если нужен указатель на примитивный тип, используются классы-обёртки примитивных типов: Boolean, Byte, Character, Short, Integer, Long, Float, Double.
Дублирование ссылок и клонирование
При присваивании не происходит копирования объекта, так как объектные переменные — ссылочные. Так, если написать
<source lang="java" line="1">
Foo foo, bar;
. . .
bar = foo;
</source>
то произойдёт копирование адреса из переменной foo в переменную bar. То есть foo и bar будут указывать на одну и ту же область памяти, то есть на один и тот же объект; попытка изменить поля объекта, на который ссылается переменная foo, будет менять объект, с которым связана переменная bar, и наоборот. Если же необходимо получить именно ещё одну копию исходного объекта, пользуются или методом (функцией-членом, в терминологии C++) clone(), создающим копию объекта, или (реже) копирующим конструктором (конструкторы в Java не могут быть виртуальными, поэтому экземпляр класса-потомка будет неправильно скопирован конструктором класса-предка; метод клонирования вызывает нужный конструктор и тем самым позволяет обойти это ограничение).
Метод clone()<ref group="док.">Шаблон:Javadoc:SE</ref> требует, чтобы класс реализовывал интерфейс Cloneable<ref group="док.">Шаблон:Javadoc:SE</ref>. Если класс реализует интерфейс Cloneable, по умолчанию clone() копирует все поля (мелкая копия). Если требуется не копировать, а клонировать поля (а также их поля и так далее), надо переопределять метод clone(). Определение и использование метода clone() часто является нетривиальной задачей<ref>Шаблон:Cite web</ref>.
Инициализация переменных
Все переменные или требуют явного определения, или автоматически заполняются нулями (0, null, false). Таким образом, исчезают гейзенбаги, связанные со случайным использованием неинициализированной памяти, характерные для низкоуровневых языков вроде Си.
Сборка мусора
В языке Java невозможно явное удаление объекта из памяти — вместо этого реализована сборка мусора. Традиционным приёмом, дающим сборщику мусора «намёк» на необходимость освобождения памяти, является присваивание переменной значения null, что может оказаться эффективным при необходимости освободить более не требующийся объект, ссылка на который хранится в долгоживущем объекте<ref>Шаблон:Книга</ref>. Это, однако, не значит, что объект, заменённый значением null, будет немедленно удалён, но есть гарантия, что этот объект будет удалён в будущем. Данный приём всего лишь устраняет ссылку на объект, то есть отвязывает указатель от объекта в памяти. При этом следует учитывать, что объект не будет удалён сборщиком мусора, пока на него указывает хотя бы одна ссылка из используемых переменных или объектов. Существуют также методы для инициации принудительной сборки мусора, но не гарантируется, что они будут вызваны исполняющей средой, и их не рекомендуется использовать для обычной работы. Помимо периодических сборок мусора стоит отметить так называемую «общую сборку мусора» (STW, англ. Шаблон:Lang-en2), которая может привести ко временному «подвисанию» исполняемой программы<ref>Шаблон:Cite web</ref>.
В Java используется несколько сборщиков мусора (Serial GC, Parallel GC, G1, ZGC), какой из них используется по умолчанию — зависит от версии IDE. Чтобы выбрать какой-то определённый, нужно запустить JRE с ключом командной строки «-XX:+Use<имя сборщика>GC -jar <имя-jar-файла.jar>», например, вызов «java -XX:+UseG1GC -jar Application.java» приведёт к сборке мусора его сборщиком G1<ref>Шаблон:Cite web</ref>.
Классы и функции
Java не является процедурным языком: любая функция может существовать только внутри класса. Это подчёркивает терминология языка Java, где нет понятий «функция» или «функция-член» (англ. Шаблон:Lang-en2), а только метод. В методы превратились и стандартные функции. Например, в Java нет функции sin(), а есть метод Math.sin() класса Math (содержащего, кроме sin(), методы cos(), exp(), sqrt(), abs() и многие другие).
Как и в языке C, любая исполняемая программа на Java должна иметь точку входа, которой является метод main — он должен/может быть единственным в программе и, в отличие от Си, всегда статическим. При этом, начиная с Java 21, в которой были экспериментально введены безымянные классы, допускается определять этот метод, не определяя имени главного класса.
Конструкторы в Java не считаются методами. Деструкторов в Java не существует, а метод finalize() ни в коем случае нельзя считать аналогом деструктора.
Конструкторы
Конструктор — это специальный метод, который обязательно вызывается при создании нового объекта, то есть объект (экземпляр класса) не может быть создан без вызова конструктора класса. Не всегда удобно инициализировать все переменные класса при создании его экземпляра, поэтому переменные экземпляра часто объявляют внутри тела конструктора, а инициализируют как аргументы конструктора при создании экземпляра класса. Иногда проще, чтобы какие-то значения были бы созданы по умолчанию при создании объекта. В таком случае переменные объявляются и инициализируются внутри тела конструктора.
Конструктор инициализирует объект непосредственно во время создания. Имя конструктора совпадает с именем класса, включая регистр, а по синтаксису конструктор похож на метод без возвращаемого значения.<syntaxhighlight lang="java" line="1"> private int Cat(); // так выглядит метод по имени Cat Cat(); // так выглядит конструктор класса Cat </syntaxhighlight>В отличие от метода, конструктор никогда ничего не возвращает.
Конструктор определяет действия, выполняемые при создании объекта класса, и является важной частью класса. Как правило, программисты стараются явно указать конструктор. Если явного конструктора нет, то Java автоматически создаст его (пустым) для использования по умолчанию.
В качестве примера можно рассмотреть некий класс Box, представляющий собой описание коробки. Конструктор класса просто установит начальные размеры для коробки.<syntaxhighlight lang="java" line="1">
class Box {
int width; // ширина коробки int height; // высота коробки int depth; // глубина коробки
// Конструктор
Box(int a, int b) {
width = a;
height = b;
depth = 10;
}
// вычисляем объём коробки
int getVolume() {
return width * height * depth;
}
} </syntaxhighlight>
Статические методы и поля
В Java (как и в C++) используются статические поля и статические методы (англ. Шаблон:Lang-en2 — в теории программирования их также называют методами класса), которые задаются при помощи ключевого слова static. Статические поля (переменные класса) имеют тот же смысл, что и в C++: каждое такое поле является собственностью класса, поэтому для доступа к статическим полям не требуется создавать экземпляры соответствующего класса.
Например, математические функции, реализованные в классе Math<ref group="док.">Шаблон:Javadoc:SE</ref>, представляют собой как раз статические методы данного класса. Поэтому их можно вызывать напрямую из класса, не создавая его экземпляра, например:
<source lang="java" line="1">double x = Math.sin(1);</source>
Создание экземпляра статического класса запрещают с помощью приватного конструктора. Например, создание экземпляра класса Math приведёт к ошибке на этапе компиляции:
<source lang="java" line="1">Math m = new Math(); // Error: Math() has private access in java.lang.Math
double x = m.sin(1); // Метода sin у объекта не существовало бы, т. к. он статичный</source>
Поскольку статические методы существуют независимо от объектов (экземпляров класса), они не имеют доступа к обычным (не статическим) полям и методам данного класса. В частности, при реализации статического метода недопустимо использовать идентификатор this.
Возможность статического импорта позволяет вызывать статические функции и константы без указания класса. Пример без статического импорта: <source lang="java" line="1"> double x = Math.sin(Math.tan(Math.sqrt(y)) + Math.floor(24.5)) + Math.cos(42 * Math.PI);</source> Тот же пример, но со статическим импортом: <source lang="java" line="1"> import static java.lang.Math.*; ... double x = sin(tan(sqrt(y)) + floor(24.5)) + cos(42 * PI);</source>
Завершённость (final)
Ключевое слово final (финальный) имеет разные значения при описании поля, метода или класса.
- Финальное поле класса инициализируется при описании или в конструкторе класса (а статическое поле — в статическом блоке инициализации). Впоследствии его значение не может быть изменено. Если статическое поле класса или переменная проинициализированы константным выражением, они рассматриваются компилятором как именованная константа; в таком случае их значение может быть использовано в операторах
switch(для констант типовintиString, в том числе — элементов перечислений), а также для условной компиляции (для констант типаboolean) при использовании с операторомif. - Значения локальных переменных, а также параметров метода, помеченных ключевым словом
final, не могут быть изменены после присвоения. При этом их значения могут использоваться внутри анонимных классов. - Метод класса, отмеченный словом
final, не может быть переопределён при наследовании. В случае статического метода с модификаторомfinalметод не может быть скрыт (hide) методом дочернего класса при наследовании. - Финальный класс не может иметь наследников.
Абстрактность
В Java методы, не объявленные явно как static, final или private, являются виртуальными в терминологии C++: при вызове метода, по-разному определённого в базовом и наследующем классах, всегда производится проверка времени выполнения.
Абстрактным методом (модификатор abstract) в Java называется метод, для которого заданы параметры и тип возвращаемого значения, но не задано тело. Абстрактный метод определяется в классах-наследниках. Аналог абстрактного метода в C++ — чисто виртуальная функция (pure virtual function). Для того чтобы в классе можно было описывать абстрактные методы, сам класс тоже должен быть описан как абстрактный. Объекты абстрактного класса создавать нельзя.
Интерфейсы
Высшей степенью абстрактности в Java является интерфейс (модификатор interface). Интерфейс содержит преимущественно абстрактные методы, имеющие всеобщий уровень доступа: описатели abstract и public для них даже не требуются. Однако с версий Java 8 и 9 были введены возможности использования в интерфейсах
— Java 8: статических (static) методов и методов по умолчанию (default);
— Java 9: методов, имеющих уровень доступа private.
Эти методы содержат тело, а значит абстрактными не являются, но в конкретной реализации интерфейса default-методы могут быть переопределены.
Интерфейс в Java не считается классом, хотя, по сути, является полностью абстрактным классом.
Класс может наследовать/расширять (extends) другой класс или реализовывать (implements) интерфейс. Интерфейсы же могут наследовать/расширять другие интерфейсы. В Java класс не может наследовать более одного класса, зато может реализовывать несколько интерфейсов. Множественное наследование интерфейсов не запрещено — один интерфейс может наследоваться от нескольких.
С версии Java 15 (экспериментально, официально — с версии Java 17) добавлена возможность использования запечатанных (sealed) классов/интерфейсов, при объявлении которых, с помощью ключевого слова permits, можно указывать, какие классы/интерфейсы могут наследовать данный запечатанный класс/интерфейс.
Интерфейсы можно использовать в качестве типов параметров методов. Нельзя создавать экземпляры интерфейсов.
Маркерные интерфейсы
В Java есть интерфейсы, которые не содержат методов для реализации, а специальным образом обрабатываются JVM: Cloneable, Serializable, RandomAccess, Remote.
Шаблоны в Java (generics)
Шаблон:Anchor Начиная с версии Java 5.0 в языке появился механизм обобщённого программирования — шаблоны, внешне близкие к шаблонам C++. С помощью специального синтаксиса в описании классов и методов можно указать параметры-типы, которые внутри описания могут использоваться в качестве типов полей, параметров и возвращаемых значений методов.
<source lang="java" line="1"> // Объявление обобщённого класса class GenericClass<E> {
E getFirst() { ... }
void add(E obj) { ... }
}
// Использование обобщённого класса в коде GenericClass<String> obj = new GenericClass<>(); obj.add("qwerty"); String p = obj.getFirst(); </source>
Допускается обобщённое объявление классов, интерфейсов и методов. Кроме того, синтаксис поддерживает ограниченные объявления типов-параметров: указание в объявлении конструкции вида <T extends A & B & C...> требует, чтобы тип-параметр T реализовывал интерфейсы A, B, C и так далее.
В отличие от шаблонов C#, шаблоны Java не поддерживаются средой исполнения — компилятор просто создаёт байт-код, в котором никаких шаблонов уже нет. Реализация шаблонов в Java принципиально отличается от реализации аналогичных механизмов в C++: компилятор не порождает для каждого случая использования шаблона отдельный вариант класса или метода-шаблона, а просто создаёт одну реализацию байт-кода, содержащую необходимые проверки и преобразования типов. Это приводит к ряду ограничений использования шаблонов в программах на Java.
Проверка принадлежности к классу
В Java можно явно проверить, к какому классу принадлежит объект. Выражение foo instanceof Foo равно true, если объект foo принадлежит классу Foo или его наследнику, или реализует интерфейс Foo (или, в общем виде, наследует класс, который реализует интерфейс, который наследует Foo).
Далее функция getClass()<ref group="док.">Шаблон:Javadoc:SE</ref>, определённая для всех объектов, выдаёт объект типа Class<?>. Для каждого класса создаётся не более одного описывающего его объекта типа Class, поэтому эти объекты можно сравнивать. Так, например, foo.getClass() == bar.getClass() будет истинно, если объекты foo и bar принадлежат к одному классу.
Кроме того, объект типа Class<?> любого типа можно получить так: Integer.class, Object.class.
Прямое сравнение классов не всегда является оптимальным средством проверки на принадлежность к классу. Зачастую вместо него используют функцию isAssignableFrom(). Эта функция определена у объекта типа Class и принимает объект типа Class<?> в качестве параметра. Таким образом, вызов Foo.class.isAssignableFrom(Bar.class) вернёт true в случае, если Foo является предком класса Bar. Так как все объекты являются потомками типа Object, вызов Object.class.isAssignableFrom() всегда вернёт true.
В паре с упомянутыми функциями объекта типа Class используются также функции isInstance<ref group="док.">Шаблон:Javadoc:SE</ref> (эквивалентно instanceof), а также cast() (преобразует параметр в объект выбранного класса).
Обработка ошибок
Обработка ошибок в Java похожа на обработку ошибок в C++ за исключением необходимости в блоке finally. Данное отличие обусловлено тем, что Java не может придерживаться концепции RAII из-за наличия сборщика мусора, а автоматическое освобождение ресурсов в деструкторе может идти в непредсказуемом порядке через произвольные промежутки времени.
Осуществляется обработка ошибок с помощью операторов try, catch и finally. Выбрасываемая ошибка описывается объектом определённого класса, наследующегося от Throwable<ref group="док.">Шаблон:Javadoc:SE</ref> и соответствующего типу ошибки. Внутрь блока try помещается код, который может выбросить исключение, а блок catch отлавливает заданные программистом типы ошибок. При этом можно указывать более одного блока catch для обработки различных классов ошибок, или multi-catch для обработки нескольких ошибок. Блок finally является необязательным, но при наличии выполняется независимо от возникновения ошибки и предназначен для освобождения выделенных в ходе работы блока try ресурсов.
Начиная с Java 7 поддерживается интерфейс AutoCloseable<ref group="док.">Шаблон:Javadoc:SE</ref>, который позволяет реализовывать классы, автоматически освобождающие ресурсы. Объекты подобных классов требуется создавать в круглых скобках перед блоком try. Простым примером автоматического освобождения ресурсом может служить чтение содержимого файла:
<syntaxhighlight lang="java" line="1">
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
if (args.length < 2) {
System.err.println("Не указано имя файла.");
return;
}
String filename = args[1];
// Открытый файл будет автоматически закрыт по ошибке
try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
String line;
for (int n = 1; (line = reader.readLine()) != null; ++n) {
System.out.println(n + ": " + line);
}
} catch (FileNotFoundException e) {
System.err.println("Указанный файл не найден.");
}
// finally {
// reader.close(); // автоматическое закрытие ресурса
// }
}
} </syntaxhighlight>
Java придерживается концепции обязательного указания классов ошибок, которые может выбросить метод. Делается это с помощью ключевого слова throws после описания метода. Если в методе не указать класс исключения (или его предка), которое может быть выброшено из метода, то это вызовет ошибку компиляции. Концепция должна была позволить делать код самодокументируемым, обозначая, какие исключения может выбросить тот или иной метод, но на практике редко себя оправдывает, поскольку в силу разных обстоятельств программист может указать в качестве выбрасываемого исключения класс Exception либо заключить проблемные части метода в блок try...catch для игнорирования отдельных ошибок, либо — в блок try...finally, скрывая все возможные ошибки. Недостатком концепции также является и то, что программист сам должен определять и прописывать исключения, которые может выбрасывать метод<ref>Шаблон:Cite web</ref>.
Пространство имён
Шаблон:Main Идея пространств имён воплощена в Java-пакетах.
Название Java-пакета создаётся латиницей (используется нижний и верхний регистр) с цифрами (они не должны быть первыми в строке) и знаком подчёркивания (он не должен быть первым и последним в строке), не являющейся инструкциями языка (например, if, null), разделённой точками.
Правильные примеры названий:
project.types.net.mediaa0.a_b.canrepeat.canrepeat.UPPERCASE.RaNdOmCaSe(хотя нежелательно, из-за нечитабельности)
Неправильные примеры названий:
doubledots..something(две точки подряд)нестандартный.язык(не латиница)0first.characret.is.number(число в начале)contains.white space(пробел вместо точки)true.asd(содержитtrue, см. выше)
Пакеты содержат классы, интерфейсы, перечисления, аннотации (и т. д.), имена которых тоже создаются латиницей (используется нижний и верхний регистр) с цифрами (они не должны стоять первыми в строке). Публичный класс, интерфейс (и т. д.) в одном файле может быть только один. Имя публичного класса, интерфейса (и т. д.) в файле должно совпадать с названием файла. Каждый класс имеет своё пространство имён для функций, переменных и подклассов, подинтерфейсов (и т. д.), причём получить подкласс класса можно с помощью OuterClass.InnerClass, а можно — с помощью OuterClass$InnerClass, поэтому использование символа доллара в названии класса не рекомендуется.
Примеры программ
Код программы «Hello, world!». <source lang="java" line="1"> class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, world!");
}
} </source>
Обобщения: Шаблон:Hider hiding
Рефлексия: Шаблон:Hider hiding
Аннотации: Шаблон:Hider hiding
Средства разработки ПО
- JDK — помимо набора библиотек для платформ Java SE и Java EE, содержит компилятор командной строки javac и набор утилит, так же работающих в режиме командной строки.
- NetBeans IDE — свободная интегрированная среда разработки для всех платформ Java — Java ME, Java SE и Java EE. Пропагандируется Oracle, владельцем технологии Java, как базовое средство для разработки ПО на языке Java и других языках (C, C++, PHP, Fortran и др.).
- Eclipse IDE — свободная интегрированная среда разработки для Java SE, Java EE и Java ME<ref>Шаблон:Cite web</ref>. Пропагандируется IBM, одним из важнейших разработчиков корпоративного ПО, как базовое средство для разработки ПО на языке Java и других языках (C, C++, Ruby, Fortran и др.).
- IntelliJ IDEA — среда разработки для платформ Java SE, Java EE и Java ME. Разработчик — компания JetBrains. Распространяется в двух версиях: свободной бесплатной (Community Edition) и коммерческой проприетарной (Ultimate Edition).
- JDeveloper — среда разработки для платформ Java SE, Java EE и Java ME. Разработчик — компания Oracle.
- BlueJ — среда разработки программного обеспечения на языке Java, созданная в основном для использования в обучении, но также подходящая для разработки небольших программ.
- Geany — свободная среда разработки программного обеспечения, написанная с использованием библиотеки GTK2.
См. также
Примечания
Комментарии
Документация
Источники
Литература
- Шаблон:Книга
- Шаблон:Книга
- Шаблон:Книга
- Шаблон:Книга
- Шаблон:Книга
- Шаблон:Книга
- Шаблон:Книга
- Шаблон:Книга
- Шаблон:Книга
- Шаблон:Книга
- Шаблон:Книга
- Шаблон:Книга
- Шаблон:Книга