• ,

Уровень 14: план уровня и доп. материалы

План уровня:
  • Приведение типов, instanceof. Большая задача на интерфейсы.
  • instanceof
  • Приведение ссылочных типов: расширение и сужение. type cast
  • Singleton pattern

Курс Java

Что еще можно посмотреть на досуге:
«Информация о типах» в Thinking in java
RTTI — run-time type identification
Преобразование ссылочных типов или спящий волк на клавиатуре

habrahabr.ru/post/27108/
docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.6
docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.5



Нашли классную ссылку к материалу данной темы? Добавьте ее сюда в виде комментария.
Возможно, именно Ваша ссылка поможет другому человеку стать программистом и улучшить свою жизнь!

Вернуться к плану обучения

Вернуться к обучению java онлайн на JavaRush

54 комментария

senyuk
А может быть у кого-нибудь есть ещё, что почитать про:
Приведение ссылочных типов: расширение и сужение.
?
GBarkhatov
Часть информации про сужение и расширение, описанное в этой лекции — полный бред. Здесь описаны правильные определения.
docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.6
docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.5
OceanBee
Ссылка на отличный материал по Singleton Pattern с примером использования (на английском)
Your text to link...
olenenok
И добавлю еще ссылочку по Singleton Pattern, коротко и понятно. habrahabr.ru/post/27108/
Как-то странно, в лекции про этот паттерн ничего, ссылок никаких. Ищем сами))
aleczander
В лекции 3 на 14-м уровне говорится
Движение вверх по цепочке наследования называется сужением
но в других материалах, например, тут, говорится обратное, что более логично. Поправьте, пожалуйста, чтоб не сеять путаницу в неокрепших еще умах)
gnev
Действительно, похоже ты прав:
A widening reference conversion exists from any reference type S to any reference type T, provided S is a subtype (§4.10) of T.

...the narrowing reference conversions:
1. From any reference type S to any reference type T, provided that S is a proper supertype of T


пункты 5.1.5 и 5.1.6.
Izhak
Здесь бы больше подошло вымя

Собака

|Немецкая борзая| Пудель| Белый Бим чёрное ухо|...| гончая|
Lam-lam
Как я понимаю сужение — это в том плане, что становятся недоступными методы «немецкой борзой». Ведь не зря же используется слово «extends» при наследовании. Что дословно означает «расширяет».
Pavel255
  • Pavel255
  • 0
  • Комментарий отредактирован 2015-11-06 20:07:28 пользователем Pavel255
