Программирование на JAVA

Навигация

Лекция 1. Что такое Java? История создания

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

Лекция 2. Основы объектно-ориентированного программирования

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

Лекция 3. Лексика языка

51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68

Лекция 4. Типы данных

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

Лекция 5. Имена. Пакеты

90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108

Лекция 6. Объявление классов

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128

Лекция 7. Преобразование типов

129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144

Лекция 8. Объектная модель в Java

145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160

Лекция 9. Массивы

161 162 163 164 165 166 167 168 169 170 171 172 173 174

Лекция 10. Операторы и структура кода. Исключения

175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195

Лекция 11. Пакет java.awt

196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224

Лекция 12. Потоки выполнения. Синхронизация

225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241

Лекция 13. Пакет java.lang

242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260

Лекция 14. Пакет java.util

261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286

Лекция 15. Пакет java.io

287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314

Лекция 16. Введение в сетевые протоколы

315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344

}

public void test() { int x=3; x=double(x);

}

Перейдем к ссылочным типам.

public void process(Point p) { p.x=3;

}

public void test() {

Point p = new Point(1,2);

process(p);

print(p.x);

}

Ссылочная переменная хранит ссылку на объект, находящийся в па­мяти виртуальной машины. Поэтому аргумент метода processo будет иметь в качестве значения ту же самую ссылку и, стало быть, ссылаться на тот же самый объект. Изменения состояния объекта, осуществленные с по-мошью одной ссылки, всегда видны при обращении к этому объекту с по­мощью другой. Поэтому результатом примера будет значение 3. Объектные значения передаются в Java по ссылке.

Однако если изменять не состояние объекта, а саму ссылку, то ре­зультат будет другим:

public void process(Point p) { p = new Point(4,5);

}

public void test() {

Point p = new Point(1,2);

process(p);

print(p.x);

}

В этом примере аргумент метода processo после присвоения начи­нает ссылаться на другой объект, нежели исходная переменная p, а зна­чит, результатом примера станет значение 1. Можно сказать, что ссылоч­ные величины передаются по значению, но значением является именно ссылка на объект.

Теперь можно уточнить, что означает возможность объявлять пара­метры методов и конструкторов как final. Поскольку изменения значений параметров (но не объектов, на которые они ссылаются) никак не сказы­ваются на переменных вне метода, модификатор final говорит лишь о том, что значение этого параметра не будет меняться на протяжении работы метода. Разумеется, для аргумента final Point р выражение р.х=5 является допустимым (запрещается p=new Point(5, 5)).

Перегруженные методы

Перегруженными (overloading) методами называются методы одного класса с одинаковыми именами. Сигнатуры у них должны быть различ­ными и различие может быть только в наборе аргументов.

Если в классе параметры перегруженных методов заметно различа­йся: например, у одного метода один параметр, у другого - два, то для ava это совершенно независимые методы и совпадение их имен может служить только для повышения наглядности работы класса. Каждый вы-3ов> в зависимости от количества параметров, однозначно адресуется то-МУ Или иному методу.

Однако если количество параметров одинаковое, а типы их различа­ются незначительно, при вызове может сложиться двойственная ситуа­ция, когда несколько перегруженных методов одинаково хорошо подхо­дят для использования. Например, если объявлены типы Parent и Child, где Child расширяет Parent, то для следующих двух методов:

void process(Parent р, Child с) {} void process(Child с, Parent p) {}

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

process(new Child(), new Child());

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

process(Object о) {} process(String s) {}

и примеры вызовов:

process(new Objecto); process(new Point(4,5)); process("abc");

Очевидно, что для первых двух вызовов подходит только первый метод, и именно он будет вызван. Для последнего же вызова подходят оба перегру­женных метода, однако класс String является более "специфичным", или узким, чем класс Object. Действительно, значения типа String можно пе­редавать в качестве аргументов типа Object, обратное же неверно. Компи­лятор попытается отыскать наиболее специфичный метод, подходящий для указанных параметров, и вызовет именно его. Поэтому при третьем вы­зове будет использован второй метод.

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

