Понеже всичко е манипулатор в Java и понеже всички обекти се създават на хийпа и се почистват само когато вече не са необходими, вкусът на обработката на обекти се променя, специално когато се подават и връщат обекти. Например в C или C++ ако искате да инициализирате някаква област от паметта в един метод, вероятно ще искате потребителят да даде адреса на тази памет. Иначе ще трябва да се притеснявате за това кой ще очисти после тази памет. Така интерфейсът и разбираемостта на такива методи са усложнени. Но в Java никога не се грижите за съществуването на обекта когато вече не е необходим, понеже за това се грижи боклукосъбирането. Програмата ви може да създаде обекта в точката в която е необходим, не преди това, и няма да се безпокоите за предаването на обекта (като параметър - б.пр.): просто предавате манипулатора. Понякога опростяването което носи това е незабележима, друг път е смайващо.
Обратната страна на цялата тази магия е двойна:
Винаги получавате удар по скоростта поради допълнителната работа за управление на паметта (макар и това да може и да е твърде малко) и винаги има малка несигурност относно времето за което нещо може да стартира (понеже може да се активира събирачът на боклук винаги щом има недостиг на памет). За повечето приложения ползите превишават недостатъците, а особено критичните откъм време на изпълнение части могат да се напишат чрез native методи (виж приложение A).
Псевдонимите: понякога може по стечение на обстоятелствата да завършите с два манипулатора сочещи към един и същ обект, което е проблем само ако те сочат различен обект. Това е на което трябва да се обърне малко повече внимание, когато е необходимо, clone( )-ирайте обекта за да предотвратите изненадата на другия манипулатор от промяната. Като алтернатива може да допуснете псевдоними заради ефективността, избягвайки проблемите чрез създаването на неизменяеми обекти чиито операции могат да върнат нов обект от същия тип или някакъв друг тип, но никога не променят началния обект така че няма никакви промени за псевдонимите които го сочат.
Някои хора твърдят че клонирането в Java е проектирано през куп за грош, така че прилагат тяхна собствена версия на клонирането5 и никога не викат метода Object.clone( ) елиминирайки с това необходимостта да използват Cloneable и да прихващат CloneNotSupportedException. Това сигурно е резонен подход и понеже clone( ) е поддържан така рядко в стандартната библиотека на Java, види се е по-сигурен също така. Но доколкото не викате Object.clone( ) не е необходимо да прилагате Cloneable или да прихващате изключението, така че и това ще е приемливо.
Интересно е да се отбележи че едната “запазена но неизползвана” ключова дума в Java е byvalue. След разглеждането на въпросите с псевдонимите и клонирането може да си въобразите че byvalue може някой ден да бъде използвана за реализацията на автоматично локално копие в Java. Това би могло да елиминира неприятностите с клонирането и да направи програмирането по-просто и с по-добър резултат.
Упражнения
Създайте клас myString съдържащ String обект който инициализирате в конструктора използвайки аргументите му. Добавете toString( ) метод и метод concatenate( ) който добавя String обект към вашия вътрешен стринг. Приложете clone( ) в myString. Създайте два staticвсеки да взема myString x манипулатор като аргумент и да вика x.concatenate(“test”), но във втария метод извикайте clone( ) първо. Пробвайте двата метода и покажете различния ефект.
Създайте клас наречен Battery съдържащ int който е номер на батгерията (като уникален идентификатор). Направете я кланируема и напишете toString( ) метод. Сега създайте клас наречен Toy който съдържа масив от Batteryи и toString( ) който извежда всичките батерии. Напишете clone( ) за Toy който автоматично клонира всичките Battery обекти. Пробвайте това чрез клониране на Toy и извеждане на резултатите.
Променете CheckCloneable.java така че всички clone( ) методи да хващат CloneNotSupportedException наместо да го предават към извикващия метод.
Променете Compete.java с добавяне на повече член-обекти към Thing2 и Thing4 и вижте дали ще може да определите промяната на времената в зависимост от сложността – дали това е проста линейна зависимост или е някаква по-сложна.
Започвайки със Snake.java, създайте версия с дълбоко копиране на змията.
13: Създаване на прозорци и аплети
(Следващата бележка не се превежда, понеже вече има 8-ма окончателна версия на книгата - б.пр.)
[[[ Note: please notice that only the code files have been changed to be Swing-compliant, and the prose is essentially the way it was before, and refers to the old programs – that is to say, more work is going to be done here. So please concentrate on the code listings, and if you see changes that should be made, please email the entire file after you’ve made the improvements to Bruce@EckelObjects.com. Thanks! ]]]
Основно правило в проектирането е “направи простите неща лесни и трудните - възможни1.”
Първоначалната цел на графичния потребителски интерфейс в съответната (GUI) библиотека в Java 1.0 беше да позволи на програмиста да направи GUI който изглежда добре на всички платформи. Тази цел не беше достигната. Вместо това Abstract Window Toolkit (AWT) на Java 1.0 дава GUI който изглежда еднакво посредствено на всички системи. Освен това е ограничителен: може да използвате само четири шрифта и не може да достигнете по-сложни елементи на GUI които са налице във вашата операционна система. AWT програмния модел на Java 1.0 е също тромав и не е обектно-ориентиран. Един слушател на моите семинари (който беше в Sun по време на създаването на Java) обясни защо: оригиналния AWT е бил концептуализиран, проектиран и реализиран за един месец. Чудо на производителността а също и урок защо е важно проектирането.
Ситуацията е много подобрена в Java 1.1 Събитийния модел на AWT който взема много по-ясен, обектно ориентиран подход, заедно с добавката на Java Beans, среда за компонентно програмиране, чиято цел е бързо и лесно визуално създаване на програми. Java 2 завършва трансформацията от стария Java 1.0 AWT чрез добавяне на Java Foundation Classes (JFC), частта GUI на която е наречена “Swing.” Това е множество от лесни за използване, лесни за разбиране Java Beans които могат да бъдат влачени и пускане (както и удобно програмирани) за създаване на GUI който може (накрая) да бъде удовлетворителен. Правилото “revision 3” на софтуерната индустрия (продуктът не е добър до версия 3) изглежда валидно също и за програмните езици.
Тази глава не разглежда нищо освен съвременната, Java 2 Swing библиотека, и прави резонното предположение че Swing е крайната библиотека GUI за Java. Ако по някаква причина трябва да използвате оригиналния “стар” AWT (понеже поддържате стар код или стари браузъри), може да намерите това въведение в първото он-лайн издание на книгата на www.BruceEckel.com .
Повечето примери ще показват създаването на аплети, най-вече защото е по-просто и лесно да се разберат примерите по този начин. Освен това ще видите разликите когато се създава обикновено приложение с използването на Swing, а също и приложения които са и приложения и аплети, та могат да се пускат както чрез браузър така и от команден ред.
Моля имайте предвид, че това не е гълен справочник на методите в съответните класове. Тази глава само ви позволява да започнете основното. Когато търсите повече от това, вижте с браузера да намерите методите които ви трябват. Има множество книги посветени само на Swing и ще трябва да се обърнете към тях ако искате да промените повезението по подразбиране на Swing.
Както си учите за Swing ще откриете че:
Swing е много по-добър програмен модел отколокто вероятно сте виждали в други програмни езици и развойни среди. Java Beans е рамката за тази библиотека.
“GUI построители” (визуални програмни среди) са de rigeur за всички развойни системи. Java Beans и библиотеката Swing позволява на построителя на GUI да пише код заради вас както си попълвате формите. Това не само много ускорява работата при строене на GUI, но и позволява изпробването на повече възможности за късо време и по този начин предполага по-добър дизайн най-накрая.
Една от основните цели в Java е създаването на appletи, които са малки програми работещи в Web браузър. Понеже трябва да бъдат безопасни, аплетите са ограничени във възможностите си. Обаче те са мощен инструмент за поддръжка на клиентската страна, основна задача в Web.
Програмирането в рамките на аплет е толкова ограничително, че често се говори за него като за в “пясък,” понеже винаги има някой – системата за сигурност на Java – да ви следи. Java предлага цифров подпис така че може да позволите на аплети на които може да се вярва достъп до вашата машина. Може също да излезете от пясъка и да напишете нормабно приложение, в който случай имате достъп до различни черти на ОС. През цялото време писахме нормални приложения до сега, но те бяха за конзола без никакви графични компоненти. Swing може също да се използва за постройка на GUI за обикновени приложения.
Библиотеките често се групират според тяхната функционалност. Някои, например, се използват както са си, "от рафта". Стандартните в Java библиотеката String и ArrayList класове са примери за този случай. Други библиотеки са проектирани специално да съдържат строителни блокове за постройка на други класове. Някой клас от такава библиотека е application framework, чиято цел е да дадат базово множество от класове които изпълняват всички общи цели на приложението, чиято е рамката. Тогава за да се приспособи според нуждите поведението трябва да се наследи от тези класове и да се подтиснат методите, които представляват интерес. Механизмът за управление на рамката ще извика вашите методи когато му е времето. Рамките за приложения са добър пример за “разделяне на нещата които се променят от тези които остават същите,” понеже се опитват да ограничат всички уникални части на програмата в подтиснатите методи2.
Аплетите се пишат чрез използване на рамка. Наследявате от клас JApplet и подтискате методите където е нужно. Има няколко метода които управляват създаването и изпълнението на аплети в страница:
Метод
Операция
init( )
Вика се когато аплетът е създаден за пръв път и извършва инициализация, вкл. На разположението на компонентите. Винаги ще подтискате този метод.
start( )
Вика се всеки път когато аплетът влиза в полезрението на Web браузър за да започне изпълнението на нормалните си операции (особено онези спрени със stop( )). Също се вика след init( ).
stop( )
Вика се всеки път когато аплетът излиза от полезрението на Web броузер за да позволи спирането на скъпите операции. Също се вика непосредствено преди destroy( ).
destroy( )
Вика се когато аплетът се маха от страницата за освобождаване на всички ресурси когато аплетът вече не е нужен
С тази информация може да създадете прост аплет:
//: c13:Applet1.java
// Very simple applet
import javax.swing.*;
import java.awt.*;
public class Applet1 extends JApplet {
public void init() {
getContentPane().add(new JLabel("Applet!"));
}
} ///:~
Забележете че аплетите не е необходимо да имат main( ). Всичко необходимо е вградено в рамката; слагате всичкия код за начално установяване в init( ).
Пускане на аплети от Web браузър
За да се стартира тази програма трябва да я сложите в Web страница и да я разгледате с вашия Web броузър, в който Java е активиран. За да сложите аплет в Web страница слагате специален текст в HTML сорса на Web страницата3 за да се каже на страницата как да натовари и пусне аплета.
Този процес беше много простичък когато Java беше простичък и всеки се намираше в същото купе и слагаше една и съща поддръжка на Java в броузера си. Така че може би ще се разминете с много простичък текст HTML в Web страницата, като този:
После дойдоха браузърските и езикови войни, а всички ние загубихме. След доста време Javasoft разбра че вече не може да се разчита браузърите да поддържат еднакво добре Java, а единственото спасение е добавянето на нещо което отчита механизма на конкретния браузър. Чрез използване на механизма на разширенията (които продавачът на браузъра не може да деактивира – в стремежа да направи състезателен напредък – без да съсипе всичсите разширения от трети доставчици) Javasoft гарантира че Java не може да бъде разкаран от браузър от антагонистично настроен доставчик.
При Internet Explorer механизмът на разширяването е ActiveX управление, а при Netscape механизмът е plug-in.Във вашия html код трябва да сложите текст за поддръжка и на двата. Ето как изглежда най-простата HTML страница за Applet1: