Конструкторы. Параметризированные конструкторы. Ключевое слово this. Сборка «мусора». Метод finalize(). Присваивание ссылок на объекты

 

Конструкторы. Параметризированные конструкторы. Ключевое слово this. Сборка «мусора». Метод finalize(). Присваивание ссылок на объекты


Содержание


1. Что называется конструктором класса? Назначение конструктора

Конструктор – это специальный метод (функция) класса, который используется для создания объекта класса и начальной инициализации внутренних переменных класса. Конструктор имеет такое самое имя как и класс. В классе может быть несколько конструкторов, которые между собой отличаются параметрами. Конструктор вызывается автоматически при объявлении объекта класса.

Общая форма объявления конструктора

ClassName(parameters)
{
    // тело конструктора
    // ...
}

где

  • ClassName – имя конструктора, которое совпадает с именем класса. Конструктор не возвращает значения;
  • parameters – параметры конструктора. Конструктор может быть без параметров (по умолчанию).

2. Примеры использования конструкторов класса

Пример 1. Объявление и использование класса Month, содержащего информацию о месяце года.

В классе объявляется:

  • внутренняя, скрытая (private) переменная класса с именем month;
  • конструктор без параметров, устанавливающий значение внутренней переменной month в 1 (январь);
  • конструктор с одним параметром, инициализирующий значение переменной month начальным значением;
  • методы доступа Get(), Set() к внутренней переменной month;
  • методы Next() и Prev(), которые устанавливают следующий и предшествующий месяцы в году;
  • метод MonthStr(), возвращающий название месяца.
public class Month 
{
    // класс, который описывает месяц года
    private int month; // внутренняя переменная (ключевое слово private)

    // Объявление конструкторов класса
    // конструктор без параметров 
    Month()
    {
        month = 1; // месяц "январь" по умолчанию
    }

    // конструктор с одним параметром
    Month(int mn)
    {
        if ((mn>=1)&&(mn<=12)) // проверка, верно ли задан номер месяца 1..12
            month = mn;
        else
            month = 1;
    }

    // Методы класса
    // методы доступа
    int Get() { return month; } // взять текущий номер месяца
    void Set(int nmonth)
    {
        // установить новое значение
        if ((nmonth>=1)&&(nmonth<=12))
            month = nmonth;
    }

    // Дополнительные методы класса
    // установить следующий месяц в году
    int Next()
    {
        month++;
        if (month==13) month = 1;
        return month;
    }

    // установить предшествующий месяц в году
    int Prev()
    {
        month--;
        if (month==0) month = 12;
        return month;
    }

    // взять название месяца
    String MonthStr()
    {
        String s="";
        if (month==1) s = "Jan";
        if (month==2) s = "Feb";
        if (month==3) s = "Mar";
        if (month==4) s = "Apr";
        if (month==5) s = "May";
        if (month==6) s = "Jun";
        if (month==7) s = "Jul";
        if (month==8) s = "Aug";
        if (month==9) s = "Sep";
        if (month==10) s = "Oct";
        if (month==11) s = "Nov";
        if (month==12) s = "Dec";
        return s;
    }
}

Использование класса в другой функции:

Month m1 = new Month(); // вызов конструктора без параметров
int d;
String s;

d = m1.Get(); // d = 1
d = m1.Prev(); // d = 12
s = m1.MonthStr(); // s = "Dec"

Month m2 = new Month(5); // вызов конструктора с 1 параметром
d = m2.Get(); // d = 5
m2.Next();
s = m2.MonthStr(); // s = "Jun"
m2.Set(9);
s = m2.MonthStr(); // s = "Sep"

Пример 2. Пусть задан класс MyRect, описывающий прямоугольник. Для прямоугольника задаются следующие внутренние переменные:

  • координаты x, y левого верхнего угла экрана;
  • длины сторон dx, dy прямоугольника.
  • в классе реализованы 3 конструктора и 6 методов:
  • конструктор без параметров;
  • конструктор с 2 параметрами (параметризированный конструктор);
  • конструктор с 4 параметрами (параметризированный конструктор);
  • методы чтения значений внутренних переменных GetX(), GetY(), GetDX(), GetDY();
  • метод Set(), устанавливающий новые значения внутренних переменных;
  • метод Square(), вычисляющий площадь прямоугольника.
public class MyRect 
{
    // внутренние переменные класса
    private int x, y, dx , dy; // скрытые - ключевое слово private

    // Конструкторы класса
    // конструктор без параметров
    MyRect()
    {
        x = 0;
        y = 0;
        dx = 1;
        dy = 1;
    }

    // параметризированный конструктор с двумя параметрами
    MyRect(int dx, int dy)
    {
        this.dx = dx;
        this.dy = dy;
        x = 0;
        y = 0;
    }

    // параметризированный конструктор с 4 параметрами
    MyRect(int nx, int ny, int ndx, int ndy)
    {
        x = nx;
        y = ny;
        dx = ndx;
        dy = ndy;
    }

    // Методы класса
    // чтение внутренних данных класса
    int GetX() { return x; }
    int GetY() { return y; }
    int GetDX() { return dx; }
    int GetDY() { return dy; }

    // запись новых значений во внутренние данные класса
    void Set(int nx, int ny, int ndx, int ndy)
    {
        x = nx;
        y = ny;
        dx = ndx;
        dy = ndy;
    }

    // метод, который вычисляет площадь прямоугольника
    int Square()
    {
        return (int)(dx*dy);
    }
}

 В параметризированном конструкторе с 2 параметрами на вход поступают внутренние параметры с именами dx, dy. Такие самые имена имеют внутренние переменные класса. Чтобы доступиться к внутренним переменным класса за пределами тела конструктора, используется ключевое слово this:

...
this.dx = dx;
this.dy = dy;
...

