1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/wizardforcel-thinking-in-java-zh

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
6.1 组合的语法.md 7.9 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 11.03.2025 09:15 d56454c

6.1 Грамматика композиции

По предыдущим занятиям можно заметить, что фактически уже несколько раз выполнялись операции "компоновки". Для выполнения компоновки достаточно просто поместить ссылки на объекты в новый класс. Например, предположим, что нам требуется хранить несколько объектов типа String, два примитивных типа данных и один объект другого класса внутри одного объекта. Для неприситивных типов данных достаточно поместить ссылки на них в новый класс, а для примитивных типов данных следует объявить их в своём классе. Пример представлен ниже (если возникают проблемы при запуске программы, обратитесь к разделу 3.1.2 главы 3 "Присваивание").

//: SprinklerSystem.java
// Композиция для повторного использования кода
package c06;

class WaterSource {
  private String s;
  WaterSource() {
    System.out.println("WaterSource()");
    s = new String("Создано");
  }
  public String toString() { return s; }
}

public class SprinklerSystem {
  private String valve1, valve2, valve3, valve4;
  WaterSource source;
  int i;
  float f;
  void print() {
    System.out.println("valve1 = " + valve1);
    System.out.println("valve2 = " + valve2);
    System.out.println("valve3 = " + valve3);
    System.out.println("valve4 = " + valve4);
    System.out.println("i = " + i);
    System.out.println("f = " + f);
    System.out.println("source = " + source);
  }
  public static void main(String[] args) {
    SprinklerSystem x = new SprinklerSystem();
    x.print();
  }
} ///:~
```Метод `toString()` внутри класса `WaterSource` является особенным. Каждый объект непростого типа имеет метод `toString()`. Если компилятор ожидал получить значение типа `String`, но получил объект данного типа, он будет вызывать этот метод. Поэтому в следующем выражении:```java
System.out.println("источник = " + источник);

Компилятор обнаруживает попытку сложения строки с объектом типа WaterSource (источник =). Это недопустимо, так как мы можем складывать только строки, поэтому компилятор говорит: "Я вызову toString(), чтобы преобразовать источник в строку!" После этого он может скомпилировать две строки и передать результирующую строку методу System.out.println(). В каждом случае, когда вы позволяете этому поведению, вам нужно реализовать метод toString().

Если не углубляться в детали, можно легко ошибочно полагать, что компилятор автоматически создаёт объект для каждого обращения к нему (в силу образа Java как безопасного и осторожного языка программирования). Например, может показаться, что он вызывает конструктор по умолчанию для WaterSource, чтобы инициализировать источник. Однако фактический вывод команды печати выглядит следующим образом:

valve1 = null
valve2 = null
valve3 = null
valve4 = null
i = 0
f = 0.0
источник = null

Как указано в главе 2, базовые данные, используемые как поля внутри класса, инициализируются нулем. В то же время, ссылки на объекты инициализируются значением null. При попытке вызвать метод для любого из этих объектов будет выброшено исключение. Такое поведение является вполне нормальным (и полезным): мы можем распечатать эти значения без генерации исключения.Компилятор не создаёт по умолчанию объект для каждой ссылки, так как это привело бы к неоправданному увеличению затрат в большинстве случаев. Если требуется инициализация ссылок, это можно сделать в следующих местах:

(1) В момент определения поля. Это означает, что они будут инициализированы до вызова конструктора.

(2) В самом конструкторе класса.

(3) Непосредственно перед тем, как использовать объект. Это позволяет минимизировать необоснованные затраты — если объект не нужен, его создание можно избежать.

Далее представлен пример всех трёх способов инициализации:

//: Bath.java
// Инициализация конструктором с использованием композиции

class Soap {
  private String s;
  Soap() {
    System.out.println("Soap()");
    s = new String("Создан");
  }
  public String toString() { return s; }
}
``````public class Bath {
  private String
    // Инициализация при определении:
    s1 = new String("Счастливый"),
    s2 = "Счастливый",
    s3, s4;
  Soap castille;
  int i;
  float toy;
  Bath() {
    System.out.println("Внутри Bath()");
    s3 = new String("Радость");
    i = 47;
    toy = 3.14f;
    castille = new Soap();
  }
  void print() {
    // Отложенная инициализация:
    if(s4 == null)
      s4 = new String("Радость");
    System.out.println("s1 = " + s1);
    System.out.println("s2 = " + s2);
    System.out.println("s3 = " + s3);
    System.out.println("s4 = " + s4);
    System.out.println("i = " + i);
    System.out.println("toy = " + toy);
    System.out.println("castille = " + castille);
  }
  public static void main(String[] args) {
    Bath b = new Bath();
    b.print();
  }
} ///:~

Обратите внимание, что в конструкторе `Bath` перед началом всех инициализаций выполняется один оператор. Если инициализация не происходит при определении, это всё ещё не гарантирует выполнение какой-либо инициализации до отправки сообщения объектному ссылочному значению  за исключением непредотвратимых исключений времени выполнения.
```Вот вывод программы:

```markdown
Внутри Bath()
Soap()
s1 = Happy
s2 = Happy
s3 = Joy
s4 = Joy
i = 47
toy = 3.14
castille = Constructed

При вызове print(), он заполняет s4, обеспечивая правильную инициализацию всех полей перед их использованием.

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/wizardforcel-thinking-in-java-zh.git
git@api.gitlife.ru:oschina-mirror/wizardforcel-thinking-in-java-zh.git
oschina-mirror
wizardforcel-thinking-in-java-zh
wizardforcel-thinking-in-java-zh
master