Сравнение C Sharp и Java

Сравнение C Sharp и Java

Правильный заголовок этой статьи — Сравнение C# и Java. Он показан некорректно из-за технических ограничений.

В этой статье сравниваются языки программирования C# и Java — два очень похожих между собой современных языка со сборкой мусора и компиляцией при выполнении, произошедшие от языков Си и C++. Настоящая страница даёт обзор сходства и различия этих однотипных языков. Оба языка были тщательно спроектированы, и если в одном из них есть возможность, отсутствующая в другом, то это результат сознательного решения разработчиков. Таким образом, читателю следует избегать искушения «вести счёт» и вместо этого обратить внимание на причины, по которым было сделано то или иное решение.

Содержание

Язык

Объектность

Оба языка — полностью объектно-ориентированные, с синтаксисом, похожим на синтаксис C++. Однако ни один из этих двух языков не является надмножеством C++. Оба они используют сборку мусора, а не явно задаваемое освобождение памяти. Оба включают в свой синтаксис механизмы синхронизации потоков.

И в Джаве, и в C# есть сильные и слабые ссылки на объекты. Джава позволяет зарегистрировать слушатель (listener), который будет получать сообщения, когда ссылка подвергается сборке мусора, что даёт улучшение производительности WeakHashMap, которого нет в C#. Оба языка позволяют выполнять пользовательский код, когда сборке мусора подвергается объект. В С# механизмом этого служит специальный метод-финализатор, выраженный через знакомый синтаксис деструктора C++. В Джаве это достигается переопределением метода finalize, который декларируется в классе Object.

C# позволяет использовать указатели, которые проектировщики языков зачастую считают опасными. Подход C# в этом деле — требование ключегого слова unsafe при блоках кода или методах, использующих эту возможность. Это ключевое слово предупреждает пользователей такого кода о его потенциальной опасности. Оно также требует явного задания компилятору опции /unsafe, которая по умолчанию выключена.

Типы данных

Оба языка поддерживают идею примитивных типов (известных в C# как типы-значенияvalue types), и оба для трансляции примитивных типов в объектные обеспечивают их автоматическое «заворачивание» в объекты (boxing) и «разворачивание» (unboxing). У C# имеется больше примитивных типов, чем у Джавы, за счёт беззнаковых целых типов (unsigned), имеющихся парно ко всем знаковым, и специального типа decimal для высокоточных вычислений с плавающей запятой. В Джаве отказались от большинства беззнаковых типов ради простоты. В частности, в Джаве нет примитивного типа беззнакового байта.

Строки в обоих языках являются объектами, при этом поддерживается отдельный случай создания строк через строковые литералы. Для массивов и коллекций в обоих языках введена особая разновидность цикла for — это цикл по коллекции, известный также как цикл foreach. Объектные типы могут быть также параметризованными, чем поддерживается обобщённое программирование. Однако реализация обобщённых классов (generics) в Джаве такова, что они известны только на этапе компиляции и пропадают для выполнимого кода.

C# позволяет создавать пользовательские типы-значения, используя ключевое слово struct. В отличие от экземпляров классов, экземпляры типов-значений создаются не на куче, а на стеке вызовов или в составе экземпляра объекта, в котором они объявлены, что в некоторых случаях повышает производительность кода. С точки зрения программиста они подобны классам, но с несколькими ограничениями: у них не может быть конструктора без параметров (но может быть конструктор с параметрами), от них нельзя наследовать и они не могут наследовать от других классов (но могут реализовывать интерфейсы).

Перечислимые типы в C# происходят от примитивных целочисленных типов. В этом языке допустимым значением перечислимого типа является любое значение лежащего в его основе примитивного, хотя для его присваивания может потребоваться явное приведение типа. Это позволяет комбинировать значения перечислимого типа побитовой операцией «или», если они являются битовыми флагами. В Джаве перечислимые значения, напротив, являются объектами. Единственные допустимые для них значения — те, что перечислены в объявлении типа. Для комбинации их вместе как флагов требуется специальный объект набора перечислений. В Джаве перечислимые типы позволяют задавать разные реализации методов для каждого значения. И в C#, и в Джаве перечисления могут преобразовываться в строки, но только в Джаве такое преобразование можно подгонять под себя (customize).

В C# есть как настоящие многомерные массивы, так и массивы массивов, которые есть и в Джаве, а в C# обычно называются неровными, или ступенчатыми (jagged) массивами. Многомерные массивы всегда «прямоугольные» (говоря в двумерной терминологии), в то время как массивы массивов могут хранить строки разной длины (опять-таки в двумерном случае, в многомерном аналогично). Прямоугольные массивы ускоряют доступ к памяти для тех случаев, когда это важно (для них указатель разыменовывается только один раз), а неровные массивы работают медленнее, но экономят память, когда не все строки заполнены. Прямоугольные массивы также избавляют от необходимости явно выделять память для каждой строки.

Обобщённые классы в Джаве используют так называемое затирание типов (type erasure). Информация о специализирующем типе доступна только компилятору и во время выполнения отсутствует, а для рефлексии она доступна только для статических объектов. В .NET 2.0 же информация об обобщённых типах полностью сохраняется во время выполнения. Подход Джавы требует дополнительных проверок типа в программном коде, не гарантирует, что клиент кода будет следовать соответствию типов, и не обеспечивает рефлексии для обобщённых типов. Джава не позволяет специализировать обобщённые типы примитивными, а C# обеспечивает обобщение как для ссылочных типов, так и для типов-значений, включая примитивные. Как в Джаве, так и в C# специализации обобщённого типа на разных ссылочных типах дают одинаковый код [1], но C# динамически генерирует оптимизированный код при специализации на типах-значениях (например, List<int>), что позволяет их хранить и извлекать из контейнеров без операций за- и разворачивания. В .NET 2.0 типовая безопасность (type safety) для обобщённых типов обеспечивается виртуальной машиной на этапе загрузки, в то время как в Джаве она обеспечивается только частично во время компиляции (VM Джавы не знает об обобщённых типах). Среда выполнения .NET также может создавать динамически новые специализации обобщённых типов во время выполнения.

Обозначения и особые возможности

В Джаве есть специальный синтаксис импорта статических имён (import static), позволяющий использовать сокращённые имена некоторых или всех статических методов и переменных класса. В C# есть синтаксис статического класса (static class), ограничивающий класс только статическими методами, но нет возможности указывать только эти методы без явного задания класса каждый раз.

Специальные ключевые слова

Ключевое слово Возможность, пример использования
get, set Синтаксис C# поддерживает свойства.
out, ref C# поддерживает выходные параметры методов, позволяя возвращать несколько значений.
switch В C# оператор switch работает также на строках.
strictfp Джава использует strictfp для гарантирования неизменности результатов операций с плавающей точкой на всех платформах.
checked, unchecked В C# выражения или блоки checked могут включать проверку арифметического переполнения во время выполнения.
using Ключевое слово using в C#'s обеспечивает ликвидацию или закрытие созданного объекта на выходе из блока кода:
using (StreamWriter file = new StreamWriter("test.txt"))
{
   file.Write("test");
}

goto C# поддерживает оператор перехода goto. Он может быть иногда полезным, хотя обычно рекомендуются более структурированные методы передачи управления (из-за чего от него и отказались в Джаве). Обычное использование ключевого слова goto в C# — передача управления на разные метки case в операторе switch.
switch(color)
{
   case Color.Blue: Console.WriteLine("Color is blue"); break;
   case Color.DarkBlue: Console.WriteLine("Color is dark"); goto case Color.Blue;
   // ...
}

Обработка событий

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

C# предоставляет обширную поддержку событийного программирования на уровне языка, включая делегаты .NET, мультикастинг, специальный синтаксис для задания событий в классах, операции для регистрации и разрегистрации обработчиков события, ковариантность делегатов и анонимные методы с полным набором семантики замыкания.

Замыкания предлагаются к включению в Java SE 7 [2]. Эти замыкания, как делегаты в C#, имели бы полный доступ ко всем локальным переменным в данной области видимости, а не только доступ для чтения к переменным, помеченным словом final (как с анонимными вложенными классами).

Перегрузка операций

C# включает большой набор удобств нотации, многие из которых, такие как перегрузка операций и задаваемое пользователем приведение типов, знакомы программирующим на C++. В нём также есть явная реализация методов интерфейса, что позволяет классу реализовывать методы интерфейса отдельно от собственных методов или давать разные реализации одноимённых методов, принадлежащих двум разным интерфейсам.

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

Методы

В C# методы по умолчанию не являются виртуальными и должны для этого явно объявляться ключевым словом virtual. В Джаве, наоборот, все открытые методы, кроме статических, являются виртуальными. [1] Ключевое слово Java final является аналогом sealed в C# и позволяет запретить создание метода с такой же сигнатурой в производных классах. Виртуальность гарантирует нужное перекрытие для вызываемого метода, но при выполнении налагает некоторые расходы на вызовы, поскольку эти вызовы обычно не проходят инлайн-подстановку и требуют дополнительного обращения к таблице виртуальных методов. Однако некоторые реализации JVM, включая реализацию Sun, реализуют инлайн-подстановку наиболее часто вызываемых виртуальных методов.

C# требует явного объявления о намерении перекрыть (override) виртуальный метод в производном классе. Такое намерение описывается ключевым словом override. Если перекрытие не входит в намерения программиста, и требуется просто ввести новый виртуальный метод с тем же именеи и сигнатурой, заслоняющий (shadowing) старый, то тогда требуется другое ключевое слово, new. Если ни одно из этих слов не указано, то это ведёт к ошибке компиляции. В Джаве любой метод всегда виртуально перекрывает метод базового класса с теми же именем и сигнатурой, если он есть. Такое поведение потенциально опасно, если базовый класс создан другим разработчиком, и в новой его версии вводится такой же метод, который уже есть в производном классе; в этом случае существующий метод из производного класса перекроет вновь введённый метод в базовом, что не входит в намерения обоих разработчиков.

Условная компиляция

C#, в отличие от Java, поддерживает условную компиляцию с использованием директив препроцессора. В нём также есть атрибут Conditional, означающий, что указанный метод вызывается только тогда, когда определена данная константа компиляции. Таким путём можно вставлять в код, например, проверки допущений (assertion checks), которые будут работать только в отладочной версии, когда определена константа DEBUG. В стандартной библиотеке .NET это метод Debug.Assert(). Java версий 1.4 и выше включает в язык возможность проверки допущений, включаемую во время выполнения.

Пространства имён и исходные файлы

Пространства имён C# больше напоминают C++. В отличие от Джавы, местонахождение файла с исходным текстом никак не связано с его пространством имён. Хотя, строго говоря, местонахождение исходных файлов в Джаве не обязательно отражает структуру каталогов пакета, но таково поведение по умолчанию.

Джава требует, чтобы имя исходного файла точного соответствовало имени единственного общедоступного (public) класса, определённого в нём, в то время как C# позволяет в одном файле определять несколько общедоступных классов и не налагает никаких ограничений на имя файла, а также (в версии 2.0 и выше) позволяет разбить класс на два и более файла (ключевое слово partial).

Исключения

Джава поддерживает проверяемые (checked) исключения, принудительно обеспечивая полную ловлю и обработку всех исключительных ситуаций. Все исключения, которые метод может выбросить, должны перечисляться в его объявлении при помощи ключевого слова throws. C# проверяемые исключения не поддерживает. Одни разработчики считают, что проверяемые исключения очень полезны для обеспечения хорошего стиля программирования. Другие, включая Андерса Хейлсберга, главного архитектора C#, возражают, что они в Джаве были в какой-то степени экспериментом и себя не оправдали [3] [4].

Один из аргументов против проверяемых исключений — то, что при их использовании изменение внутреннего кода функции может привести к выбросу новых исключений, что требует изменения в объявлении этой функции и всех других, её вызывающих. В конце концов для сохранения совместимости интерфейсов зачастую просто стали объявлять функции как throws Exception, сводя таким образом на нет всю идею проверяемых исключений. Другой способ сохранения совместимости интерфейса в Джаве — поймать нововведённое исключение, завернуть его в старое объявленное и снова выбросить. Например, если метод изменили так, что он начинает обращаться к базе данных вместо файловой системы, то он может сам ловить SQLException и выбрасывать вместо него вновь создаваемый IOException, поскольку пользователь метода не должен знать о деталях его внутренней реализации.

Низкоуровневый код

Java Native Interface (JNI) позволяет программам вызывать из Джавы другой код. Однако JNI требует от вызываемого кода соблюдения специальных соглашений и налагает ограничения на использование типов и имён. Это означает, что между старым кодом и Джавой требуется дополнительный адаптирующий слой. Такой адаптирующий код должен писаться на C, C++ или других подобных языках. Выпускаются также специализированные библиотеки для взаимодействия Java с COM.

Технология Platform Invoke (P/Invoke), реализованная в .NET, предлагает ту же возможность, позволяя вызывать из C# внешний код, который Microsoft называет неуправляемым. Через атрибуты в метаданных программист может точно управлять передачей (маршрутизацией) параметров и результатов, избегая таким образом необходимости дополнительного кода адаптации. P/Invoke позволяет почти полный доступ к процедурным API (таким, как Win32 или POSIX), но не даёт прямого доступа к библиотекам классов C++.

.NET Framework предоставляет также мост между .NET и COM, позволяя обращаться к COM-компонентам так, как если бы они были родными объектами .NET.

C# также позволяет программисту отключить нормальную проверку типов и другие возможности безопасности CLR, разрешая использование переменных-указателей при условии применения ключевого слова unsafe. JNI, P/Invoke и unsafe-код одинаково рискованны, чреваты дырами в безопасности системы и нестабильностью приложения. Преимуществом управляемого unsafe-кода над P/Invoke или JNI является то, что он позволяет программисту продолжать работать в знакомой среде C# для выполнения задач, которые при других методах потребовали бы вызова неуправляемого кода, написанного на другом языке.

Реализации

JVM и CLR

Джава вездесуща во всевозможных операционных системах и средах. Существуют многочисленные реализации JVM, иногда с открытыми исходными кодами.

Java Webstart и апплеты обеспечивают удобное, лёгкое и безопасное средство распространения настольных приложений, причём эффективность её байткодового представления вкупе с агрессивными технологиями сжатия, такими как pack200, делают Джаву средством распространения сетевых приложений, неприхотливым к полосе пропускания.

C# тоже является кроссплатформенным стандартом. Его первичная платформа — Windows, но существуют и реализации для других платформ, самая значительная из которых — проект Mono.

Технология ClickOnce предлагает подобную же функциональность для Java Webstart, но она имеется только для клиентов Windows. Internet Explorer на Windows тоже умеет показывать элементы интерфейса .NET Windows Forms, что даёт апплетоподобную функциональность, но ограничено конкретным браузером.

Стандартизация

Язык C# определяется не Microsoft, а комитетами стандартов ECMA и ISO. В то время как Sun сохраняет копирайт и право вето на платформу Java, последняя в большой степени управляется через Java Community Process]] (JCP), который позволяет заинтересованным сторонам вовлекаться в определение новых версий и возможностей спецификации технологии Java.

Стандарты ECMA и ISO для C# и .NET определяют язык, инфраструктуру CLI и базовые классы (Base Class Library, или BCL). Стандарты не включают многие новые библиотеки, реализованный Microsoft поверх стандартного каркаса, такие как библиотеки для баз данных, GUI и веб-приложений (Windows Forms, ASP.NET и ADO.NET). Однао Microsoft формально согласилось не преследовать в судебном порядке проекты сообщества за реализацию этих библиотек [5].


Использование

Сообщество

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

Несмотря на существование Mono, C# тесно привязывает разработчиков к платформе. Это сильно упрощает разработку и уже поэтому служит решением, хоть и может кому-то не нравиться.

Джава следует более чистому подходу к разработке. Каркасы, построенные на Джаве, имеют тенденцию к большому количеству классов, взаимодействующих друг с другом, со многими слоями абстракции. Это придаёт каркасам значительную мощность, но изучение новой библиотеки может быть затруднено, и даже программа Hello world в некоторых случаях может оказаться сложной.

Подход C# более прагматичен. В дополнение ко вложенным уровням абстракции часто поставляются простые вспомогательные классы; в некоторых случаях уровни абстракции вообще не делаются.

Популярность и развитие

Джава старше, чем C# и построена на большой и активной пользовательской базе, став lingua franca во многих современных областях информатики, особенно таких, где задействованы сети. Джава доминирует в курсах программирования американских университетов и колледжей, и литературы по Джаве сегодня намного больше, чем по C#. Зрелость и популярность Джавы привели к большему числу библиотек и API на Джаве (многие из которых открытые), чем на C#.

В отличие от Джавы, C# — язык относительно новый. Microsoft изучила существующие языки, такие как Джава и Дельфи, и изменила некоторые аспекты языка для лучшего соответствия нуждам некоторых типов приложений. С течением времени временно́е преимущество Джавы становится менее значимым.

В отношении Джавы можно услышать критику, что она медленно развивается, в ней не хватает некоторых возможностей, которые облегчают модные шаблоны программирования и методологии. Язык C# критикуют в том, что его разработчики, возможно, слишком спешат угодить сиюминутным течениям в программировании за счёт фокусировки и простоты языка. Очевидно, проектировщики Джавы заняли более консервативную позицию по добавлению крупных новых возможностей в синтаксис языка, чем в других современных языках — возможно, не желая привязать язык к течениям, которые в долгосрочной перспективе могут завести в тупик. С выпуском Java 5.0 эта тенденция во многом была нарушена, так как в ней ввели несколько крупных новых возможностей языка: цикл типа foreach, автоматическое заворачивание, методы с переменным числом параметров, перечислимые типы, обобщённые типы и аннотации (все они присутствуют и в C#).

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

Рынок

С момента появления C# он постоянно сравнивается с Джавой. Невозможно отрицать, что C# и его управляемая среда CLR многим обязаны Джаве и ее JRE (Java Runtime Environment). Однако C# также приспособлен и к конструкциям, чаще существующим в языках типа C++, Дельфи (который спроектировал тот же Андерс Хейлсберг) и, в последних версиях C#, кое-что позаимствовал также из таких динамических скриптовых языков, как Руби.

Можно спорить, является ли разработка C# в какой-то степени результатом признания Майкрософтом того, что среда управляемого кода, где лидирует Джава, имеет множество достоинств в растущем сетевом мире, особенно при появлении интернета на устройствах, отличных от персональных компьютеров, и при растущей важности сетевой безопасности. До создания C# Microsoft модифицировала Джаву (создав J++), с тем чтобы добавить возможности, работающие только на ОС Windows, нарушив таким образом лицензионное соглашение Sun Microsystems. Пока Microsoft находилась на второй фазе своей бизнес-стратегии, известной как <embrace, extend and extinguish>, развитие J++ было остановлено иском, поданным Sun'ом. Будучи лишённой возможности разрабатывать клон Джавы с нужными ей свойствами, Microsoft создала альтернативу, которая больше соответствовала их потребностям и видению будущего.

Несмотря на такое беспокойное начало, становится всё более очевидным, что два языка редко конкурируют друг с другом на рынке. Джава доминирует в мобильном секторе и имеет много приверженцев на рынке веб-приложений. C# получил хорошее признание на рынке настольных приложений Windows и проталкивается Майкрософтом как основной язык приложений Windows. Благодаря ASP.NET, C# также является игроком и на рынке веб-приложений.

Настольные приложения

Джаву иногда обвиняют в том, что она много обещает и мало даёт, когда речь заходит о настольных приложениях. Хоть её оконные библиотеки AWT (Abstract Windowing Toolkit) и Swing могут похвастаться обилием возможностей, Джаве пришлось побороться, чтобы утвердиться на рынке настольных приложений. Её строгая приверженность принципу <пишем один раз, используем везде> затрудняет использование по максимуму специфических возможностей и режимов работы в каждой конкретной настольной системе. В результате написанные на Джаве настольные приложения часто выглядят внешне как <чужие> на той платформе, на которой они выполняются.

Sun Microsystems, по мнению некоторых, также медлила с продвижением Джавы в среду разработчиков и пользователей так, чтобы она выглядела привлекательно при выборе платформы для настольных приложений. Даже такие технологии, как Java Web Start, у которых мало соперников среди языков и платформ, продвигались слабо.

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

Многие открытые и свободные операционные системы также отказываются включить какую-либо среду Sun Java Runtime Environment, поскольку Sun Microsystems ещё не лицензировала легально совместимую версию для общественного достояния.[2][3][4] Многие из нынешних пользовательских лицензионных соглашений Sun, касающихся Джавы, определяют многое из платформы Джавы как коммерческую тайну[2] и бессрочно запрещают конечному пользователю делать вклад в среду Java третьих сторон. Некоторые из этих положений могут измениться, если Sun изменит лицензию Java на GPL, о чем она уже объявляла как о намерении.

C# недавно стал популярным на нескольких операционных системах на основе Linux и BSD.[5][6][7] Реализация проекта Mono была юридически безболезненным процессом, поскольку CLR и язык C# стандартизированы Ecma и ISO, и любой может их реализовывать, не беспокоясь о правовой стороне дела[8].

Серверные приложения

На этой арене, возможно, два языка наиболее близки к тому, чтобы считаться конкурентами. Джава с её платформой J2EE (Java(2) Enterprise Edition) и C# с его ASP.NET соперничают в области создания динамического веб-контента и приложений.

На этом рынке широко используются и поддерживаются оба языка, вместе с комплектом инструментов и сопровождающих продуктов, имеющихся для JavaEE и .NET.

Мобильные приложения

J2ME (JavaME, Java(2) Micro Edition) имеет очень широкую базу на рынках мобильных телефонов и КПК, где только самые дешёвые устройства лишены KVM (урезанная Java Virtual Machine для устройств с ограниченными ресурсами). Программы на Джаве, включая множество игр, встречаются повсеместно.

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

На рынке смартфонов и КПК быстро набирает силу Windows Mobile, она же становится предпочтительной платформой для написания тяжёлых бизнес-приложений. Windows Mobile основана на платформе Windows CE и использует .NET Compact Framework (.NETCF) — подмножество полной версии .NET Framework с дополнительной функциональностью для мобильных устройств.

Передовые технологии

Джава принята в качестве официального программного средства для использования в следующем поколении стандарта DVD, Blu-ray, через интерактивную платформу BD-J. Это значит, что такое интерактивное содержимое, как меню, игры, скачивания и т.д., на всех дисках DVD Blu-ray будет создаваться на платформе Java.

Примечания

  1. Робинсон С., Корнес О. и др. C# для профессионалов//М., Лори, 2005 - С.123. ISBN 1861004990
  2. а б Sun Java 2 Runtime License Agreement
  3. GNU Classpath FAQ: isn't java free already?
  4. GNU classpath tainted developer description
  5. Fedora embraces Mono - ZDNet UK
  6. Debian -- mono
  7. Wikipedia Uses Mono; Mono Integrated into Ubuntu/Debian - OSNews.com
  8. ISO Standards Development:ISOTC home:00. ISO standards and patents
 
Начальная страница  » 
А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ы Э Ю Я
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
0 1 2 3 4 5 6 7 8 9 Home