Использование класса в другом программном коде (например, функции main):

// использование класса
MyRect r1 = new MyRect(); // вызов конструктора без параметров
int d;

// проверка
d = r1.GetDX(); // d = 1

r1.Set(5, 6, 2, 3); // вызов метода Set() класса
int s = r1.Square(); // s = 6 - площадь прямоугольника

// вызов конструктора с 2 параметрами
MyRect r2 = new MyRect(5,4);
d = r2.GetX(); // d = 0
d = r2.GetDY(); // d = 4

// вызов конструктора с 4 параметрами
MyRect r3 = new MyRect(2,3,8,9);
d = r3.GetDY(); // d = 9
d = r3.Square(); // d = 72 - площадь, метод Square()

3. Что такое параметризированные конструкторы?

Параметризированные конструкторы – это конструкторы, получающие параметры.

4. Для чего используется ключевое слово this? Пример

Ключевое слово this используется для того, чтобы получить в методе ссылку на объект, который его вызвал. Ключевое слово this можно использовать в теле любого метода для ссылки на текущий объект.

Пример. Пусть дан класс DWeek, описывающий (реализующий) день недели.

В классе объявляется:

  • внутренняя переменная day;
  • конструктор без параметров;
  • конструктор с 1 параметром;
  • методы доступа Get() и Set();
  • метод IsDayOff(), определяющий, выходной этот день или нет.
// Класс, который описывает день недели
public class DWeek 
{
    // внутренняя скрытая (private) переменная day
    private int day;

    // Конструкторы класса
    DWeek() // конструктор без параметров
    {
        day = 1; // Понедельник
    }

    // конструктор с 1 параметром
    DWeek(int day)
    {
        // доступ к переменной-экземпляру класса day с помощью ключевого слова this
        if ((day>=1)&&(day<=7))
            this.day = day;
    }

    // методы доступа
    int Get() { return day; }

    void Set(int day)
    {
        // доступ к переменной экземпляру: this.day
        if ((day>=1)&&(day<=7))
            this.day = day;
    }

    // метод, который определяет, выходной этот день или нет
    boolean IsDayOff()
    {
        int d; // внутренняя переменная

        // вызов метода Get() класса с помощью ключевого слова this
        d = this.Get(); // взять текущий день

        boolean b = true;
        if ((d>=1)&&(d<=5)) b = false;
            return b;
    }
}

В конструкторе с 1 параметром входной параметр имеет такое же имя как и внутренняя переменная класса day. Поэтому, чтобы доступиться к переменной-экземпляру класса day используется ключевое слово this:

// конструктор с 1 параметром
DWeek(int day)
{
    // доступ к переменной-экземпляру класса day с помощью ключевого слова this
    this.day = day;
}

Это же касается и метода Set(), в котором имя входного параметра совпадает с именем экземпляра класса. В этих двух случаях использование ключевого слова this есть эффективным. Конечно, при желании можно изменить имя входного параметра и обойтись без слова this.

В методе IsDayOff() для доступа к методу Get() используется ключевое слово this (в демонстрационных целях).

Использование класса в другом методе

public static void main(String[] args) 
{
    // использование класса DWeek
    DWeek dw1 = new DWeek(); // вызов конструктора без параметров
    boolean b;
    int d;

    b = dw1.IsDayOff(); // b = false
    d = dw1.Get(); // d = 1

    DWeek dw2 = new DWeek(7);
    b = dw2.IsDayOff(); // b = true
    dw2.Set(4);
    d = dw2.Get(); // d = 4
    b = dw2.IsDayOff(); // b = false

    System.out.println(d);
}

5. Что означает термин «сборка мусора»? Как происходит «сборка мусора»?

«Сборка мусора» – это автоматическое уничтожение объектов в оперативной памяти, которые больше не используются в программе. «Сборка мусора» используется для освобождения памяти под объекты, которые еще существуют в программе и больше не используются. В языке Java уничтожать объекты явным образом не нужно. Разные реализации Java используют разные подходы к «сборке мусора».



6. Какое назначение метода finalize() в Java?

В методе finalize() указываются действия, которое должны быть выполнены перед уничтожением объекта. Это могут быть, например, сохранение промежуточных данных/результатов, уничтожение дескриптора файла и т.д.

Если метод finalize() определен в классе, то он вызывается перед тем как должен быть уничтожен объект класса «сборщиком мусора». Эта процедура выглядит приблизительно так:

  • «сборщик мусора» время от времени запускается и проверяет наличие объектов, на которые отсутствуют ссылки. Эти объекты нужно удалить;
  • для найденных объектов сначала вызывается метод finalize(), если он определен в классе. В этом методе выполняются соответствующие действия по освобождению «отличных от Java» ресурсов;
  • удаляется найденный объект.

Метод finalize() имеет следующий общий вид:

protected void finalize()
{
    // тело метода
    // ...
}

Этот метод должен быть объявлен в классе, например:

class MyClass
{
    // ...

    protected void finalize()
    {
        // ...
    }

    // ...
}

 

7. Каким образом реализуется присваивание переменным ссылок на объекты класса?

Если объявлены две переменные (два объекта) некоторого класса с именами v1 и v2 и для переменной v1 выделена память оператором new, то строка

v2 = v1;

будет означать следующее:

  • переменная v2 содержит ссылку на объект v1;
  • переменные v2 и v1 ссылаются на одну и ту же область памяти. Это означает, что память для переменной v2 не выделяется. Изменения по ссылке в переменной v1 приведут к одним и тем же изменениям в переменной v2 (и наоборот);
  • эти переменные не связаны между собой. То есть, если изменить значение одной из переменных, то это не повлияет на значение другой переменной (другая переменная останется ссылаться на исходный объект).


Связанные темы