
- •Глава 2
- •Глава 2. Обзор языка Java 31_
- •Глава 2. Обзор языка Java
- •Глава 2. Обзор языка Java 37
- •Глава 2. Обзор языка Java 39
- •Глава 2. Обзор языка Java 41
- •Часть I. Язык Java
- •Глава 2. Обзор языка Java 43_
- •Глава 2. Обзор языка Java 45_
- •Глава 2. Обзор языка Java 47
- •Глава 2. Обзор языка Java 49_
- •Часть I. Язык Java
- •Глава 2. Обзор языка Java 57
- •Глава 3
- •Глава 3. Типы данных, переменные и массивы 53
- •Глава 3. Типы данных, переменные и массивы _ 55
- •Глава 3. Типы данных, переменные и массивы
- •Глава 3. Типы данных, переменные и массивы 59_
- •Глава 3. Типы данных, переменные и массивы 61_
- •Глава 3. Типы данных, переменные и массивы
- •Глава 3. Типы данных, переменные и массивы 65_
- •Часть I. Язык Java
- •Глава 3. Типы данных, переменные и массивы 67_
- •Часть I. Язык Java
- •Глава 3. Типы данных, переменные и массивы 69_
- •Глава 3. Типы данных, переменные и массивы 71_
- •Глава 3. Типы данных, переменные и массивы 73_
- •Глава 3. Типы данных, переменные и массивы
- •Часть I. Язык Java
- •Глава 3. Типы данных, переменные и массивы _ 77_ Эта программа генерирует следующий вывод:
- •Глава 3. Типы данных, переменные и массивы 79
- •Часть I. Язык Java
- •Глава 3. Типы данных, переменные и массивы 81_
- •Глава 4
- •Глава 4. Операции 83
- •84 Часть I. Язык Java
- •Глава 4. Операции 85_
- •Глава 4. Операции 87_
- •88_ Часть I. Язык Java
- •Глава 4. Операции 89
- •Глава 4. Операции 91_
- •Глава 4. Операции 93_
- •Глава 4. Операции 95_
- •Глава 4. Операции 97_
- •Глава 4. Операции 99
- •Глава 4. Операции 101
- •Глава 4. Операции 103
- •104 Часть I, Язык Java
- •Глава 4. Операции 105
- •Глава 5
- •Глава 5, Управляющие операторы 107
- •Глава 5. Управляющие операторы 109
- •110 Часть I. Язык Java
- •Глава 5, Управляющие операторы 111
- •Глава 5. Управляющие операторы 113
- •Глава 5. Управляющие операторы
- •Глава 5. Управляющие операторы 117
- •118 Часть I. Язык Java
- •Глава 5. Управляющие операторы 119
- •Глава 5. Управляющие операторы 121
- •122 Часть I. Язык Java
- •Глава 5. Управляющие операторы 123
- •Глава 5. Управляющие операторы 125
- •Глава 5. Управляющие операторы 127
- •Глава 5. Управляющие операторы 129
- •Глава 5. Управляющие операторы
- •Глава 6
- •134 Часть I. Язык Java
- •Глава 6. Введение в классы 135
- •136 Часть I. Язык Java
- •Глава 6. Введение в классы _ 137
- •Глава 6. Введение в классы 139
- •Глава 6. Введение в классы
- •Глава 6. Введение в классы 143
- •Глава 6. Введение в классы 145
- •Глава 6. Введение в классы 147
- •Глава 6. Введение в классы 149
- •Глава 6. Введение в классы 151
- •154 Часть I. Язык Java
- •Глава 6. Введение в классы 155
- •Глава 6. Введение в классы 157
- •Глава 7
- •Глава 7. Методы и классы 159
- •Глава 7. Методы и классы . 161
- •Глава 7. Методы и классы • 163
- •164 Часть I. Язык Java
- •Глава 7. Методы и классы 165
- •Глава 7. Методы и классы 167
- •Глава 7. Методы и классы 169
- •Глава 7, Методы и классы 171-
- •Глава 7. Методы и классы 173
- •Глава 7. Методы и классы 775
- •Глава 7. Методы и классы 177
- •Глава 7. Методы и классы ' 179
- •Глава 7. Методы и классы 1_81_
- •Глава 7. Методы и классы 1_83
- •184 '• Часть I. Язык Java
- •Глава 7. Методы и классы . 185
- •Глава 7. Методы и классы 187
- •Глава 8
- •Глава 8. Наследование 191
- •Глава 8. Наследование 193
- •Глава 8, Наследование 195
- •Глава 8. Наследование 197
- •198 Часть I. Язык Java
- •Глава 8, Наследование 199
- •Глава 8. Наследование 201
- •202 Часть I. Язык Java
- •Глава 8. Наследование 203
- •Глава 8. Наследование 205
- •Глава 8. Наследование 207
- •Глава 8. Наследование 209
- •Глава 8. Наследование 211
- •Глава 8. Наследование 213
- •Глава 8. Наследование 215
- •Глава 8. Наследование 217
- •Глава 12
- •Глава 12. Ввод/вывод, апплеты и другие темы 303_
- •Глава 12. Ввод/вывод, апплеты и другие темы . 305
- •Глава 12. Ввод/вывод, алплеты и другие темы 307
- •Глава 12. Ввод/вывод, апплеты и другие темы 309
- •Глава 12. Ввод/вывод, апплеты и другие темы 311
- •Глава 12. Ввод/вывод, апплаты и другие темы 313
- •314 Часть I. Язык Java
- •Глава 12. Ввод/вывод, апплеты и другие темы 315
- •Глава 12. Ввод/вывод, апплеты и другие темы 317
- •Глава 12. Ввод/вывод, апплеты и другие темы 319
- •320 Часть I. Язык Java
- •Глава 12. Ввод/вывод, апплеты и другие темы 321
- •Глава 12. Ввод/вывод, апплеты и другие темы 323
- •324 Часть I. Язык Java
- •Глава 12. Ввод/вывод, апплеты и другие темы 325
- •326 Часть I. Язык Java
- •Глава 12. Ввод/вывод, апплегы и другие темы 327
Глава 8. Наследование 205
// Демонстрирует порядок вызова конструкторов.
// Создать суперкласс А. class A { А() {
System.out.println("Внутри А-конструктора."); } }
// Создать подкласс В расширением А. class В extends A { ВО {
System.out.println("Внутри В-конструктора."); } }
// Создать другой класс (С), расширяющий В. class С extends В { СО {
System.out.println("Внутри С-конструктора."); }
}
class CallingCons {
public static void main(String args[]) {
С с = new С(); } }
Вывод этой программы:
Внутри А-конструктора. Внутри В-конструктора. Внутри С-конструктора.
Не трудно видеть, что конструкторы вызываются в порядке подчиненности классов.
Если подумать, то выполнение функций конструкторов в порядке подчиненности классов имеет определенный смысл. Поскольку суперкласс не имеет никакого знания о каком-либо подклассе, любая инициализация, которую ему нужно выполнить, является отдельной и, по возможности, предшествующей любой инициализации, выполняемой подклассом. Поэтому-то она и должна выполняться первой.
Переопределение методов
В иерархии классов, если метод в подклассе имеет такое же имя и сигнатуру типов (type signature), как метод в его суперклассе, говорят, что метод в под-
206 Часть I. Язык Java
классе переопределяет (override) метод в суперклассе. Когда переопределенный метод вызывается в подклассе, он будет всегда обращаться к версии этого метода, определенной подклассом. Версия метода, определенная суперклассом, будет скрыта. Рассмотрим следующий фрагмент:
// Переопределение методов. class A {
int i, j; *
A(int a, int b) {
i = a;
j = b; •
} • •
// показать i и j на экране void show() {
System.out.println)"! и j: " + i + " " + j); } }
class В extends A { int k;
В(int a, int b, int c) {
super(a, b);
k = c; }
// Показать на экране k (этот show() переопределяет show() из А) void show() {
System.out.println("k: " + k) ; } }
class Override {
public static void main(String args[]) { В subOb = new В (1, 2, 3) ;
subOb.show(); // здесь вызывается show() из В
} }
Вывод этой программы:
k: 3
Когда show () вызвается для объекта типа в, используется версия show (), определенная в классе в. То есть версия show () внутри в переопределяет (отменяет) версию, объявленную в а.
Если нужно обратиться к версии суперкласса переопределенной функции, то можно сделать это, используя super. Например, в следующей версии под-
Глава 8. Наследование 207
класс в вызывается show о версия суперкласса а. Это позволяет отобразить все экземплярные переменные.
class В extends A { int k;
B(int a, int b, int с) {
super(a, b);
k = c; }
void show() {
super.show(); // вызов show() суперкласса А
System.out.println("k: " + k) ; } }
Если вы замените этой версией класс в предыдущей программы, то получите следующий вывод:
i и j : 1 2 k: 3
Здесь super, show о вызывает версию show о суперкласса.
Переопределение метода происходит только тогда, когда имена и сигнатуры типов этих двух методов идентичны. Если это не так, то оба метода просто перегружены. Например, рассмотрим следующую модифицированную версию предыдущего примера:
// Методы с различными сигнатурами типов перегружаются, // а не переопределяются, class A { int i, j;
A(int a, int b) {
i - a;
j = b; }
// Показать i и j void show(} {
System.out.println("i и j: " + i + " " + j); } }
// Создать подкласс В расширением класса А. class B extends A { int k;
208 Часть I. Язык Java
B(int a, int b, int c) { . •
super(a, b) ;
k = c; }
// Перегруженный sliowf) void show(String msg) {
System.out.println(msg + k) ; }
} • . • '
class Override {
public static void main(String args[]) { В subOb = new B(l, 2, 3);
subOb.show("Это k: "); // вызов show() класса В
subOb. show () ; ' /'/ вызов show () класса А
} }
Вывод этой программы:
Это k: 3 i и j : 1 2
Версия show о в классе в имеет строчный параметр. Это делает сигнатуру его типов отличной от класса а, который не имеет никаких параметров. Поэтому никакого переопределения (или скрытия имени) нет.
Динамическая диспетчеризация методов
В то время как примеры в предшествующем разделе демонстрируют механику переопределения метода, они не показывают всей мощи этой методики. Действительно, если бы в методике переопределения не имелось бы ничего кроме соглашения о пространстве имен, то это был бы, в лучшем случае, интересный курьез, но он не имел бы большого реального значения. Однако дело обстоит иначе. Методика переопределения формирует основу для одной из наиболее мощных концепций Java — динамической диспетчеризации методов. Динамическая диспетчеризация методов это механизм, с помощью которого решение на вызов переопределенной функции принимается во время выполнения, а не во время компиляции. Динамическая диспетчеризация методов важна потому, что таким способом Java реализует полиморфизм времени выполнения.
Начнем с повторения важного принципа: ссылочная переменная суперкласса может обращаться к объекту подкласса. Java использует этот факт, чтобы принимать решения о вызове переопределенных методов во время выполнения. Вот как это делается. Когда переопределенный метод вызывается через