Чтение онлайн

на главную - закладки

Жанры

Философия Java3

Эккель Брюс

Шрифт:

}

public С f InnerASC public С g package С u protected С v private С w */// ~

He помогло. Как насчет анонимного класса?

// typeinfo/AnonymousImplementation java

// Анонимные внутренние классы тоже не скрыты от рефлексии

import typeinfo.interfacea *.

import static net.mindview util Print *,

class AnonymousA {

public static A makeAO { return new AO {

public void fO { printCpublic С f"), } public void gO { printCpublic С gn); } void uO { print (package C.uO"), } protected void vO { print ("protected C.vO"). } private void wО { printOprivate С wO"). }

public class AnonymousImplementation {

public static void main(String[] args) throws Exception { A a = AnonymousA.makeAO; a.fO;

System.out.pri ntin(a.getCl ass

О.getName).

// Рефлексия все равно позволяет добраться до приватного класса.

Hiddenlmplementation callHiddenMethod(a, "g"),

Hiddenlmplementation.call HiddenMethod(a, "u");

Hi ddenlmpl ementati on callHiddenMethod(a, Y);

HiddenImplementation.callHiddenMethod(a, "w");

}

} /* Output: public C.fO AnonymousA!1 public C.gO package C.uO protected C.vO private C.wO *///•-

Похоже, не существует никакого способа предотвратить обращение и вызов методов с уровнем доступа, отличным от public, посредством рефлексии. Сказанное относится и к полям данных, даже к приватным:

//. typeinfo/ModifyingPrivateFields.java import java lang reflect *;

class WithPrivateFinalField { private int i = 1.

private final String s = "I'm totally safe";

private String s2 = "Am I safe?", продолжение &

public String toStringO {

return Hi = " + i + ", " + s + ", " + s2,

}

}

public class ModifyingPrivateFields {

public static void main(String[] args) throws Exception {

WithPrivateFinalField pf = new WithPrivateFinalField, System out println(pf);

Field f = pf getClassO getDeclaredFieldC'i"), f.setAccessible(true),

System.out.printlnC'f.getlnt(pf). " + f getlnt(pf)). f setlnt(pf. 47); System out.println(pf); f = pf getClassO getDeclaredFieldC's"). f.setAccessible(true);

System.out.printlnC'f.get(pf): " + f.get(pf)); f.set(pf. "No, you're not!"); System.out.println(pf); f = pf. getClassO. getDeclaredField("s2"); f.setAccessible(true);

System.out.printlnC'f.get(pf). " + f.get(pf)), f.set(pf, "No, you're not!"); System.out.println(pf),

}

} /* Output:

i = 1, I'm totally safe. Am I safe? f getlnt(pf): 1

i =47, I'm totally safe. Am I safe? f.get(pf): I'm totally safe i =47, I'm totally safe, Am I safe? f.get(pf): Am I safe? i =47, I'm totally safe. No, you're not! *///:-

Впрочем, final-поля защищены от изменений. Система времени выполнения спокойно воспринимает любые попытки их изменения, но при этом ничего не происходит.

В действительности все эти нарушения уровня доступа не так уж страшны. Если кто-то захочет вызывать методы, которым вы назначили приватный или пакетный доступ (тем самым ясно показывая, что вызывать их не следует), вряд ли он станет жаловаться на то, что вы изменили некоторые аспекты этих методов. С другой стороны, «черный ход» к внутреннему устройству класса позволяет решить некоторые проблемы, нерешаемые другими средствами, и в общем случае преимущества рефлексии неоспоримы.

Резюме

Динамическое определение типов (RTTI) позволяет вам получить информацию о точном типе объекта

тогда, когда у вас для него имеется лишь ссылка базового типа. Таким образом, оно открывает широкие возможности для злоупотреблений со стороны новичков, которые еще не поняли и не успели оценить всю мощь полиморфизма. У многих людей, ранее работавших с процедурными языками, возникает сильное желание разбить свою программу на множество конструкций switch при помощи RTTI. Однако при этом они лишаются всех преимуществ полиморфизма, относящихя к разработке программы в целом и ее дальнейшей поддержке. В Java рекомендуется использовать именно полиморфные методы, а к услугам RTTI следует прибегать только в крайнем случае.

Впрочем, при использовании полиморфных методов требуется полный контроль над базовым классом, поскольку в некоторой точке программы, после наследования очередного класса, вы можете обнаружить, что базовый класс не содержит нужного вам метода, и тогда RTTI вас выручит: при наследовании вы расширяете интерфейс класса, добавляя в него новые методы. Особенно верно это при использовании в качестве базовых классов библиотек, которые вы не можете изменить. Далее в своем коде в подходящий момент вы обнаруживаете новый тип и вызываете для него нужный метод. Такой подход не противоречит основам полиморфизма и расширяемости программы, так как добавление в программу нового типа не требует изменения бесчисленного множества конструкций switch. Но чтобы извлечь пользу из дополнительной функциональности нового класса, придется использовать RTTI.

Включение некоторого метода в базовый класс будет выгодно только одному производному классу, который действительно реализует его, но все остальные производные классы будут вынуждены использовать для этого метода какую-либо бесполезную «заглушку». Интерфейс базового класса «размывается» и раздражает тех, кому приходится переопределять ненужные абстрактные методы при наследовании от базового класса. Например, рассмотрим иерархию классов, представляющих музыкальные инструменты. Предположим, что вы хотите прочистить мундштуки духовых инструментов своего оркестра. Конечно, можно поместить в базовый класс Instrument (общее представление музыкального инструмента) еще один метод с lea rS pi tVa Ive (прочистка мундштуков), но тогда получится, что и у синтезатора, и у барабана есть мундштук! С помощью RTTI можно получить гораздо более верное решение данной задачи, поскольку этот метод уместно поместить в более конкретный класс (например, в класс Wind, базовый для всех духовых инструментов). Однако еще более разумным стало бы включение в класс Instrument метода preparelnstrument (подготовить инструмент к игре), который подошел бы всем инструментам без исключения. На первый взгляд можно было бы ошибочно решить, что в данном случае без RTTI не обойтись.

Наконец, иногда RTTI решает проблемы производительности. Если ваш код использует полиморфизм по всем правилам, но один из объектов чрезвычайно непродуктивно обрабатывается кодом, предназначенным для базового типа, то для этого объекта можно сделать исключение, определить его точный тип с помощью RTTI и работать с ним более производительно. Однако ни в коем случае не следует писать программы, ориентируясь только на их эффективность, как бы соблазнительно это ни было. Сначала надо получить работающую программу и только после этого решать, достаточно ли быстро она работает, и решать проблемы быстродействия, вооружившись инструментами для проверки скорости исполнения.

Поделиться:
Популярные книги

Кротовский, не начинайте

Парсиев Дмитрий
2. РОС: Изнанка Империи
Фантастика:
городское фэнтези
попаданцы
альтернативная история
5.00
рейтинг книги
Кротовский, не начинайте

Вадбольский

Никитин Юрий Александрович
1. Вадбольский
Фантастика:
попаданцы
5.00
рейтинг книги
Вадбольский

Истребители. Трилогия

Поселягин Владимир Геннадьевич
Фантастика:
альтернативная история
7.30
рейтинг книги
Истребители. Трилогия

Законник Российской Империи. Том 4

Ткачев Андрей Юрьевич
4. Словом и делом
Фантастика:
городское фэнтези
альтернативная история
аниме
дорама
5.00
рейтинг книги
Законник Российской Империи. Том 4

Пятнадцать ножевых 4

Вязовский Алексей
4. 15 ножевых
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Пятнадцать ножевых 4

Адаптация

Уленгов Юрий
2. Гардемарин ее величества
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Адаптация

Имперский Курьер. Том 4

Бо Вова
4. Запечатанный мир
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Имперский Курьер. Том 4

Его огонь горит для меня. Том 2

Муратова Ульяна
2. Мир Карастели
Фантастика:
юмористическая фантастика
5.40
рейтинг книги
Его огонь горит для меня. Том 2

Кодекс Крови. Книга VII

Борзых М.
7. РОС: Кодекс Крови
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга VII

Локки 4 Потомок бога

Решетов Евгений Валерьевич
4. Локки
Фантастика:
аниме
фэнтези
5.00
рейтинг книги
Локки 4 Потомок бога

Хозяйственная помощница для идеала

Свободина Виктория
15. Помощница
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Хозяйственная помощница для идеала

Газлайтер. Том 19

Володин Григорий Григорьевич
19. История Телепата
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Газлайтер. Том 19

Три `Д` для миллиардера. Свадебный салон

Тоцка Тала
Любовные романы:
современные любовные романы
короткие любовные романы
7.14
рейтинг книги
Три `Д` для миллиардера. Свадебный салон

Студиозус 2

Шмаков Алексей Семенович
4. Светлая Тьма
Фантастика:
юмористическое фэнтези
городское фэнтези
аниме
5.00
рейтинг книги
Студиозус 2