Rambler's Top100IT • archiv

rus / eng | Логин | Комментарий к колонке | Печать | Почта | Клуб




Колонки


Раскроем карты

 
( Андрей Терешко )

Пора, наверное, пора. Уж скоро год, как я задал свои загадки (см. "Ловкость рук и никакого… " и "Волшебство"). Пришло и несколько писем с ответами, что удивительно. :-)

Вопрос: [На этот вопрос, идею которого подсказал Роман Поротников, правильно ответил Andrei Prygounkov.]
Измените класс Quirk так, чтобы, не изменяя (а также, не удаляя и не добавляя) ни одного символа в коде метода main, на консоль выводилось бы другое сообщение, вместо "Magic Java.":

public class Quirk {
     public static void  main(String[] args)
{
      System.out.println("Magic
Java.");
     }
}

Ответ: Действительно, так как при загрузке класса первым начинает выполняться не метод "static void  main(String[] args)", как многие возможно считают, а блоки статической инициализации, то именно в них и можно вывести на консоль другое сообщение и вообще - завершить программу так, что метод "static void  main(String[] args)" вообще не будет никогда вызван!

// Обратите внимание, в КОДЕ метода " main(String[] args)" я не изменил ни одного символа. :-)

public class Quirk {
    public static void  main(String[] args)
{
         System.out.println("Magic
Java.");
     }
   static {
         System.out.println("Cool
Java.");
         System.exit(0);
   }
}

Вопрос: ["Зеленая" Java. Эта загадка от Романа Поротникова не нашла решения ни у одного из приславших мне письма с ответами. Неужели эта зелень НИКОМУ не по зубам? ;-) ]
В JBuilder (да и не только в нем) есть синтаксический анализатор кода, который показывает зеленым цветом код комментария. Напишите программу, которая вся(!) была бы окрашена в зеленый цвет: Green.java.  И эта "зеленая " программа должна выводить на консоль сообщение "World is green!" — вот "зеленые" то обрадуются.

Ответ:: Конечно, вопрос довольно эффектный и многих может ввести в шок. Как так? —   грузим исходник в редактор, видим одну зелень, то есть ВСЯ программа визуально(!) состоит из ОДНИХ комментариев, запускаем программу и, на тебе, — программа работает и выводит на консоль сообщение "World is green!" Чудо да и только! А секрет прост, ведь текст в Java можно набирать не только на английском, китайском, тайваньском и русском, но и на всех этих (и многих других) языках разом, используя … Эка, я Вам уже сколько подсказал. Но задача то красивая — вся такая зеленая. Нет, пока секрет полностью не открою. Присылайте решения. ;-)

Вопрос: Конструктору класса нельзя приписать атрибут "synchronized", ибо, как пишут К.Арнольд и Д.Гослинг ("Язык программирования Java") - "Конструктор не обязан быть synchronized, поскольку он выполняется только при создании объекта, а это может происходить только в одном потоке для каждого вновь создаваемого объекта". Замечу, что не просто "не обязан", а просто и не может иметь атрибут synchronized, иначе при компиляции сразу вылетает ошибка: "Constructors can't be native, abstract, static, synchronized, or final".  Приведите пример, возможно и гипотетического, но вполне работоспособного кода, когда конструктор просто обязан(!) обладать свойствами, обычно даруемыми атрибутом "synchronized". И как же этого достичь?

Ответ: Если конструтор в теле своего кода вызывает метод какого либо класса, передавая ему в качестве параметра САМОГО СЕБЯ (this) и команды тела конструтора продолжают выполняться дальше, то существует вероятность в многопоточном приложении, что ДРУГОЙ поток сумеет обратиться к синхронизируемому методу объекта, ВСЕ ЕЩЕ создаваемого этим конструктором, ДО ТОГО КАК конструктор успеет выполниться до конца. Тем самым произойдут незапланируемые программистом действия. В этом случае, то есть в том случае, если в конструкторе происходит "выброс во вне" ссылки на еще не полностью проиницилизированный объект (то есть "this"), надо использовать внутри конструктора ОПЕРАТОР synchronized (this):

public class Client {
   public Client() {
       synchronized (this){
       Manager.add(this); // "Выброс себя
вовне"
       … // Различные действия по инициализации полей
объекта (возможно и длительные)
      }
   }
   synchronized void addAccount(){
     …
  }
} // end Client

И пока в конструкторе все еще инициализирующейся объект заблокирован оператором "synchronized (this)" ни один другой тред не сможет вызвать метод "synchronized void addAccount()" этого объекта, хотя ссылка на объект уже передана "в мир" ( в данном случае, вызовом static метода класса Manager — Manager.add(this)). А как потом "в миру" будут использовать ссылку на Ваш объект — это, в общем случае, уже может абсолютно не зависеть от Вас.

Вопрос: При вызове конструктора оператором "new", конструктор всегда возвращает ссылку на НОВЫЙ объект. Заставить конструктор возвратить вместо ссылки на новый объект ссылку на уже существующий объект нельзя. А если очень хочется? Как "обмануть" конструктор?
Приведите пример кода, когда при "создании" объекта — то есть при присвоении новой ссылке значения, эта новая ссылка получает значение ссылки на уже существующий объект.

Ответ: Конструтор "обмануть" мне не удалось, как я не старался. ;-(
Но в Java НОВЫЙ объект можно создавать(!) не только с помощью оператора "new", но и востанавливая объект "из пепла" — то есть десериализуя его. И вот в методе readResolve(), при десериализации,  можно подставить вместо "себя" другой объект, что и применятся при работе с синглетонами. Если Вы не знаете, что такое "синглетон", то я об этом напишу в следующий раз — ибо это очень интересный объект, почти никак официально не поддерживаемый в спецификации языка Java, но занимающий пристальное и постоянное внимание многих java-программистов. Об этом объекте можно написать целую книгу — и постоянно ее дополнять. ;-).

public class Singleton implements Serializable 
{
    private static final Singleton INSTANCE =  new
Singleton();
    private Singleton( ) {  }
    public static Singleton getInstance( )
{
        return INSTANCE;
    }
    private Object readResolve() throws
ObjectStreamException {
        return INSTANCE;
    }
}

Вопрос:  В JSP при монтировании в страницу bean-компонента с помощью тега <jsp:useBean … </jsp:useBean>, используется такой jsp-механизм, что если данного экземпляра bean-компонента, отвечающего требованиям тега, не находится, то с помощью безаргументного конструктора создается новый экземляр данного bean-компонента.
А если bean-компонент не имеет безаргументного конструктора? Или Вы считаете, что bean  обязан всегда иметь безаргументный конструктор?
Укажите, напишите пример, каким образом bean-компонент, не имеющий безаргументного конструктора, можно вмонтировать в jsp-страницу. Сколько имеется способов для этой процедуры?

Ответ: Несмотря на широко распространенное мнение о том, что bean-компонент ОБЯЗАН иметь безаргументный конструктор, должен Вас разочаровать — никто этой обязанности ему не вменял. Таким образом, если у Вас есть bean-компонент не имеющий безаргументного конструктора, и Вы желаете его вмонтировать в jsp страницу, то:

Первый способ, используя скриплеты:

package bar;
public class FooBean {
   public FooBean(SomeObj arg) {
     ...
   }
    //getters and setters here
}

Встраиваем в сессию:

<%
someObj x = new SomeObj(...);
bar.FooBean foobar = new FooBean(x);
session.putValue("foobar",foobar);

%>

И можем с любой страницы сессии обратиться:

<% bar.FooBean foobar =
session.getValue("foobar"); %>

Можно встроить и в приложение:

<% application.setAttribute("foobar",foobar);
%>

Или только в область запроса:

<% request.setAttribute("foobar",foobar);
%>

Если не размещается в request, session или application scope, то можно использовать только в пределах jsp-страницы: page scope

Как только bean встроен, к нему можно обращаться как обычно:

<jsp:getProperty name="foobar"
property="someProperty"/>
<jsp:setProperty name="foobar"
property="someProperty" value="someValue"/>

Второй способ -  сериализуйте этот bean-компонент и уже в таком, сериализованном виде вмонтируйте в jsp страницу:

<jsp:useBean id="shop" 
type="shopping.Disks" beanName="Disks"  />
<jsp:getProperty name="shop"
property="album" />

В beanName вместо "filename.ser", указать "filename".

Вопрос: Модификатор поля (переменной класса) "final" — "объявляет, что значение переменной присваивается всего один раз, при ее инициализации" (К.Арнольд и Д.Гослинг "Язык программирования Java"). Приведите пример, когда волшебным образом, можно менять поле с модификатором "final" столько раз, сколько душе угодно. Подсказка — это поле вы, уважаемый Читатель, наверняка знаете и довольно часто используете в своих программах на Java.

Ответ: Пришло несколько писем, где правильно указали имя этого широко известного и повсеместно всеми применяемого и изменяемого(!) поля с модификатором "final". Но никто не указал — почему это происходит? Почему вообще возможно "переписать финал" в java. Кто и что позволяет это сделать? А как Вы считаете, лично Ваши переменные с модификатором поля "final" кто-либо может изменить? И если да, то каким именно способом?

Вопрос: Если, при создании класса, приписать методу атрибут доступа "private", то доступ к такому методу может быть осуществлен только из самого класса. Приведите пример, когда разработчик класса должен создавать методы класса с атрибутом доступа "private", но нигде(!) в своем классе, не использовать вызов этих методов. Вот как удивлялся этому волшебству Д. Флэнэген в своей книге "Java in a Nutshell": "… Как ни странно, но эти методы не определены ни в одном из интерфейсов. Их следует объявлять как "private", что также вызывает некоторое удивление, поскольку они вызываются извне…". Кому же нужны такие методы? Кто их вызывает извне и как?

Ответ: На это вопрос также поступило несколько писем, где правильно — когда именно разработчик класса должен создавать методы класса с атрибутом доступа "private", но нигде(!) в своем классе, не использовать вызов этих методов. Но никто не написал — почему вообще такое возможно? И можете ли Вы вызывать методы другого класса, определенные с атрибутом доступа "private"? И если да, то каким именно способом?

Полный ответ на этот вопрос такой же и как на предыдущий. Все очень просто. ;-) Отгадка механизма этого "фокуса" похожа на разоблачение фокусника, достающего кролика из совершенно пустого ящика. И когда зрителю раскрывают секрет этого фокуса, то по зрительному залу проносится вздох: "Я так и знал, что у этого ящика есть двойное дно!". ;-)
Затем интерес к фокусу пропадает и фокуснику приходиться придумывать новый фокус, используя тот же механизм, но в другой упаковке — он начинает, например, распиливать женщину. ;-)

Так и в Java — почти все "фокусы" и "некоторые удивления"  опираются на то, что … Ну, я немного устал, да и Вы, уважаемый читатель, немного устали читать. Все, что не успел, я сообщу Вам в следующий раз. Что-то ведь должно остаться еще некоторое время неразгаданным для широкой публики. ;-)

Успехов Вам.

Все права на публикацию этого материала принадлежат автору.

Терешко Андрей, Минск.




Справка | Условия Copyright © 1999 — 2008, IT • archiv.
В начало | Логин | Комментарий к колонке | Поиск | Почта