process((Parent)(new Child()), new Child()); // или

process(new Child(),(Parent)(new Child()));

Это верно и в случае использования значения null:

process((Parent)null, null); // или

process(null,(Parent)null);

Заключение

В этой лекции началось рассмотрение ключевой конструкции языка Java — объявление класса.

Первая тема посвящена средствам разграничения доступа. Главный вопрос — для чего этот механизм вводится в практически каждом совре­менном языке высокого уровня. Необходимо понимать, что он предназ­начен не для обеспечения "безопасности" или "защиты" объекта от неких неправильных действий. Самая важная задача — разделить внешний ин­терфейс класса и детали его реализации с тем, чтобы в дальнейшем вос­пользоваться такими преимуществами ООП, как инкапсуляция и модуль­ность.

Затем были рассмотрены все четыре модификатора доступа, а также возможность их применения для различных элементов языка. Проверка уровня доступа выполняется уже во время компиляции и запрещает лишь явное использование типов. Например, с ними все же можно работать че­рез их более открытых наследников.

Объявление класса состоит из заголовка и тела класса. Формат заго­ловка был подробно описан. Для изучения тела класса необходимо вспомнить понятие элементов (members) класса. Ими могут быть поля, методы и внутренние типы. Для методов важным понятием является сиг­натура.

Кроме того, в теле класса объявляются конструкторы и инициализа­торы. Поскольку они не являются элементами, к ним нельзя обратиться явно, они вызываются самой виртуальной машиной. Также конструкторы и инициализаторы не передаются по наследству.

Дополнительно был рассмотрен метод main, который вызывается пРи старте виртуальной машины. Далее описываются тонкости, возника­ющие при передаче параметров, и связанный с этим вопрос о перегру-Женных методах.

Классы Java мы продолжим рассматривать в следующих лекциях.

Вариант 1

1.   Какие модификаторы позволяют обращаться к элементу из классов того же пакета?

О     public

О      protected

|~1   по умолчанию

fjj    private

2.   Корректен ли следующий код? public class Test { private int id; public Test(int i) {

id=i;

}

public static boolean test(Test t, int id) { return t.id==id;

}

}

□   да, так как метод test является элементом класса Test

П   нет, так как поле id объявлено как private, а значит недоступно извне объекта

3.   Как записывается заголовок метода main?

G   public int main()

П   public int main(String[] args)

G   public static void main(String[] args)

П   public void main()

Вариант 2

1.      Если в классе заводится новый элемент и пока нет никаких факторов, позволяющих выбрать тот или иной модификатор доступа, какой модификатор следует использовать?

О   public

П   protected

Г~!   по умолчанию

□       private

2.       Если метод использует переменную класса, должна ли она быть объявлена выше объявления метода?

□ да

□ нет

3.       Может ли измениться содержимое переменной типа String, если передать ее в качестве аргумента при вызове метода?

□ да

□ нет

Вариант 3

1.      Пусть класс User описывает пользователя системы. В качестве имени используется его e-mail адрес, который всем известен, а пароль, конечно, не должен быть доступен никому, кроме самого пользователя. Корректна ли следующая реализация?

public class User {

public String login; // e-mail private String password; // пароль

}

П   код некорректен

f~|   код корректен с точки зрения компилятора, но, скорее всего, неверен с позиций ООП; лучше ограничить доступ к переменной login с помощью метода getLogin(), чтобы значение переменной не могло измениться непредсказуемо

П   код полностью верен

2.      Может ли класс не иметь ни одного конструктора?

□   да О   нет

3.      Какие заголовки методов являются корректными с точки зрения компилятора?

П     public void getX()

П     static private int setY()

П     public void static main (String s[])

П     String toString(final int x)