Вот и я тоже заметил это. На том же интуите (7.Лекция: Преобразование типов) расширение типа трактуется ровно наоборот, чем в лекцих JR.
Там еще запоминать легко было, что как для примитивных типов, так и ссылочных, при расширении не требуется явно указывать в скобках тип, к которому преобразуем. Ну и вроде как логично, что родительский класс охватывает все дочерние, т.е шире в этом смысле.
В итоге упоминание в лекциях обратной формулировки несколько сбивает, хотя понятно, что здесь уже имеется ввиду расширенный набор методов, доступный у объектов дочерних классов (отсюда и «extends»).
Как компромисс, можно использовать термин из «Философии java» — восходящее/нисходящее преобразование, тогда нет этой двусмысленности.
Pavel255
Оказывается по этому поводу уже есть целая дискуссия в статье про спящего на клавиатуре волка))
GDove
13 глава в Thinking in java, как пуля в висок — выносит мозг начисто.
Мне просто интересно это действительно на столько труднопонимаемо, или же это спостобность автора писать сложно о простых вещах?
blacky
Автор тут не при чем. В конечном 4-м издании, переведенном на русский, редакторы убрали:
* главы — Strings, Generics, Containers in Depth, Enumeration types, Annotations, GUI
* абсолютно все задачи
Это о многом говорит. Это почти полкниги. Красноречивы и отзывы на ozon`е.
В общем и целом по содержанию книга не плохая.
GDove
я вообще собирался почитать эту книгу в оригинале, после завершения 27(сколько там сейчас) уровней. закрепить полученные знания и уже в большей степени уделить внимание ньюансам. кроме того я часто замечаю крутые неточности в переводах =) поэтому, когда есть время, надо читать оригиналы
blacky
После 27-го ты спокойно будешь цитировать спецификацию Java и создавать достойные архитектурные решения =)

Вообще, спецификация языка достаточно доступно написана плюс к ней java tutorials очень хороши — все из первых рук. Есть интересная статья «4 Things I Wish I Would Have Known When I Started My Software Development Career», в которой упоминаются книги «Code Complete» и «Clean Code», а также
There is no “right way” in software development

Reading a book cover-to-cover is not the best way to learn

Community is extremely important in your software development career

Pavel255
Мне тоже кажется сложноватой подача материала в этой книге, рассчитана на более опытных пользователей. Прочитал пока половину 13 главы, но пришлось скопировать код классов в свой проект, чтобы разобраться. По рефлексии нашел хороший материал, там все четко и по существу, доступно изложено и намного короче. Может кому-то пригодится, вот ссылка:

by-bismark.net.ua/java-refleksiya
GDove
Мы все читали несколько ранее, что instanceof самый медленный оператор.
у меня вопрос, что лучше использовать в программе:
1) String name = object.getClass().getSimpleName();
if( «Vasya».equals(name)){
doSmth();
}
2)if(object instanseof Vasya) doSmth();
blacky
По поводу заметок об использовании instanceof мне нравится статья хабра «маленькие хитрости Java»
Старайтесь как можно реже использовать оператор instanceOf.

Почти всегда полиморфизм способен помочь избавится от этого оператора.
P. S. Многие в комментариях аппелируют к «Это один из самых медленных java операторов». Это действительно так. Конечно, не совсем корректно сравнивать операторы языка по производительности, так как они выполняют абсолютно разные задачи, но, тем не менее, механизм работы instanceOf гораздо сложнее, например, оператора '*'.

Боятся instanceof тоже не стоит, где-то была работа где изучались разные виды multiple dispatch. Все эти двойные коллбеки аля визитор, instanceof и прочие полиморфизмы. instanceof по перформансу был одним из самых быстрых. Опять же проблема тут не в перформансе, а скорее в поддерживаемости кода.
Бояться — нет. Избегать, где это возможно — да. Оптимизации instanceof в HotSpot хоть и хороши, тем не менее не являются серебряной пулей — против них можно легко можно создать контр-пример. В реальных приложения такие контр-примеры случаются не часто. Но в хорошо-спроектированных реальных приложениях «instanceof» в принципе почти не встречается.

Наезд на instanceOf неверен принципиально — перелопачивать архитектуру в обмен на ~0 прирост производительности.
GDove
я правильно понял, что желательно изначально выстраивать архитектуру программы, чтобы можно было легко пользоваться рефлексией, но если кода уже много, а определить тип очень надо, то instanseof?
blacky
а хз) рефлекция нужна, когда заранее неизвестен тип получаемого объекта, а работать с ним надо. Раньше при инициализации драйвера в JDBC это использовалось. Рефлексия используется при работе с клиент-серверными и сервис-ориентированными приложениями.
Пока я мало об этом знаю. Но подгонять архитектуру под рефлексию, чтобы получить мега гибкую архитектуру… смахивает на silver-bullet.
GDove
меня этот вопрос начал сильно мучить после решения 3 задаче в домашней работе.
там вводишь названия классов в которых запустить методы.
в задаче 4 класса, а если бы их было 1000? вот я подумал, что проще написать 4 строчки кода, чем 1000 instanceof. но новый плагин сказал что я лошара: типа 90% справились лучше =))
blacky
Ну касательно этого урока — здесь просто показали, что есть ключевое слово instanceof и для чего его можно использовать. А про архитектуру тут ни слова не было)
Dmitriy_Ivanov
Не могу понять такой, наверное простой, момент. А для чего вообще нужно присваивать объекту класса переменную его класса-родителя?.. В задачах уже было много таких операций, но я пропускал их, думая «потом разберусь». Но тут понимаю, что пропускаю что-то важное.

К примеру, имея классы:

    static class Pet
    {
    }

    static class Cat extends Pet
    {
    }

    static class Tiger extends Cat
    {
    }

Зачем использовать переменную класса Pet
Pet pet = new Tiger; 

вместо «родной» переменной класса Tiger?
Tiger tiger = new Tiger; 
Fedotenkov
  • Fedotenkov
  • 0
  • Комментарий отредактирован 2014-06-27 19:39:10 пользователем Fedotenkov
представь что у тебя зоопарк и тебе надо разместить в одном массиве разных зверей если будет массив объектов tiger ты не сможешь например туда положить объект мышь или жираф
Dmitriy_Ivanov
  • Dmitriy_Ivanov
  • 0
  • Комментарий отредактирован 2014-06-28 12:36:16 пользователем Dmitriy_Ivanov
То есть, использование переменных класса-родителя ( типа Pet pet = new Tiger ) может быть удобно, когда мы не знаем точно какие именно объекты (этого же класса или дочерних классов) нам нужно будет повесить на эту переменную в процессе выполнения программы?
Dmitriy_Ivanov
Стоило прочитать статью из материалов лекции и все стало на свои места :)
Преобразование ссылочных типов или спящий волк на клавиатуре
raynn
  • raynn
  • 0
  • Комментарий отредактирован 2014-07-17 10:46:04 пользователем raynn
Не совсем понимаю, зачем в этом примере в лекции создается новый объект tiger:
if (pet instanceof Tiger)
{
   Tiger tiger  = (Tiger) pet;
   tiger.doTigerActions();
}

Почему нельзя сделать так:

if (pet instanceof Tiger)
{
   pet.doTigerActions();
}
raynn
Кажется, понял:
если в классе Pet тоже есть метод doTigerActions(), то во втором случае выполнится он, а нам нужен метод из класса Tiger?
Sant9Iga
  • Sant9Iga
  • 0
  • Комментарий отредактирован 2014-07-17 11:13:42 пользователем Sant9Iga
а если его нету, тогда ты его прото не сможешь вызвать.
Ну и плюс нелогично в Pet делать метод для тигра)
raynn
А почему не смогу его вызвать?
Если в переменной pet хранится ссылка на объект класса Tiger, значит, можно вызывать методы этого класса, нет?
Sant9Iga
  • Sant9Iga
  • 0
  • Комментарий отредактирован 2014-07-17 11:38:55 пользователем Sant9Iga
<code>if (pet instanceof Tiger)
{
   pet.doTigerActions();
}</code>
вот так ты не смождешь сделать. тебе все равно придется приводить pet к Tiger. потому что если написать вот так:
public class Solution {
    public static void main(String[] args)
    {
        Pet tiger = new Tiger();
        if(tiger instanceof Tiger){
            ((Tiger) tiger).doTiger();
            tiger.doPet();
        }
    }
    public static class Pet{
        public void doPet(){
            System.out.println("doPet");
        }
    }
    public static class Tiger extends Pet{
        public void doTiger(){
            System.out.println("doTiger");
        }
    }
}

и не сделать приведение типа, тогда у tiger будет один метод doPet.
raynn
  • raynn
  • 0
  • Комментарий отредактирован 2014-07-17 12:16:31 пользователем raynn
Спасибо, теперь вроде понятно.
Т.е. tiger имеет методы только класса Pet, поскольку объявлена как Pet tiger. Несмотря на то что в ней хранится ссылка на экземпляр класса Tiger.
raynn
Еще один непонятный момент:
почему можно сделать такое расширение:
Object obj = new Tiger();
Pet pet = (Pet) obj;
Cat cat = (Cat) obj;
Tiger tiger = (Tiger) pet;
но нельзя такое:

Pet pet1 = new Pet();
Tiger tiger = (Tiger) pet1;

Ведь вроде бы и pet и pet1 хранят объекты класса Pet.
Sant9Iga
raynn
Не совсем, но, видимо, просто так устроено, что в первом случае в pet хранится объект, приведенный к классу Pet от Tiger, система как-то это запоминает, и разрешает обратное приведение: Tiger tiger = (Tiger) pet;
В случае же объекта, изначально созданного как Pet, приведение к классу-потомку невозможно.
aleczander
Никто ничего не запоминает. JVM пытается провести преобразование, и, поскольку в переменной хранится ссылка на объект, позволяющий это сделать, все проходит успешно. Во втором случае вылетит ClassCastException
Pavel255
Потому что при такой реализации pet1 может ссылаться на любое животное (объект new Pet): кошка, собака, рыба...
И превратить потом такого зверька в тигра никак не получится)
Eldar
Всем привет.

На 10 уровне говорилось:
«Кратко и по существу о преобразовании ссылочных типов. Но пока мы коснёмся только переменной типа Object. Этой переменной можно присвоить ссылку любого типа (расширение типа). Но чтобы выполнить обратное присваивание (сужение типа) приходится явно указывать операцию приведения:
».
И примеры.
Типичное расширение ссылочного типа:
String s = "mama";
Object o = s;

Типичное сужение ссылочного типа:
Object o = "mama";
String s2 = (String) o;

Дошел до 14 уровня, там говорится обратное:
«Движение вверх по цепочке наследования называется сужением, т.к. теряется возможность вызвать методы, которые были добавлены в класс при наследовании.»
И пример.
При расширении типа, нужно использовать оператор преобразования типа.
Object obj = new Tiger();
Pet pet = (Pet) obj;
Cat cat = (Cat) obj;
Tiger tiger = (Tiger) pet;
Tiger tiger2 = (Tiger) cat;


Или я чего-то недопонимаю? Объясните пожалуйста.
BappekM
  • BappekM
  • 0
  • Комментарий отредактирован 2014-07-24 03:22:57 пользователем BappekM
не путайте расширение/cужение ссылки и объекта, ccылка Object o может указывать на что угодно, получается она расширила свои возможности, в случае с объектом все получается иначе… через эту ссылку мы имеем ограниченную функциональность…
duddeniska
Блин ребят я вообще валенок нифига не понял зачем это приведение типов и когда его нужно использовать!(((
ath01
стоит прочитать хотя бы комменты выше, там все объясняют простым языком.
artemtimac
  • artemtimac
  • 0
  • Комментарий отредактирован 2015-02-08 23:05:55 пользователем artemtimac
Дайте новую ссылку на RTTI. Эта не работает.
evgeniys
artemtimac
Спасибо, конечно, но эта ссылка ничем не отличается от ссылки «Информация о типах» в Thinking in java. А до тех пор пока не хакнули украинский вики, RTTI — run-time type identification ссылался на свою собственную статью (тоже на вики), насколько я помню.
evgeniys
Тогда, пардон. Мне казалось, там перепечатка главы из книги. До перехода на англ. версию, читал оттуда и вначале писали, что якобы сделали вики книги на русском ввиду убогого скана оригинала на русском.
Но если там действительно статья, сам бы почитал.
Goodpupil
Эта глава конечно задержала мой быстрый проход по уровням. Тяжело её было осилить
b_rhyme
В материалах — ссылки на главы Эккеля дублируются. Может стоит убрать одну?)
Cepr0
  • Cepr0
  • 0
  • Комментарий отредактирован 2016-04-05 16:55:26 пользователем Cepr0
DenisDN
Здравствуйте. В представленой теме от профессора, то есть 13 главе Эккеля ( тыц), есть раздел Проверка перед приведением типов. В этом разделе есть пример

public class Individual implements Comparable<Individual> {
  private static long counter = 0;
  private final long id = counter++;
  private String name;
  public Individual(String name) { this.name = name; }
  // 'name' is optional:
  public Individual() {}
  public String toString() {
    return getClass().getSimpleName() +
      (name == null ? "" : " " + name);
  }
  public long id() { return id; }
  public boolean equals(Object o) {
    return o instanceof Individual &&
      id == ((Individual)o).id;
  }
  public int hashCode() {
    int result = 17;
    if(name != null)
      result = 37 * result + name.hashCode();
    result = 37 * result + (int)id;
    return result;
  }


У меня возник вопрос. Какую смысловую нагрузку несет число 37, это просто первое пришедшее на ум автору число или это специальное число, которое должно на что-то меня натолкнуть?
Sant9Iga
37 это перевернутое лучшее число
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.