Чекор по чекор
Почетни чекори со Java
Објектно оријентирани концепти во Јава - Прв дел
Објектно оријентирани концепти во Јава - Втор дел
Објектно оријентирани концепти во Јава - Трет дел
Јава сервлети - Прв дел
Единствен Јава објект (singleton)
Најчести 10 грешки што ги прават Java програмерите
повеќе...
Што е тоа ...
... IDE
... Tomcat
... објект?
... класа?
... наследување?
... интерфејс?
... наследување? (прашања и одговори)
повеќе...
За загревање
Нов проект во Eclipse?
Примитивни податочни типови
Променливи
Оператори
Доделувачки, аритметички и Unary оператори
Оператори за еднаквост, релации и услови
Изрази, искази и блокови
повеќе...
Како да ...
... конвертирам java.sql.Timestamp во java.util.Date
... зададам формат на датум
... ковертирам „long“ во HEX и обратно
... прочитам датотека и променам стринг
... креирам ZIP датотека
... поврзам Apache и Tomcat користејќи mod_jk
... пратам недефиниран број на атрибути до некоја метода
повеќе...
Java преку примери
new Socket(String addr,int port)
new URL(String address)
new URL(String protocol, String host, int port, String file)
CommPort: getInputStream()
CommPortIdentifier: getPortIdentifiers()
Statement: executeQuery(String sql)
Statement: getMaxRows()
повеќе...
Грешка
Нов напис
Рубрика:
Наслов:
  
  

страна број:123
Најчести 10 грешки што ги прават Java програмерите
прегледано:  210950
 вкупно гласови:  1
 средна оценка:  4.0
 коментари:  2
Дури и да ја знаете Java-та како прстите на вашата рака, или сте почетник во програмирањето, ќе правите грешки. Природно е, човечки е, и погодете што? Најверојатно ќе ги правите истите грешки што ги прават другите, повторно и повторно. Ова е мојата листа на десет најпознати грешки што сите ги правиме, како да ги пронајдеме, и како да ги исправиме.

10. Пристапување на нестатички променливи од статички методи (како main)

Многу програмери, посебно оние нови во Java, имаат проблеми со пристапување на променливи од нивниот main метод. Методот main е маркиран како static - значи дека не треба да креираме инстанца од класата за да го повикаме main методот. На пример, Java виртуелната машина (JVM) може да ја повика апликацијата вака:

MyApplication.main ( command_line_args );


Ова значи дека не постои инстанца од MyApplication - нема променливи за пристап. На пример, следново ќе генерира компајлерска грешка:

public class StaticnoDemo {
    public String moja_promenliva = "nekoj podatok";

    public static void main (String args[]) {
        // Pristap do nestaticka promenliva od staticki metod
        System.out.println ("Ova generira kompajlerska greska" + moja_promenliva );
    }
}


Ако сакате да пристапите на класните променливи од нестатички метод (како main), мора да креирате инстанца од класата. Еве пример како правилно да напишете код за пристап до нестатички класни променливи:

public class NeStaticnoDemo {
    public String moja_promenliva = "nekoj podatok";
   
    public static void main (String args[]) {
        NeStaticnoDemo demo = new NeStaticnoDemo();
        // Pristapi klasna promenliva
        System.out.println ("Ova nema da generira greska: " + demo.moja_promenliva );
    }
}



9. Грешење на името на методот при преклопување (override)

Преклопувањето им дозволува на програмерите да ја заменат имплементацијата на методот со нов код. Многу ОО програмери често го користат. Ако користите AWT 1.1 модел за справување со настани, често ќе преклопите имплементации на listeners за да дадете своја имплементација. Еден лесен начин да паднете во стапица е погрешно да го именувате методот. Ако го сторите тоа, веќе не преклопувате метод - креирате сосема нов метод, но со исти тип на параметри и повратен тип.

public class MyWindowListener extends WindowAdapter {
    // Ova treba da bide WindowClosed
    public void WindowClose(WindowEvent e) {
        // Izleguva od programa koga korisnikot kje go iskluci prozorot
        System.exit(0);
    }
}

Компајлерите нема да реагираат на оваа грешка и затоа овој проблем е тежок да се пронајде. Симптомите на оваа грешка се изразуваат на тој начин што методот нема да биде повикан. Најдобар начин за да видите дали еден метод се повикува или не е да ставите println, да запишете порака во log фајл, или да користите trace debugger и да извршувате линија по линија. Ако вашиот метод не е повикан, значи дека сте му го погрешиле името.


8. Споредба и доделување ( = наместо == )

Оваа грешка лесно се прави. Ако сте користеле други програмски јазици претходно, како Pascal, ќе видите колку лош избор било ова на програмерите на јазикот. Во Pascal, на пример, користиме оператор := за доделување, а = за споредба. Ова личи како недостаток на C/C++, од кои Java-та влече корени.

