Опубликован: 01.11.2004 | Уровень: для всех | Доступ: свободно | ВУЗ: Московский государственный университет имени М.В.Ломоносова
Лекция 13:

Java: механизмы наследования, ссылочные типы данных, интерфейсы, вложенные классы

< Лекция 12 || Лекция 13: 123 || Лекция 14 >

Приведение ссылочных типов

В языке Java преобразование ссылочных типов может происходить в четырех контекстах:

  • приведение;
  • присваивание;
  • вызов метода;
  • выполнение арифметических действий.

Наиболее общим случаем является приведение.

В языке Java объявление класса определяет одноименный ссылочный тип. Все переменные, имеющие ссылочный тип, указываемый именем класса, являются объектами. Тип такого объекта определяется оператором instanceof.

Например:

String str1;
Object ObjectName;
ObjectName =(Object) str1; 
    // Приведение типа

if (ObjectName instanceof String) {
                  // Тип объекта String
    String str2 = (String) ObjectName ;
    System.out.println(str2);  
        // Запись в стандартный поток 
        // вывода значения строки, 
        // указанной параметром str2
}

В рассмотренном примере тип объекта str1 сначала приводится к типу своего косвенного суперкласса Object, а затем оператором instanceof определяется непосредственный тип объекта (при определении оператором instanceof типа объекта ObjectName как String или Object возвращается значение true ).

При приведении ссылочных типов действуют следующие правила:

  • объект всегда может быть приведен к типу своего непосредственного суперкласса;
  • приведение ссылочных типов может выполняться по иерархии классов сколь угодно глубоко;
  • любой класс ссылочного типа всегда можно привести к типу Object.

После приведения объекта к типу суперкласса все переменные и методы самого класса объекта становятся недоступными для приведенного объекта.

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

Значение простого типа не может быть присвоено значению ссылочного типа, как и значение ссылочного типа не может быть присвоено значению простого типа.

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

Например:

public class A { int x, y; }
public class ADerived extends A { int z; }
public interface B {     
    void setColor(int color);
}
public class AB extends A implements B 
{ int color;
    public void setColor(int color) { 
        this.color = color; 
    }
}
class MyA{
  public static void main(String[ ] args) {
    // Создание переменных ссылочного типа 
    // и присваивание им значения:
    A p = new A();
    p = new ADerived();    
      // Правильно: ADerived это 
      // подкласс класса A
    ADerived p3d = p;      
	  // Ошибка
  
      // Присваивание значения переменной
      // типа Object:
    Object o = p;          
      // Правильно: любой объект приводим 
      // к типу  Object
    int[ ] a = new int[3];
    Object o2 = a;
	  // Правильно: массив приводим к Object

      // Присваивание значения переменной 
      // типа интерфейса:
    AB cp = new AB();
    B c = cp;              
	  // Правильно: AB реализует интерфейс  B

      // Присваивание значения переменной 
      // типа массива:
    byte[ ] b = new byte[4];
    a = b;                 
	  // Ошибка: это массивы различных типов
    ADerived[ ] p3da = new ADerived[3];
    A[ ] pa = p3da;        
	  // Правильно: ADerived подкласс класса A
    p3da = pa;             
	  // Ошибка, т.к. необходимо приведение 
  }
}

Преобразование приведением является более общим: если преобразование возможно, то приведение может его выполнить. Часто следует явно указывать преобразование приведением, чтобы компилятор имел строгую информацию о типе объекта. Для любого типа значения времени компиляции всегда можно выполнить приведение к тому же самому типу. Это позволит точно указать, что результирующее значение будет иметь именно указанный тип.

Приведением можно преобразовывать значения одного вычислимого типа к другому. Тип boolean не может быть приведен ни к какому другому типу.

Значения простых типов не могут быть приведены к значениям ссылочных типов и наоборот.

Эквивалентность объектов

Для определения равенства различных объектов применяется метод equals.

Метод equals реализован в классе Object и соответственно наследуем любым классом Java. Большинство классов переопределяет этот метод таким образом, что позволяет сравнивать на эквивалентность объекты конкретного класса.

Например:

class A {
    String objectName;
    A (String name) { objectName = name; }
    // Конструктор
}
public class MyA {
    public static void main (String args[ ])
    {
    A A = new A("Class1");      
        // Создание экземпляра класса
    
    A A_eq = A;                 
        // Ссылка на существующий объект
    
    A A_clon = (A)A.clone;      
       // Создание объекта методом clone
    
    A A_2 = new A("Class2");
    // Сравнение объектов:
    if (A.equals(A_eq))    {  }
    if (A.equals(A_ clon)) {  }
    if (A.equals(A_ 2))    {  }
    }
}

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

Принадлежность объекта к конкретному классу проверяется с помощью оператора instanseof.

Пакеты классов JDK

Инструментальный набор JDK включает утилиты и пакеты классов.

Собственно говоря, все стандартные возможности программирования на Java базируются на классах этого инструментального набора. JDK состоит из нескольких отдельных пакетов, иногда называемых библиотеками. Различные среды программирования, такие как JBuilder, предоставляют дополнительные пакеты классов.

Среда JBuilder 8 Enterprise полностью поддерживает работу со всеми классами пакета JDK 1.4.

< Лекция 12 || Лекция 13: 123 || Лекция 14 >
Александр Демьяненко
Александр Демьяненко

Можно ли сдавать один и тот же тест несколько раз?
Или же один и тот же тест можно сдать лишь однажды?

Максим Стогний
Максим Стогний

Добрый день!

Скажите, пожалуйста, если в терминологии объектно-ориентированного программирования функции также называются методами или методами - членами класса, в примере объявления указателя на метод использовали в формальном описании оба названия:

тип_метода (имя_класса::*имя_метода_указателя)
    (список параметров);
тип_функции (*имя_ функции_указателя)
    (список параметров);

при этом можно было  тип_функции во втором описании заменить на тип_метода? Т.е.:

тип_метода (*имя_ метода_указателя)
    (список параметров);