Hakemisto
0. Mistä nämä ovat kotoisin?
Nämä tekstit on poimittu pääasiassa artikkeleistani erilaisissa Javaa ja ohjelmointia käsittelevissä uutisryhmissä. Ajattelin että saattaisi olla hyödyllistä kerätä niitä talteen, jos vaikka joku myöhemminkin haluaa näistä hyötyä.
Nämä vastaukset olen antanut pääasiassa ryhmissä hy.opiskelu.tktl.java ja hy.atk.kielet.java. Jos vastaus tai sen osa on peräisin joltakulta muulta, vastaaja on merkitty vastauksen yhteyteen.
1. Kirjoitan näytölle / pistokkeeseen / tiedostoon, mutta mitään ei tulostu / tulostus tulee vasta myöhemmin. Miksi?
Usein IO on puskuroitua. Kokeile sanoa esimerkiksi System.out.flush().
2. Voiko Javalla lukea merkkejä näppäimistöltä merkkiä ilman että käyttäjän täytyy painaa enteriä?
Komentoriviltä ei. Useimmat käyttöjärjestelmät puskuroivat syötteen ja vaikka yksittäisen merkin voikin lukea, ohjelma saa sen käsiteltäväksi vasta kun rivinvaihto on syötetty.
AWT:lla sen sijaan merkkien ja näppäinten lukeminen onnistuu yksitellen, katso java.awt.event.KeyListener.
(Jari Juslin, Tuomo "Bass" Salo ) )
3. Mitä virkaa on alkeistyyppien kääreillä? (esim. java.lang.Integer)
Ensinnäkin, alkeistyyppien kääreitä (wrapper) ei ole tarkoitettu niinkään korvaamaan alkeistyyppejä, vaan täydentämään niitä.
Itse näkisin kääreille kaksi päätarkoitusta. Ensimmäinen on koota alkeistyyppeihin liittyviä apuoperaatioita yhteen pakettiin. Toinen on tarjota mahdollisuus välittää alkeistyyppejä paikkoihin joihin eivät kelpaa kuin oliot.
Joku voisi nähdä kääreet myös yrityksenä korjata Javan oliomaisuuden puutteita, mutta oli miten oli, mielestäni ratkaisu toimii vähintäänkin hyvin. Java 1.0.2:ssa kääreet oli tarjolla vain osalle alkeistyyppejä, mutta 1.1:stä alkaen kääreet on tarjottu kaikille alkeistyypeille.
Ensimmäinen merkitys lienee aika selvä.
Toinen merkitys tulee esiin esimerkiksi Javan varastoluokissa. Niissä on usein talletettavana perusalkiona luokka java.lang.Object. Tämähän on käytännöllistä, sillä mikä tahansa olio voidaan silloin sijoittaa tuollaiseen varastoon. Kaikki luokathan ovat Objectin perillisiä.
Ja kuten tarkkaavaisimmat ehkä jo huomasivat, sanoin "mikä tahansa olio". Alkeistyypit eivät ole Objectin perillisiä, joten ne on käärittävä oliokuoriin jotta ne voitaisiin kelpuuttaa Objectin perillisiksi.
Useimmiten olen itse törmännyt tuohon Hashtablen kanssa. Hashtablehan perustuu avain-tietoalkio -pareihin, jossa olioita voidaan tallettaa ja hakea avaimen perusteella. Monissa tapauksissa on soveliasta käyttää tunnisteena yksikäsitteisiä kokonaislukuja, koska niitä on helppo generoida, tallentuvat pieneen tilaan ja avainavaruus on laaja. Tällöin apuun säntää Integer, jolloin kokonaislukujen käyttö avaimina onnistuu kätevästi.
4. Muutin näytöllä näkyvien komponenttien layout-parametrejä / Lisäsin näytölle komponentin / Poistin komponentin näytöltä, mutta mitään muutosta ei näy?
Aina remove- ja add- operaatioiden jälkeen on paikallaan kutsua java.awt.Container-luokassa määriteltyä validate()-metodia, joka päivittää näytön. Validatea kutsutaan sattumoisin automaattisesti ikkunan koon muuttamisen jälkeen, joten se selittää homman toimimisen ikkunan venyttämisen jälkeen.
Siteeraan taas API-kuvausta: public void validate()
Validates this container and all of its subcomponents. AWT uses validate to cause a container to lay out its subcomponents again after the components it contains have been added to or modified.( Sami Nikander )
5. Onko mahdollista tehdä Java-ohjelma joka olisi toiminnassa WWW-palvelimella silloinkin kun en itse ole kirjoittautuneena sisään? (Esimerkiksi chat- tai peli-sovelmien keskinäisestä tietoliikenteestä huolehtimaan)
Yleisesti: On mahdollista.
Käytännössä: Riippuu kunkin palvelimen ylläpidosta. Useimpien kaupallisten yhteydentarjoajien ylläpito tuskin antaa tuollaisia tehdä. Lue käyttösopimuksesti ja/tai kysy ylläpidolta.
6. Kuinka tehdään palvelin-ohjelma? (Esimerkiksi chat-palvelimeksi)
Mallia voi katsoa Sunin Java Tutorialista, client-server-pari-esimerkistä .
Ko. teos on saatavissa myös kirjana ja on IHMO erittäin käyttökelpoinen Javan opetteluun.
7. Voiko Javalla muotoilla numeroiden tulostusta?
Muotoilu helposti C-tyyliin %3d ei ole mahdollista.
Muotoiluun on kielen versiosta 1.1 alkaen ollut tarjolla mm. luokka java.text.DecimalFormat. Sen käyttö on kuitenkin jonkin verran monimutkaisempaa.
Toisaalta nuo java.text-pakkauksen luokat tukevat ohjelmien paikallistamista, jolloin samalla luokalla saa kerralla numerot muotoiltua kunkin maan tyyliin sopivaksi.
Esimerkiksi Suomessa numerot on ollut tapana merkitä 1 000,00 ja USA:ssa 1,000.00.
8. Miksi tekemäni sovelma toimii oikein hyvin koneelta jolla tein sen, muttei muilla?
Todennäköisesti selaimesi omalta koneeltasi kokeillessasi hakee sovelman luokat omalta kovalevyltäsi. Useimmat selaimet tietoliikennettä säästääkseen hakevat luokat paikalliselta levyltä, jos niistä on siellä kopiot (paikallisen CLASSPATH-polun alla).
Tarkista että
9. Määrittelin CLASSPATH:in uudelleen ja nyt kääntäjä/JVM ei löydä valmisluokkia. Miksi?
JDK:n asennusohjelma tai vastaava yleensä asentaa CLASSPATH:in osoittamaan valmisluokkiin. Kun haluat lisätä omasi, sinun täytyy muistaa sisällyttää myös tuo valmisluokkien polku mukaan.
Esimerkiksi java -classpath mun/polku Luokka ei toimi. Oikea muoto on esimerkiksi java -classpath /lib/classes.zip:mun/polku Luokka.
10. Onko mahdollista kahden Java-sovelluksen kommunikoida keskenään? Pistokkeilla?
On toki. Se on sitten eri asia, ovatko pistokkeet se paras tapa toteuttaa juuri se mitä aiot tehdä. Itse tekisin todennäköisesti pistokkeilla. Toinen vaihtoehto voisi olla RMI. Siitä en valitettavasti tiedä paljoakaan, huhut kertovat että se ei ole turvallinen julkisessa verkossa.
Suosittelen tutustumaan vaikkapa Java Tutorialin tai JavaWorldin ohjeisiin. Java Tutorialin pistokkeista kertova osuus löytyy osoitteesta <URL:"http://java.sun.com:81/docs/books/tutorial/networking/sockets/index.html">.
Käytännössä, jos kumpi vain sovellus voi olla käynnissä ennen toista, sinun olisi tehtävä molemmista osuuksista sekä asiakas- että palvelinohjelma. Toinen vaihtoehto on tehdä yksi palvelinohjelma, joka on "aina" päällä ja välittää tietoa noiden kahden välillä.
Jotain asiaa liippaavaa on myös JavaWorldin näissä artikkeleissa: <URL:"http://www.javaworld.com/javaworld/jw-02-1997/jw-02-step.html"> <URL:"http://www.javaworld.com/javaworld/jw-03-1997/jw-03-step.html">
11. Voinko suojata Java-koodini takaisinkääntämiseltä?
Osittain. On olemassa erilaisia koodia sekoittavia työkaluja, jotka yleensä ainakin muuttavat muuttujien ja metodien nimet käsittämättömiksi. Tällöin koodin lukeminen purettuna hankaloituu, koska muuttujien ja metodien nimistä ei voi päätellä sisältöä.
Tämä tietenkään ei estä esimerkiksi algoritmien selvittämistä, mutta vaikeuttaa sitä huomattavasti.
Toisaalta kannattaa muistaa että työn hidastaminen ja vaikeuttaminen saattaa usein riittää. Harva algoritmi on niin elintärkeä ja samalla helppo selvittää, että sillä olisi lopulta mitään merkitystä. Selvittäminen koodia takaisinkääntämällä on kuitenkin kovin tuskallinen operaatio, varsinkin jos koodia on sekoitettu. Parhaatkaan takaisinkääntäjät eivät tietääkseni tee kuin suurin piirtein kelvollisen palautuksen.
Lisätietoa noista työkaluista löytyy mm. JavaWorldin menneistä numeroista, Java decompilers compared ja Protect your bytecodes from reverse engineering/decompilation .
Enemmän näkisin ongelmana tietoturvan. Toisaalta, kukaan järkevä ohjelmiston suunnittelija ei edes tee ratkaisuja, joissa julkisessa verkossa pyörivän Java-asiakasohjelman koodia tutkimalla voitaisiin saada vinkkejä palvelimen väärinkäyttöön.
12. Mikä on profiler? Miten Javaa saa profiloitua?
Profiler on ohjelmoinnin aputyökalu, jolla voidaan mitata kauanko ohjelma suorituksensa aikana missäkin osassa koodia aikaansa käyttää.
Sillä saa siis helpohkosti selville ohjelmiensa pullonkauloja.
Suurin sankarityöni tällä saralla taisi olla kun entinen pomoni käski optimoida jonkun Java-tekelettä. Profilesin sitä päivän, analysoin toisen ja kolmantena tein vartissa 10 riviä muutosta koodiin. Tulos: 20-kertainen nopeus.
Javassa profilointia voi käyttää vaikkapa näin: java_g -prof mun.pakkaus.Luokka
13. Miten saan ajettua jonkin toisen (ei-Java-)ohjelman Javasta käsin?
Runtime-oliolla: <URL:"http://java.sun.com/products/jdk/1.1/docs/api/java.lang.Runtime.html#exec(java.lang.String)">
Huomaa että jos haluat liittää natiivikoodia Java-ohjelmaasi, silloin suositeltavin tapa on JNI.
14. Miten Javalla saa luettua jonkin WWW-sivun sisällön?
java.net.HttpURLConnection.
15. Miten voi jäljittää virheitä JNI:tä käyttävistä ohjelmista?
Olen virhejäljittänyt JNI-ohjelmia Digital Unixissa ja NT:ssä Developer Studiolla.
Developer Studiossa jäljitys onnistui avaamalla natiivi-koodin projekti ja asettamalla ohjelman käynnistyskomennoksi "java Foo". Digital Unixissa käynnistin ensin gdb:n ja latasin natiivi-kirjaston symbolit, sitten käynnisti Java-ohjelman komentoriviltä toisesta ikkunasta ja lopuksi attachoin gdb:n Java-ohjelman prosessiin.
16. Miten Javalla voi käsitellä vaikkapa sarjaportteja?
Sarjaportit ja muu vastaava on laitteistoriippuvaista, joten sen tekemiseksi Javalla tarvitsee avuksi natiivi-koodia (esim. C). Tämä tarkoittaa sitä että se C-koodi on myös sitten portattava ja käännettävä jokaiselle laitealustalle erikseen, mutta niinhän tuollaiset jutut muutenkin.
JNI:stä voi lukea lisää osoitteesta <URL:"http://java.sun.com:81/docs/books/tutorial/native1.1/index.html">.
JNI:n avulla voit siis toteuttaa nuo ei-Javalla-mahdolliset operaatiot vaikkapa C-funktioina, kääntää ne jaetuksi kirjastoksi (Windowsissa DLL) ja käyttää niitä Java-ohjelmistasi käsin.
Nykyisin Sun tarjoaa Java Communications API:n niille, jotka tämän toiminnallisuuden haluavat toteuttaa, sekä mallitoteutukset Windows- ja Solaris-alustoille.Näihin voi tutustua osoitteessa http://java.sun.com/products/javacomm/index.html. Ylläolevat periaatteet pätevät silti yhä, Sun vain on nähnyt vaivan puolestamme näille kahdelle alustalle.
Sunin Java Communications API:n FAQ:n mukaan ko. laajennos ei tule mukaan tuleviinkaan Javan perusversioihin, joten tuon toimintaa kaikilla Java-alustoilla ei voi olettaa.