За среќа, дури и да не го забележите ова при гледање на кодот на екран, компајлерот ќе го забележи. Најчесто, ќе пројави порака за грешка како "Can't convert xxx to boolean", каде xxx е тип во Java кој го доделувате наместо да го споредувате.


7. Споредба на два објекта ( == наместо .equals )

Кога го користиме операторот ==, всушност споредуваме референци на два објекта, за да провериме дали покажуваат на истиот објект. Не можеме да споредуваме два string-а за еднаквост користејќи го операторот ==. Во овој случај, го користиме методот equals, кој е метод наследен од страна на сите класи од java.lang.Object.

Еве правилен начин да споредувате два string-a.

    String abc = "abc"; String def = "def".

    // Los nacin
    if ( (abc + def) == "abcdef" ) {
        ......
    }

    // Dobar nacin
    if ( (abc + def).equals("abcdef") ) {
        .....
    }



6. Забуна при праќање на вредност и праќање преку референца

Ова може да биде фрустрирачки проблем за дијагностицирање, бидејќи кога гледате во кодот, можете да бидете сигурни дека праќате по референца, но отпосле пронаоѓате дека праќате вредност. Java ги користи и двата начина, и треба да ги разберете и двата.

Кога праќате примитивен тип на податок (како char, int, float, или double) на метод, тогаш праќате вредност. Тоа значи дека се прави копија на податокот и се праќа во методот. Ако методот ја модифицира вредноста, ќе ја модифицира само копијата. Штом заврши функцијата и се врати контролата кон повикувачката функција, "правата" променлива е недопрена. Ако целта е да модифицирате примитивен тип на податок, тогаш вратете го како повратен тип од функција, или ставете го во објект.

Кога праќате Java објект (како array, vector или string) на метод, тогаш праќате референца. Да, String е всушност објект, а не примитивен тип на податок. Тоа значи дека кога праќате објект во метод, праќате референца, а не дупликат. Секоја промена на класните променливи на објектот ќе бидат перманенти - што може да биде и добро и лошо, зависно од намерата.

Инаку, String не содржи методи за промена на содржината, па може да се искористи и за праќање по вредност.


5. Празен блок при исклучок (exception)

Најлесно е да се остави празен блок при случај на исклучок и да се игнорираат грешките. Но, ако навлезете во проблеми и немате пораки за грешки, станува невозможно да ги најдете причините за грешките. Дури и наједноставниот код во блокот на исклучокот може да даде придонес. На пример, ставете try { .. } catch Exception околу вашиот код за да фатите било каков тип на исклучок, и испечатете порака. Не мора да пишувате посебен handler за секој исклучок (иако ова е добра програмерска практика). Но, не оставајте празен блок, бидејќи нема да знаете што се случува. На пример:

public static void main(String args[]) {
    try {
        // Vasiot kod doagja tuka
    } catch (Exception e) {
        System.out.println ("Greska - " + e );
    }
}



4. Заборавање дека Јава е нулто индексирана

Доколку имаш познавања од C/C++ оваа точка не ти е проблем за разлика од оние кои користеле други јазици. Во Јава низите се нулто индексирани, односно индексот (позицијата) на првиот елемент во низата е 0 (нула). Збунет? Ајде едно примерче набрзина:

// Kreiranje na niza so tri stringa
String[] strNiza = new String[3];

// Indeksot na prviot element vsusnost e 0 (nula)
strNiza[0] = "Prv string";

// Indeksot na vtoriot element e 1 (eden)
strNiza[1] = "Vtor string";

// Indeksot na tretiot element e 2 (dva)
strNiza[2] = "Tret string";

Во овој пример имавме низа од 3 стринга, но за да пристапиме до елемтите во низата ние целовреме ќе треба да одземаме 1. На пример, доколку би пробале да пристапиме до strNiza[3] ние всушност пробуваме да пристапиме до 4-тиот елемент. Ова ќе фрли ArrayOutOfBoundsException, најочигледен знак дека сме го заборавиле правилото за нулто индексирање.

Друго место каде што нултото индексирање ќе ти донесе невоља се стринговите. На пример, доколку сакаш да „собереш“ карактер кој е на некоја позиција во стринг. Користејќи ја методата String.charAt(int) можеш да го изведеш тоа, но внимавај, во Јава класата String е исто така нулто индексирана. Тоа значи дека првиот карактер во низата од карактери (стрингот) е на позиција 0 (нула), вториот е на позиција 1 итн. Ова понекогаш стварно знае да биде фрустрирачки кога ќе се подрзаборави на ова, а посебно тоа ако се случи во апликација која целовремено работи со процесирање на стрингови. Доколку се погреши индексот на карактерите во run-time ќе добиеш грешка слична на онаа ArrayOutOfBoundsException, но овде прилагодена на пригодата, односно StringIndexOutOfBoundsException или како на пример:

public class StringDemo
{
    public static void main (String args[]) {
        String abc = "abc";

        System.out.println ("Karakter na pozicija 0 : " + abc.charAt(0) );
        System.out.println ("Karakter na pozicija 1 : " + abc.charAt(1) );
        System.out.println ("Karakter na pozicija 2 : " + abc.charAt(2) );

        // Ova ke isfrli Exception od tipot: StringIndexOutOfBoundsException
        System.out.println ("Karakter na pozicija 3 : " + abc.charAt(3) );
     }
}


Но запамети дека нултото индексирање не завршува на низи (Array) и на стрингови (String). Други делови од Јава-та се индексирани исто така, но не секогаш конзистентно. На пример класите java.util.Date и java.util.Calendar месеците ги започнуваат со 0 (нула), но деновите ги започнуваат со 1. Овој проблем би го демонстрирале во следниов пример:

import java.util.Date;
import java.util.Calendar;

public class NultoIndeksiranDatum
{
    public static void main (String args[]) {
        // Zemi go denesniot datum koristejki Date
        Date denes = new Date();

        // Ispecati ja povratnata vrednost od getMonth()
        System.out.println ("Date.getMonth() vraka : " +
        denes.getMonth());

        // Zemi go denesniot datum koristejki Calendar
        Calendar sega = Calendar.getInstance();

        // Ispecati ja povratnata vrednost od get ( Calendar.MONTH )
        System.out.println ("Calendar.get (month) vraka : " +
        sega.get ( Calendar.MONTH ));
    }
}




3. Заштита од конкурентен пристап до споделени променливи од страна на нишките (Threads)

Кога пишиваат програми со повеќе нишки (multi threading), многу програмери често ја фаќаат пократката патека и ги оставаат своите апликации ранливи на конфликти помеѓу нишки. Кога две или повеќе нишки конкуретно пристапуваат до некој податок тогаш постои можност (а законите на Марфи секогаш важат) дека две нишки ќе притапат или ќе го модифицираат истиот податок во исто време. Немој да мислиш дека таков проблем нема да се јави кај процесорите со една нишка (single threaded). Додека пристапува до некој податок (извршувајќи читање на податокот) твојата нишка може да биде суспендирана (ставена во мирување), а друга да почне со работа (на нејзе и дошло време на извршување, нејзините 5 милисекунди). Тогаш втората нишка ги запишува податоците, кои ќе бидат пребришани кога првата нишка ќе ги направи своите промени.

Такви проблеми не се лимитирани на апликациите со повеќе нишки или на аплети. Доколку пишувап Јава API-ја или JavaBeans, тогаш твојот код може да не биде thread-safe. Но дури и никогаш да не напишеш апликација која ќе користи нишки (thread-ови) луѓето кои ќе го користат твојот код најверојатно ќе користат. Затоа за да бидат раат тие, ако не ти, секогаш треба да се трудиш и да спречиш конкурентен пристап до податоци кои се делат.

Како ова да се спречи? Еден начин е опишан во написот Единствен Јава објект (singleton).


2. Грешки со големи/мали букви

Ова е една од најчестите грешки кои се (и ќе се) прават. Толку е едноставно да се направи, а некогаш може да се загледаш во самата грешка и да не ја приметиш разликата во големите/мали букви.

Иако нема конечно решение за таквите грешки лесно може да се привикнеш да правиш што помалце такви грешки. Едноставно следи барем неколку принципи од Јава конвенцијата за изворен код, односно запомни дека:

  • сите методи и променливи во Јава започнуваат со мала буква
  • сите методи и променливи користат голема буква онаму каде што треба да започне нов збор. На пример: getDoubleValue()

1. Покажувачите кон Null (Null pointers)!


Покажувачите кон Null вредност се најчеста грешка која Јава програмерите ја прават. Компајлерот неможе да ја најде оваа грешка за тебе, таа ќе се покаже сасмо во време на извршување на програмот, а доколку ти не ја откриеш, корисниците на програмот сигурно ќе ја откријат.

Кога ќе се проба да се пристапи до некој објект, а референцата до тој објект е „null“ тогаш Јава-та фрла NullPointerException. Причината за покажувачите кон null можат да бидат најразлични, но најчесто е заборавена иницијализација на некој објект или не е проверен резултатот од некоја повикана метода.

Многу функции враќаат null вредност за да индицираат некоја грешка, но доколку не ја провериш повратната вредност од функцијата никогаш нема да знаеш што се случува. А поради тоа што грешката се јавува само при одредени околности, нормалното тестирање нема да вроди со плод, а тоа ќе доведе да твоите корисници (корисниците на твојот програм) ја бараат грешката за тебе.

Друг случај е на пример каде што иницијализацијата е пропратена со малце невнимание или каде што таа е условна. На пример разгледај го следниов код и опробај се да го најдеш проблемот:

public static void main(String args[]) {
    // Prima maximum 3 parametri
    String[] lista = new String[3];

    int index = 0;

    while ( (index < args.length) "
    }

    // Proveti gi site parametri
    for (int i = 0; i < lista.length; i++) {
        if (lista[i].equals "-help") {
            // .........
        }    else
            if (lista[i].equals "-cp") {
                // .........
            }
            // else .....
    }   
}

Доколку неуспеа да најдеш можен проблем, прочитај го истиот на следната страна.
страна број: 1 2 : следна страна >> 
 
Коментирај
автор: Анонимус
Анонимните коментари ќе бидат објавувани веднаш после нивната проверка.
За да вашиот коментар биде веднаш валиден претходно пријавете се или креирајте свој профил


напишал: slavejovanovski (20.01.2008 01:02:56)
Дефинитивно сите почетниците во Јава ги прават овие грешки. Некогаш дури и професионални програмери, кои никогаш не програмирале во Јава, ги имаат истите проблеми. Но не е се изгубено. Со тек на време овие грешки полека исчезнуваат.

Според моето мислење, проблемот со број 7 "Споредба на два објекта ( == наместо .equals )" останува проблем во текот на целата Јава кариера, посебно доколку користите други јазици како C/C++ додека програмирате во Јава. Операторот "=" е премногу попривлечен од ".equals()" :)

Нешто слично се случува и со пробемот со број 1 "1. Покажувачите кон Null (Null pointers)!". Премногу често забораваме да провериме дали некој објект е null пред да го користиме.

Проблемот 3 е претежно проблем во покомплицирани програми и не би очекувал да биде сретнат од почетници, но доколку го сретнете овој проблем ве очекуваат долги непреспани ноќи пробувајќи да го репродуцирате и поправите проблемот.

Е сега доаѓаме до проблемот 6 "Забуна при праќање на вредност и праќање преку референца". Јас имам малку поразлично мислење од авторот на тој параграф.

Според Јава спецификациите, во Јава СЕКОГАШ праќате по вредност (pass-by-value). Но пред да речете дека немам поим што зборувам, стрпете се за да се објаснам. Ова е лесно да се докаже за примитивните типови (float, int, ...) бидејќи промените во методот не се рефлектираат надвор од методот.

Но ако Јава е pass-by-value тогаш зошто промените на некои објекти како MojObjekt се рефлектираат надвор?

Кога креирате објект во Јава, виртуелната машина всушност ви враќа назад покажувач кон вистинскиот објект а не вредноста на тој објект. Значи после

MojObjekt x = new MojObjekt(),

x покажува кон некој објект во меморија. x не ја содржи вредноста на објект од типот MojObjekt.

Доколку x го пратите во некој метод тогаш ја праќате вредноста на x кон тој метод.

void metod(MojObjekt lokalenX) {
lokalenX.dodadi(3);
}

Бидејќи вредноста на x е всушност покажувач кон некој објект, lokalenX ќе покaжува кон истиот објект. Повикувањето на lokalenX.dodadi(3); е исто со повикувањето на x.dodadi(3) надвор од методот.

Погледнете го овој документ:

http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#37472

Значи Јава е поблиска до C кога станува збор за како се праќаат вредности до методи. Во C++ постои вистинско праќање на вредности по референца со помош на &, како на пример:

void metod(MojObjekt & x){
}

напишал: Анонимус (01.07.2008 22:17:41)
ej super e sajtov izvinete sho nemam kirilica. Sasho Lazarevski go spomna. Ni predava Java vo Strumica. Ne znaev deka ima mk sajt za java. Se registriram na forumot odma . Keif mi e da napravime edna dobra java community :) pzodrav i kep up the good work.
пребарување
најди
 
Форум
 
JugMK
GetJava Download Button
http://www.eclipse.org
 
 
 
 
Copyrights © 2006 - 2024 by Java.com.mk
Права и правила за користење на java.com.mk
Контакт адреса:
contact AT java.com.mk
Powered by Supernova v.0.70 beta
JavaTM и Java-базираните ознаки се трговски марки или регистрирани трговски марки на Sun Microsystems, Inc. во САД и други држави. Java.com.mk никако не соработува со Sun Microsystems, Inc.
Сите други трговски марки се сопственост на нивните сопственици.