eManual.ru - электронная документация
Секция 3 из 7 - Предыдущая - Следующая
Все секции
- 1
- 2
- 3
- 4
- 5
- 6
- 7
classpath по умолчанию и поддерживаемыми опциями. Во избежание путаницы,
команда jre была удалена в JDK 1.2. Вместо неё оставлена команда "java" как
в bin так и в jre/bin.
jre.exe программа запуска java, которая поставляется с Java Runtime
Environment. Используются свои собственные внутренние установки по
умолчанию, игнорируются установки окружения CLASSPATH и всё, чтобы ни
стояло в командной строке -cp или -classpath. Подразумевается, что это
немного проще для тех, кто только запускает на выполнение Java программы, а
не разрабатывает их.
java.exe программа запуска java, которая поставляется с JDK. Использует
установки окружения CLASSPATH как начальную точку поиска, а затем
обращается к собственным внутренним параметрам.
Обе служат одной и той же цели - запуск виртуальной Java машины (JVM),
выполнение в ней приложения Java, затем остановка JVM. Исходные тексты
jre.exe поставляются с JDK. Исходные тексты java.exe поставляются только со
специальным дистрибутивом исходных текстов JDK.
(Часть 4) Какие IDE (Integrated Development Environments - Интегрированные
среды разработчика) существуют?
[*] Ниже перечислены популярные IDE:
Apptivity (Progress) http://www.apptivity.com
Bluette (свободно) http://blue.donga.ac.kr/bluette/index.html
Chicory (свободно) http://www.chicory.com
CodeWarrior Professional http://www.metrowerks.com
Freebuilder http://www.freebuilder.org
GRASP (свободно) http://www.eng.auburn.edu/grasp
Grinder http://www.tpex.com
Java WorkShop (Sun) http://www.sun.com/workshop/java
Javelin, Visual Object
Development for Java http://www.stepahead.com.au
JBuilder (Inprise) http://www.inprise.com/jbuilder
JDE для emacs http://sunsite.auc.dk/jde/
Kawa (Webcetera) http://www.tek-tools.com/kawa Metamata
http://www.metamata.com NetBeans (Swing-based) http://www.netbeans.com
PARTS alpha (ObjectShare) http://www.objectshare.com PowerJ (Sybase)
http://www.sybase.com/products/powerj SilverStream
http://www.silverstream.com Simplicity for Java
http://www.datarepresentations.com Super Mojo (Penumbra)
http://www.penumbrasoftware.com SuperCede (Asymetrix)
http://www.supercede.com teikade (PFU Ltd) http://www.pfu.co.jp/teikade
Together/J (Object Intl Inc.) http://www.oi.com Visaj (Imperial SW Tech)
http://www.imperial-software-tech.co.uk VisualAge (IBM)
http://www.software.ibm.com/ad/vajava Visual Cafe (Symantec)
http://cafe.symantec.com Visual J++ (Microsoft) (не рекомендуется) Xelfi
0.94 http://www.xelfi.com
*(Sect. 4) Почему Visual J++ - плохой выбор?
Потому что главная цель Microsoft - "Уничтожение кросс-платформенной Java"
[*] Обеспечение пользователю возможности легкого переноса программ на
другие платформы противоречит финансовым интересам Microsoft. MS -
единственная компания в компьютерной промышленности, которая активно
пытается подорвать Java. Это не предположение - Департамент Юстиции на
одном из судебных разбирательств с Microsoft, упоминая компанию, назвал ее
стратегической целью - "уничтожение кросс-платформенной Java посредством
заражения Java-рынка". Загляните на
http://www.usdoj.gov/atr/cases/f1700/1762.htm VJ++ может использоваться как
Java-совместимый продукт, но с предлагаемыми по умолчанию установками, это
невозможно.
Против Microsoft было возбуждено дело из-за несанкционированных изменений,
сделанных в Java. Федеральный судья в марте 1998 г. дал компании
предписание, запрещающее использование этикеток, выдающих J++ за Java.
Другое предписание, в котором требовалось устранение преднамеренной
несовместимости с Java, было дано Microsoft в ноябре 1998 г.(напомним, что
Microsoft не создавала Java, а всего лишь получила от Sun право на ее
распространение).
Спросите у Вашего
начальства как
комфортно оно себя чувствует, используя продукты от Microsoft в то время
как компания втягивается в юридический конфликт из-за преднамеренно
созданных несовместимостей в ПО. Спросите как оно себя чувствует, когда
доказано, что Microsoft хочет ограничить пользователя рамками одной ОС. Все
это сказано для того, чтобы защитить Вас от неправильного выбора. Вы можете
ссылаться на эти факты, внедряя Java в Вашей компании.
Как Java-программист, присоединитесь пожалуйста к Java Lobby - независимой
организации, представляющей некоммерческие интересы Java. Это вы можете
сделать бесплатно. Вы можете посетить http://www.javalobby.org для
уточнения деталей. Есть другие пути, способствующие распространению Java:
* Можно использовать средства разработки других поставщиков. Можно
конвертировать MS J++ для работы с Sun'овским JDK. За инструкциями
можно обратиться на http://www.orbiter.demon.co.uk/
* Можно использовать Netscape Communicator (не Internet Explorer)
* Если без Internet Explorer не обойтись, используйте Java-плугины.
* Используйте стандартный GNU JVM, Kaffe, другие IDE (от Sun, например.
Но ни в коем случае не Microsoft J++ SDK)
* Бесплатные Java-компиляторы и плугины можно взять на
http://java.sun.com.
* Бесплатные виртуальные Java-машины можно скачать здесь:
http://www.kaffe.org, http://www.oryxsoft.com/projects/gvm, и
http://www.redhat.com/linux-info/jolt
* Бесплатный Java AWT софт можно найти на
http://www.biss-net.com/biss-awt.html а также можно взять все
необходимое на ftp.java-linux.org (linux'овский сайт).
* Бесплатный Java-софт лежит здесь:
http://www.gnu.org/software/java/java.html
Кстати, в мае 1998 г. Microsoft отрицала свою вину, настаивая на том, что
она создала новый, усовершенствованный проект. Это не соответствует
действительности. Microsoft фактически обвиняют в
* действиях, направленных против конкурентов, производящих броузеры.
Таким образом защищается монополия Microsoft на рынке настольных
операционных систем.
* использовании монополии для навязывания производителям PC
ограничивающих соглашений, требующих поставку Microsoft броузера
вместе с Windows. Это также препятствует продвижению на рынок
конкурентноспособных броузеров.
Многие люди не понимают политики, взятой на вооружение компанией Microsoft.
Зачастую условия, которые ставит Microsoft в соглашениях, очень неразумны,
а порой и абсолютно неприемлемы. Вот почему MS сталкивается с проблемой
нелегального использования своих продуктов в США, Италии, Бразилии и
европейских странах.
*(Часть 6) Как работать со связными списками, если в Java нет указателей?
[*] Из всех заблуждений, связаных с Java, это - самое неприятное.
Обьектно-ориентированное программирование основано исключительно на
указателях. Иначе говоря, доступ к обьектам происходит всегда через
указатели, и никогда - напрямую. Но это указатели названы "ссылками" и
всегда автоматически "разыменовываются".
В Java нет арифметики указателей и произвольного преобразования типов.
Запретив создавать и менять указатели по своему усмотрению, Java делает
работу с памятью более надежной, но позволяет создавать динамические
структуры. Кроме того, в Java есть NullPointerException (нулевой
указатель), а не NullReferenceException (нулевая ссылка).
Класс связаного списка мог выглядеть примерно так:
public class LinkedList {
public LinkedList head;
public LinkedList next;
public Object data;
public LinkedList advanceToNext(LinkedList current) { ...
}
Другой вариант - использовать стандартный класс java.util.Vector, который
принимает и хранит обьекты в произвольных количествах (как списки), и
выдает их по номеру (как массив). Вектор автоматически меняет свой размер
при необходимости. Добавление элемента в начало вектора - более медленная
операция, чем добавление в список, но зато выборка элемента происходит
быстрее. Что важнее для вашего приложения?
*(Часть 6) Как предаются параметры - по значению или по ссылке?
[*] Все параметры (как базовые типы так и ссылки на обьекты) передаются по
значению. Но не все так просто, так как работа с обьектами производится по
ссылке. Поэтому можно сказать, что обьекты передаются по ссылке (а ссылка
передается по значению). Это - следствие того, что переменные содержат не
сами обьекты, а ссылки на них (см. предыдущий вопрос о связных списках).
Примечание: Когда параметр примитивного типа (int, char и т.п.) изменяется
внутри метода, исходная переменнная _не меняется_. Тем не менее, поля
обьектов меняются при изменении поля параметра в вызваном методе.
См. в FAQ:
Как работать со связными списками, если в Java нет указателей?
См. также:
JLS 8.4.1 Formal Parameters
*(Часть. 6) Что такое "литералы класса"? (class litrals)
[*] Новый синтаксис в JDK 1.1. Это константы типа "Class", содержашие
информацию о конкретном классе. Есть даже константы для типа "void" и
массивов, например:
Class myCl1 = Character.class;
Class myCl2 = Void.class;
Class myCl3 = Object.class;
Class myCl4 = String[].class;
Class myCl5 = int[][].class;
Это можно использовать, например, так:
Class cl = thing.getClass();
if (cl.equals(myCl1))
System.out.println("It's a Character class");
Заметьте, что литерал класса
Component.class
есть эквивалент
Class.forName("java.awt.Component")
Последнее может выбрасывать исключение, в отличие от первого. Если в момент
написания имя конкретного класса не извесно, то вы не можете использовать
первую форму.
*(Sect. 6) Какие соглашения об именах существуют в Java?
[*] Соглашения об именах просты:
1. Несовпадения имен пакетов гарантированы использование имени домена в
обратном порядке: com.javasoft.jag - "com" и "edu" обычно в верхнем
регистре, но теперь рекомнедуется в нижнем.
2. Имена классов - описательные существительные, с заглавной буквой в
начале каждого слова: PolarCoords (ПолярныеКоординаты). Часто (но не
всегда) интерфейсы называются "что-то-able", например, "Runnable"
(запускаемый), "Sortable" (упорядочеваемый). Предупреждение:
java.util.Observable не интерфейс, а java.util.Observer - интерфейс.
Эти два имени плохо продуманы.
3. Переменный и поля - существительное/фраза с существительным, с первой
буквой в нижнем регистре и превой буквой подслова - в верхнем:
currentLimit (текущийПредел).
4. Имена методов - глагол/фраза с глаголом, с маленькой буквы, каждое
подслово - с большой: calculateCurrentLimit (вычислитьТекущийПредел).
5. Имена констант (с модификатором final) пишутся большими буквами:
UPPER_LIMIT
6. См. в FAQ:
Где взять руководство о соглашениях об именах в Java?
См. также:
JLS 6.8 Naming conventions
*(Часть 6) Лучше ли использовать импорт {package}.{class} вместо
{package}.*?
Повлияет ли это на файл класса, если я импортитрую весь пакет вместо
использования полного имени, т.е.
import java.rmi.server.*;
...
RemoteObject ro;
вместо
java.rmi.server.RemoteObject ro;
[*] Это никак не отразится на файле класса или скорости выполнения. Импорт
- это просто сокращение для для полных имен классов пакете (как в примере
выше). Импортирование лишнего класса не приводит к его загрузке при
выполнении. Нет никаких отрицательных эффектов при использовании формы "*".
Файл класса всегда содержит имена только используемых пакетов, и загрузчик
будет искать те классы, которые необходимы.
Во время компиляции вид импорта может как изменить, так и не изменить время
компиляции. Такое различие, скорее всего, будет не заметно, и это не может
служить доводом для выбора вида импортирования.
Тем не менее, существуют стилевые причины. Некоторые утверждают, что
импортирование классов илучшает "читабельность" прогоаммы. В прораммых с
большим количеством "*" иногда трудно понять, какой класс откуда
импортируется. Если вы ясно обьявляете импорт для каждого класса в начале
программы, вы документируете, где содержтся каждый используемый класс.
Такие люди предлагают использовать
import java.rmi.server.RemoteObject;
вместо
import java.rmi.server.*;
Другие же утверждают, что еще понятней использовать полные имена пакетов и
классов везде, где вы используете классы из других пакетов.
Эти люди предлагают писать
java.rmi.server.RemoteObject ro;
Это становится немного длинее, когда вы инициализируете пременную:
java.rmi.server.RemoteObject ro
= new java.rmi.server.RemoteObject();
Вы всегда можете выбрать, набрать ли вам полное имя или использовать
импорт.
Есть еще одна причина не использовать "*". Если вы импортируете два пакета,
имеющие классы с одинаковыми именами и вы хотите использовать толькоодин из
них. Например,
import com.sun.*;
import com.ms.*;
где содержатся два класса с именем Modem в обеих пакетах. Если используется
"*"-форма, то оба класса будут импортированы, и вы обязаны писать полные
имена классов везде, где они использованы, чтобы компилятор понял, что вы
имеете в виду. В Java 1.2 был представлен класс java.util.List. Этот класс
имеет тоже имя, что и java.util.List. Если вы используете в программе
"import java.awt.*; import java.util.*;", ваша программа, возможно, не
будет компилироваться - вы получите сообщение о неоднозначных именах. Если
вы импортируете все файлы без разбора, то в случае изменения API у вас
могут появиться проблемы.
В Java 1.0, если импортируется класс, который имеет то же имя, что и класс
в тексте, то вы получите сообщение о конфликте имен. В Java 1.1 будет
ипользован локальный класс, если не указано имя пакета. Для использования
"импортного" класса используйте полное имя.
Самое лучшее - писать программу так, чтобы она была как можно более
читабельна. Ели используется группа широко известных классов, как java.awt,
то нет особых причин не использовать "import java.awt.*;"
*(Часть 6) Что случилось с "private protected"?
[*] Впервые это появилось в JDK 1.0 FCS (его не было в бетах). Затем было
убрано в JDK 1.0.1. Это был грязный хак синтаксиса, и он не соответствовал
логически другим модификаторам доступа. Он никогда не работал правильно: в
версиях JDK, до того как он был убран, вызовы private protected методов не
связывались динамически, как это должно было бы быть. Он добавлял очень
немного возможностей к языку. Использовать существующие ключевые слова с
другим значением- всегда плохая идея. Использовать два из них вместе - еще
хуже.
По официальной версии это баг. Но это неполная история. Private protected
был добавлен потому, что у него были сильные защитники. Он был убран, когда
был осужден всеобщим мнением.
Наследование (inheritance)
*Каково различие между наследованием и абстрактным классом?
[*] Некоторое семантическое отличие: Модель абстрактных суперклассов
моделирует связи "есть", тогда как интерфейс моделирует связь "имеет".
Правило таково - если это подтип, наследуйте, иначе - реализуйте.
Но, в отсутствие реальных характеристик для выделения объектов из их
свойств и предков, это становится аргументом, действующим и в ту и в другую
сторону. В этом случае Вы должны посмотреть на практическое различие в Java
(в сравнении с C++) .
Основные различия между интерфейсами и абстрактными классами произрастают
из трех характеристик:
1. Оба определяют описания методов, которые будет иметь производный
класс.
2. Абстрактный класс может также определять частичную реализацию.
3. Класс может реализовать много интерфейсов, но наследуется только от
одного класса.
Более детально:
1. Описания методов И интерфейсы и абстрактные классы позволяют
обращаться с классом производного типа как с классом типа, от которого
он унаследован. Оба определяют набор доступных методов способом,
который может быть усилен механизмом проверки типа. Это обычно
используется для того, чтобы позволить различным (производным) типам
иметь одинаковове поведение (так как они все наследники, т.е. они все
имеют определенные методы). Например, все типа java,* могут быть
распечатаны как String, так как Object, суперкласс всех типов java.*,
имеет метод toString(). Аналогично, все типы, которые реализуют
интерфейс Observable доступны как Observer для сигнализации, что
событие произошло. Это позволяет алгоритму или сервису работать с
различными (производными) типами, так как будто они одного (от
которого унаследованы) типа.
Этот механизм поддерживает не только полиморфизм (один объект
обрабатывается как другой), но и дифференциацию. В любом случае типы
(производные) могут реализовывать метод способом, соответствующим
этому типу. Однако, Вы не обязаны перекрывать унаследованную
функциональность, но Вы должны реализовать методы интерфейса, так что
если Вы ожидаете значительные различия, то может быть оправданным
использование интерфейса.
Наконец, этот механизм поддерживает слабый вариант контроля доступа.
Только унаследованные методы доступны вызывающему, который имеет
доступ к описанию суперкласса или интерфейса. Это слабость,так как
возможно указать конкретный тип, если он известен. В любом случае, это
уменьшает сложность.
2. Наследование реализации Наследование реализации полезно, когда код
должен быть разделяемым. Такое случается когда производные типы
различаются в функциональности очень немного, или когда комплексный
набор интерфейсов методов может быть реализован через взаимные ссылки
с относительно небольшим количеством методов, реализованных в
производных типах. Вы можете также повторно использовать код, сделав
Ваш класс содержащим или использующим объект другого типа, который
реализует этот код, но это не дает возможности вызывающим использовать
вас особым образом. Получение и функциональности и возможности быть
использованным, как суперкласс - сущность отношений тип/подтип.
3. Правило одиночного наследования в Java Java отличается от C++ тем, что
позволяет только одиночное наследование. Это приводит к трудному
выбору, если Вы хотите совместить функциональность наследования и
полиморфизма из более, чем одного источника. Однако это усиливает
представление о наследованиее как о связи подтипов, и представлению
этого типа связи в виде дерева, а не сети.
Еще различия:
1. Реализации абстрактных классов могут включать поля
2. Интерфейсы могут включать final члены данных
3. Вызов метода через интерфейс пренебрежимо медленнее. Имеется даже
меньшая потеря при вызове суперкласса через ссылку на подкласс ( т.е.
когда подкласс не перекрывает метод). Почти нет потерь при вызове
метода подкласса при ссылке на суперкласс (Все при сравнении с прямым
вызовом, т.е. вызовом метода производного класса через ссылку на
производный класс)
*(Часть 6) Как статические методы взаимодействуют с наследованием?
[*] Статические (для класса, а не для объекта) методы не участвуют в
перекрытии (выборе нужного метода во время выполнения на основании класса
объекта) Возможно лучший и наиболее простой путь думать об этом ( и писать
Ваш код ) - писать каждый вызов статического метода, используя полное имя
класса:
class A {
public static method1() {
A.method2();
}
public static method2() {
}
}
class B extends A {
public static method3() {
A.method1();
}
public static method2() {
}
}
Сейчас прекрасно видно, что статический method2() вызывает A.method2(), а
не B.method2(). A.method2() будет вызван независимо от того, используете Вы
полное имя класса или нет, но использование "A." делает это очевидным для
всех.
*(Часть 6) Почему класс String final? Я часто хочу перекрыть его.
[*] Финальность гарантирует, что экземпляры String только для чтения (
класс String реализует объекты только для чтения, но если он не final, то
возможно написать подкласс string, который позволит быть экземплярам
изменяемыми.) Strings должен быть только для чтения для безопасности и
эффективности.
Что касается эффективности, String очень часто используется, даже неявно
компилятором Java. Еффективность, имеющаяся в классе String дает большие
пpеимущества. Так как никто не может изменить String, то Вы не должны
беспокоиться о том, кто еще ссылается на Ваш String. Проще оптимизировать
доступ к объекту, про который известно, что он не меняется.
безопасность- еще более важная причина. Прежде чем String был изменен на
final (пока Java 1.0 была еще бетой) было условие, которое могло быть
использовано для преодоления ограничений секьюрити. Это могло быть сделано
изменением пути к файлу в одном треде, псоле того как другой тред проверил,
что доступ к нему разрешен и собирался открыть его.
Существуют другие пути для решения этой проблемы, но разработчики предпочли
сделать String final, особенно так как имеется альтернативный класс
StringBuffer .
*(Часть 6) Если я расширяю/наследую класс, наследуются ли конструкторы?
[*] "Декларации конструкторов не являются членами. Они никогда не
наследются и поэтому не являются предметом скрытия или перекрытия."
Конструктор по умолчанию не наследуется, но обеспечивается. (См. JLS 8.6.7
Default Constructors)
Если Вы не даете Вашему классу конструкторы, то обеспечивается конструктор
по умолчанию без аргументов, который вызывает конструктор суперкласса. Если
суперкласс не имеет конструктора без аргументов, Вы должны создать
конструктор и вызвать соответствующий конструктор суперкласса.
Так же в FAQ:
Сообщения компилятора No constructor {superclass}()
Другие сайты:
JLS 8.6.7 Констpуктоpы по умолчанию
*(Часть 6) Как безопасно сохранить особые типы в обычных контейнерах?
Часто бывает необходимо сохранить особые типы объектов, но я не хочу
разбивать основные классы памяти чтобы достичь этого, т.к. может возникнуть
слишком большое количество подклассов (например, IntegerLinkedList,
StringLinkedList и т.д.)
[*] Родовое программирование на Java (приблизительный эквивалент шаблонов в
C++) работает приемлемо, когда все java-классы являются подклассами
Объекта. Однако существует потенциальная проблема - всегда есть вероятность
того, что родовой контейнер будет содержать различные классы объектов.
Предположим, Вы создали родовой класс LinkedList. Как обезопасить типы без
необходимости создавать множество подклассов (IntegerLinkedList,
StringLinkedList и т.д.)?
Чтобы обойти эту проблему, применените в родовом классе составной
конструктор, который будет брать параметр типа "Class" и использовать его
вместе с методом "isInstance" этого класса, чтобы гарантировать
предполагаемый тип для Объектов, добавленных в контейнер.
public class LinkedList {
Protected Class type = Object.class;
public LinkedList(Class type) { this.type = type; }
public void addElement(Object element) throws Exception
{
if(!type.isInstance( element ))
throw new Exception(
"Ожидаемый элемент типа (" + type + ")" +
" полученный элемент типа (" + element + ")" );
...
}
}
Заметьте, что комментарии в исходном тексте для isInstance() ссылаются на
"определенный параметр Класса", намекая, что Вам предлагается написать
что-то типа:
public void addElement(Object element) throws Exception
{
Class c = element.getClass();
if(!type.isInstance(c))
Это работает, но документация на isInstance разъясняет, что параметр
предпочтительнее сделать Объектом а не Классом. Также заметьте, что в JDK
1.2 имеются "Коллекции", которые обеспечивают гораздо более безопасный и
гибкий механизм. Информация об этом содержится на сайте Java в разделе Java
Developer Connection: http://java.sun.com/
Интерфейсы метода
*Как передать в метод переменное число аргументов?
[*]
1. (Легкий способ). Используйте перегрузку метода для поддержки различных
параметров. Это упрощает сам вызов, но может выйти из под контроля,
если Вы захотите поддерживать большое число разнообразных типов
параметров. Когда возникает такая необходимость, стоит задать себе
вопрос, грамотно ли организован код Вашей программы?
2. (Более запутанный). Используйте массивы. Возможно даже объявлять
массивы собственно при вызове, как показано ниже:
foo("Параметр",
new Object[] {"параметр3", "параметр4", new Integer(5)} );
// ...
void foo(String param1, Object param2[]) {
System.out.println(param1);
for (int i = 0; i < param2.length; i++) {
System.out.println(param2[i].toString());
}
}
Используя данный способ, можно передавать даже массивы массивов.
Естественно, внутри метода, необходимо суметь правильно определить
аргументы и соответственно использовать их.
3. В качестве альтернативы можно создать класс, содержащий все возможные
поля, которые Вы хотите передавать в метод (плюс булевские переменные
для указания, включено данное поле или нет), и сделать объект данного
класса параметром метода. Такими же способами можно возвращать
различные значения из метода; либо используя массивы, либо
объект-оболочку.
Однако, не стоит забывать и мудрые слова профессора Алана Перлиса (Alan
Perlis): "Если Ваша процедура имеет больше, чем пол-дюжины параметров, то,
вероятно, вы о чем-нибудь забыли". Передача большого количества аргументов
в функцию означает, что эта функция плохо организована.
*(Часть 6) Как возвращать различные объекты в параметре метода?
Как передать объект в метод, и заставить метод изменить ссылку так, чтобы
она указывала на другой объект при возврате в вызывающий код?
[*] Существует два способа. Очевидный путь - "просто добавить еще один
уровень в косвенную адресацию". Поместите объект в другой класс,
предназначение которого - быть переданным в качестве параметра, позволяя
модифицировать ссылку на несомый объект.
Второй способ - более понятный вариант первого. Передайте объект в
односимвольном массиве. Так как массивы сами являются объектами, то это
работает.
void jfoo(Object ref[]){
ref[0] = new Object();
}
...
Object kludge[] = new Object[1];
kludge[0]= myObj;
jfoo(kludge);
if (kludge[0] == myObj) ...
else ...
Заметьте, что изменение глобальной переменной/объекта внутри метода
является плохим стилем программирования; при этом обычно нарушаются
основные конструкции ООП.
*(Часть 6) Как сделать, чтобы метод возвращал несколько значений?
[*] Можно просто написать функцию, возвращающую Вектор. Это особенно
удобно, когда Вы не уверены в количестве возвращаемых значений, т.к. оно
зависит от происходящего в методе. Вектор по существу является динамически
расширяемым массивом. Регулярные массивы не могут увеличиваться после того,
как их объявили - приходится объявлять новый массив большей размерности и
перекидывать в него содержимое старого.
Массивы
*(Часть 6) Как разместить в памяти многомерный массив?
[*] Есть несколько способов. Если Вам необходим прямоугольный массив, то
всю память для него можно выделить за один раз. Следующий пример создает
массив 4x5:
int arr[][] = new int[4][5];
Если Вы хотите, чтобы каждый ряд содержал свое число колонок, можете
использовать тот факт, что двухразмерный массив на самом деле является
массивом массивов. Следующая часть кода размещает в памяти треугольный
массив:
int arr[][] = new int[4][]; // размещение массива из четырех рядов
for (int i = 0; i < 4; i++) // инициализация каждого ряда
arr[i] = new int[i + 1]; // ряд i содержит i+1 колонку
Заметьте, что если размещается массив любых объектов (в противоположность
примитивным типам), то все ссылки будут по умолчанию "null-ссылками",
которые при попытке разыменования могут превратиться в исключения
NullPointerException.
Другими словами, после:
int arr[] = new int[4];
можно написать
if (arr[2] == 0)
Однако, после
Integer Iarr[] = new Integer[4];
Вы должны заполнить ссылку на объект перед ее использованием. Например,
Iarr[2] = myInt;
или
arr[2] = new Int(27);
перед этим можно написать
if (Iarr[2].equals(myInt))
*(Sect. 6) Как скопировать массив?
[*] Если массив состоит из элементов одного из базовых типов или же вам
необходимо скопировать только ссылки (а не создавать копии объектов),
используйте метод
java.lang.System.arraycopy(Object src, int src_position,
Object dst, int dst_position, int length);
Если же ваша цель - создать копии объектов, вы должны создать новый массив
и написать цикл, который скопирует каждый элемент старого массива в
соответствующий ему элемент нового.
Обратите внимание: в документации на java.lang.System.arraycopy() указано,
что если src и dst ссылаются на один и тот же объект, то arraycopy() ведет
себя так, как если бы элементы исходного массива копировались во временный
массив (т.е. они сохраняются). Sun не указывает, создается ли действительно
при этом временный массив.
Другие источники:
JLS 20.18.16 {java.lang.System.arraycopy()}
*(Sect. 6) Как очистить массив?
[*] Методов для очистки массива в 0.0, 0, null, false, 'u0000' и т.п. не
существует. Когда вы создаете массив, его элементы инициализируются
значением по умолчанию (default value), но повторить автоматическую
инициализацию невозможно.
Если вам необходимо много раз устанавливать массив в одно и то же множество
значений, создайте массив-шаблон. Инициализируйте его необходимым набором
значений и используйте System.arraycopy() для копирования в рабочий массив
каждый раз, когда требуется переустановка значений рабочего массива.
*(Sect. 6) Какой наиболее быстрый путь установки значений всех элементов
Секция 3 из 7 - Предыдущая - Следующая
|