JavaRush /Блоги Java /Random-TG /Хатогиҳои барномасозони ибтидоии java. Қисми 2
articles
Сатҳи

Хатогиҳои барномасозони ибтидоии java. Қисми 2

Дар гурӯҳ нашр шудааст
Хатогиҳои барномасозони ибтидоии java. Қисми 1

9. Даъват кардани усулҳои синфи ғайристатикӣ аз усули main()

Нуқтаи вуруди ҳар як барномаи Java бояд усули статикӣ бошад main:
Хатогиҳои барномасозони ибтидоии java.  Қисми 2 - 1
public static void main(String[] args) {
  ...
}
Азбаски ин усул статикӣ аст, шумо наметавонед аз он усулҳои синфии ғайристатикиро даъват кунед. Донишҷӯён аксар вақт инро фаромӯш мекунанд ва кӯшиш мекунанд, ки усулҳоро бидуни эҷоди як мисоли синф даъват кунанд. Ин хато одатан дар ибтидои омӯзиш, вақте ки донишҷӯён барномаҳои хурд менависанд, содир мешавад. Намунаи нодуруст:
public class DivTest {
    boolean divisible(int x, int y) {
        return (x % y == 0);
    }

    public static void main(String[] args) {
        int v1 = 14;
        int v2 = 9;

        // на следующие строки компилятор выдаст ошибку
        if (divisible(v1, v2)) {
            System.out.println(v1 + " is a multiple of " + v2);
        } else {
            System.out.println(v2 + " does not divide " + v1);
        }
    }
}
Ду роҳи ислоҳи хато вуҷуд дорад: усули дилхоҳро статикӣ гардонед ё намунаи синфро эҷод кунед. Барои интихоби усули дуруст, аз худ бипурсед, ки оё метод майдонро истифода мебарад ё усулҳои дигари синфӣ. Агар ҳа, шумо бояд як намунаи синфро эҷод кунед ва дар он методро даъват кунед, вагарна шумо бояд методро статикӣ кунед. Намунаи ислоҳшуда 1:
public class DivTest {
    int modulus;

    public DivTest(int m) {
      modulus = m;
    }

    boolean divisible(int x) {
        return (x % modulus == 0);
    }

    public static void main(String[] args) {
        int v1 = 14;
        int v2 = 9;

        DivTest tester = new DivTest(v2);

        if (tester.divisible(v1) {
            System.out.println(v1 + " is a multiple of " + v2);
        } else {
            System.out.println(v2 + " does not divide " + v1);
        }
    }
}
Намунаи ислоҳшуда 2:
public class DivTest {
    static boolean divisible(int x, int y) {
        return (x % y == 0);
    }

    public static void main(String[] args) {
        int v1 = 14;
        int v2 = 9;

        if (divisible(v1, v2)) {
            System.out.println(v1 + " is a multiple of " + v2);
        } else {
            System.out.println(v2 + " does not divide " + v1);
        }
    }
}

10. Истифодаи an objectҳои синфи String ҳамчун параметрҳои метод.

Дар Java, синф java.lang.Stringмаълумоти сатрро нигоҳ медорад. Аммо, сатрҳо дар Java
  1. доимӣ доранд (яъне онҳоро тағир додан мумкин нест),
  2. an objectҳо мебошанд.
Аз ин рӯ, онҳоро ҳамчун буфери аломатҳо баррасӣ кардан мумкин нест; онҳо an objectҳои тағирнопазиранд. Баъзан донишҷӯён сатрҳоро бо интизории хато мегузаронанд, ки an objectи сатр ҳамчун массиви аломатҳо тавассути истинод (ба мисли C ё C++) интиқол дода мешавад. Компилятор одатан инро хато ҳисоб намекунад. Намунаи нодуруст.
public static void main(String args[]) {
   String test1 = "Today is ";
   appendTodaysDate(test1);
   System.out.println(test1);
}

/* прим. редактора: закомментированный метод должен иметь модификатор
    static (здесь автором допущена ошибка №9)
public void appendTodaysDate(String line) {
    line = line + (new Date()).toString();
}
*/

public static void appendTodaysDate(String line) {
    line = line + (new Date()).toString();
}
Дар мисоли дар боло овардашуда, донишҷӯ мехоҳад test1бо гузоштани арзиши нав ба параметр lineдар метод арзиши тағирёбандаи маҳаллиро тағир диҳад appendTodaysDate. Табиист, ки ин кор намекунад. Маънои он lineдигар мешавад, аммо маънӣ test1ҳамоно боқӣ мемонад. Ин хато аз сабаби нофаҳмӣ ба вуҷуд меояд, ки (1) an objectҳои java ҳамеша тавассути истинод интиқол дода мешаванд ва (2) сатрҳо дар java тағирнопазиранд. Шумо бояд фаҳмед, ки an objectҳои сатр ҳеҷ гоҳ арзиши худро тағир намедиҳанд ва ҳама амалҳо дар сатрҳо an objectи нав эҷод мекунанд. Барои ислоҳ кардани хато дар мисоли дар боло овардашуда, шумо бояд сатрро аз усул баргардонед ё an objectро StringBufferҳамчун параметр ба усул ба ҷои String. Намунаи ислоҳшуда 1:
public static void main(String args[]) {
   String test1 = "Today is ";
   test1 = appendTodaysDate(test1);
   System.out.println(test1);
}

public static String appendTodaysDate(String line) {
    return (line + (new Date()).toString());
}
Намунаи ислоҳшуда 2:
public static void main(String args[]) {
   StringBuffer test1 = new StringBuffer("Today is ");
   appendTodaysDate(test1);
   System.out.println(test1.toString());
}

public static void appendTodaysDate(StringBuffer line) {
    line.append((new Date()).toString());
}

тахминан. тарҷума
Дар асл, фаҳмидани он ки хатогӣ чӣ гуна аст, осон нест. Азбаски an objectҳо тавассути истинод интиқол дода мешаванд, ин маънои онро дорад, lineки он ба ҳамон ҷой ишора мекунад test1. Ин маънои онро дорад, ки бо эҷоди як нав line, мо як нав эҷод мекунем.Дар test1мисоли нодуруст, ҳама чиз ба назар чунин менамояд, ки гӯё интиқол Stringаз рӯи арзиш аст, на аз рӯи истинод.

11. Эълони конструктор ҳамчун метод

Созандагони an object дар Java аз рӯи намуди зоҳирӣ ба усулҳои муқаррарӣ монанданд. Ягона тафовут дар он аст, ки созанда навъи бозгаштро муайян намекунад ва ном бо номи синф якхела аст. Мутаассифона, Java имкон медиҳад, ки номи метод бо номи синф якхела бошад. Дар мисоли зер, донишҷӯ мехоҳад Vector listҳангоми сохтани синф майдони синфро оғоз кунад. Ин рӯй нахоҳад дод, зеро усул 'IntList'созанда нест. Намунаи нодуруст.
public class IntList {
    Vector list;

    // Выглядит How конструктор, но на самом деле это метод
    public void IntList() {
        list = new Vector();
    }

    public append(int n) {
        list.addElement(new Integer(n));
    }
}
NullPointerExceptionВақте ки бори аввал ба майдон ворид мешавад, code истисноро мегузорад list. Ислоҳи хато осон аст: шумо танҳо бояд арзиши бозгаштро аз сарлавҳаи усул хориҷ кунед. Намунаи ислоҳшуда:
public class IntList {
    Vector list;

    // Это конструктор
    public IntList() {
        list = new Vector();
    }

    public append(int n) {
        list.addElement(new Integer(n));
    }
}

12. Ба намуди зарурӣ партофтани an objectро фаромӯш кардед

Мисли ҳама забонҳои ба an object нигаронидашуда, дар Java шумо метавонед an objectро ҳамчун суперкласси он ишора кунед. Ин номида мешавад 'upcasting', он ба таври худкор дар Java анҷом дода мешавад. Аммо, агар тағирёбанда, майдони синф ё арзиши бозгашти метод ҳамчун суперкласс эълон карда шавад, майдонҳо ва усулҳои зерсинф ноаён хоҳанд буд. Бо истинод ба суперкласс ҳамчун зерсинф номида мешавад 'downcasting', шумо бояд онро худатон ба қайд гиред (яъне an objectро ба зерсинфи дилхоҳ оваред). Донишҷӯён аксар вақт дар бораи зергурӯҳбандии an object фаромӯш мекунанд. Ин аксар вақт ҳангоми истифодаи массивҳои Объектҳо ва коллексияҳо аз баста java.util(маънои Чаҳорчӯбаи Коллексия ) рӯй медиҳад. Мисоли дар поён овардашуда Stringan objectро ба массив мегузорад ва сипас онро аз массив хориҷ мекунад, то онро бо сатри дигар муқоиса кунад. Компилятор хатогиро ошкор мекунад ва то он даме, ки навъи cast ба таври возеҳ муайян карда нашавад, codeро тартиб намедиҳад. Намунаи нодуруст.
Object arr[] = new Object[10];
arr[0] = "m";
arr[1] = new Character('m');

String arg = args[0];
if (arr[0].compareTo(arg) < 0) {
    System.out.println(arg + " comes before " + arr[0]);
}
Маънои кастинги навъи барои баъзеҳо душвор аст. Усулҳои динамикӣ махсусан аксар вақт мушкилотро ба вуҷуд меоранд. equalsДар мисоли дар боло овардашуда, агар метод ба ҷои - истифода мешуд compareTo, компилятор хато намегузошт ва code дуруст кор мекард, зеро усули equalsсинф номида мешуд String. Шумо бояд фаҳмед, ки пайванди динамикӣ аз downcasting. Намунаи ислоҳшуда:
Object arr[] = new Object[10];
arr[0] = "m";
arr[1] = new Character('m');

String arg = args[0];
if ( ((String) arr[0]).compareTo(arg) < 0) {
    System.out.println(arg + " comes before " + arr[0]);
}

13. Истифодаи интерфейсҳо.

Барои бисёре аз донишҷӯён, фарқияти байни синфҳо ва интерфейсҳо комилан равшан нест. Аз ин рӯ, баъзе донишҷӯён кӯшиш мекунанд, ки интерфейсҳоро ба мисли Observerё Runnableбо истифода аз калимаи калидии extensions ба ҷои амалӣ татбиқ кунанд . Барои ислоҳ кардани хато, шумо танҳо бояд калимаи калидиро ба калимаи дуруст ислоҳ кунед. Намунаи нодуруст:
public class SharkSim extends Runnable {
    float length;
    ...
}
Намунаи ислоҳшуда:
public class SharkSim implements Runnable {
    float length;
    ...
}
Хатогии марбут: Тартиби нодурусти васеъкунӣ ва татбиқи блокҳо . Тибқи мушаххасоти Java, эъломияҳои тамдиди синф бояд пеш аз эъломияи татбиқи интерфейс ворид шаванд. Инчунин, барои интерфейсҳо, калимаи калидии implements бояд танҳо як маротиба навишта шавад; интерфейсҳои сершумор бо вергул ҷудо карда мешаванд. Чанд мисоли хатои бештар:
// Неправильный порядок
public class SharkSim implements Swimmer extends Animal {
    float length;
    ...
}

// ключевое слово implements встречается несколько раз
public class DiverSim implements Swimmer implements Runnable {
    int airLeft;
    ...
}
Намунаҳои ислоҳшуда:
// Правильный порядок
public class SharkSim extends Animal implements Swimmer {
    float length;
    ...
}

// Несколько интерфейсов разделяются запятыми
public class DiverSim implements Swimmer, Runnable {
    int airLeft;
    ...
}

14. Истифодаи арзиши баргардонидани усули суперклассро фаромӯш кардед

Java ба шумо имкон медиҳад, ки усули суперкласси шабеҳро аз зерсинф бо истифода аз калимаи калидӣ даъват кунед. Баъзан донишҷӯён бояд усулҳои суперклассро даъват кунанд, аммо аксар вақт истифодаи арзиши бозгаштро фаромӯш мекунанд. Ин махсусан дар байни донишҷӯёне, ки усулҳо ва арзишҳои бозгашти онҳоро ҳанӯз нафаҳмидаанд, рӯй медиҳад. Дар мисоли дар поён овардашуда донишҷӯ мехоҳад натиҷаи усули toString()суперсинфро ба натиҷаи toString()усули зерсинф дохил кунад. Аммо, он арзиши баргардонидани усули суперклассро истифода намебарад. Намунаи нодуруст:
public class GraphicalRectangle extends Rectangle {
      Color fillColor;
      boolean beveled;
      ...
      public String toString() {
          super();
          return("color=" + fillColor + ", beveled=" + beveled);
      }
}
Барои ислоҳи хато, одатан таъин кардани арзиши бозгашт ба тағирёбандаи маҳаллӣ кифоя аст ва сипас ҳангоми ҳисоб кардани натиҷаи усули зерсинф ин тағирёбандаро истифода баред. Намунаи ислоҳшуда:
public class GraphicalRectangle extends Rectangle {
      Color fillColor;
      boolean beveled;
      ...
      public String toString() {
          String rectStr = super();
          return(rectStr + " - " +
         "color=" + fillColor + ", beveled=" + beveled);
      }
}

15. Илова кардани ҷузъҳои AWT-ро фаромӯш кардед

AWT модели оддии тарҳрезии GUI-ро истифода мебарад: ҳар як ҷузъи интерфейс бояд аввал бо истифода аз созандаи худ сохта шавад ва сипас бо истифода аз add()усули ҷузъи волидайн дар равзанаи барнома ҷойгир карда шавад. Ҳамин тариқ, интерфейс дар AWT сохтори иерархӣ мегирад. Донишҷӯён баъзан ин 2 қадамро фаромӯш мекунанд. Онҳо ҷузъро эҷод мекунанд, аммо ҷойгир кардани онро дар равзанаи васеъкунӣ фаромӯш мекунанд. Ин дар марҳилаи тартибдиҳӣ ба хатогиҳо оварда намерасонад; ҷузъ танҳо дар равзанаи барнома пайдо намешавад. Намунаи нодуруст.
public class TestFrame extends Frame implements ActionListener {
    public Button exit;

    public TestFrame() {
        super("Test Frame");
        exit = new Button("Quit");
    }
}
Барои ислоҳ кардани ин хато, шумо танҳо бояд ҷузъҳоро ба волидони онҳо илова кунед. Мисоли зер нишон медиҳад, ки чӣ тавр ин корро кардан мумкин аст. Бояд қайд кард, ки аксар вақт донишҷӯе, ки илова кардани ҷузъро ба равзанаи барнома фаромӯш мекунад, инчунин таъин кардани шунавандагони ҳодисаро ба ин компонент фаромӯш мекунад. Намунаи ислоҳшуда:
public class TestFrame extends Frame implements ActionListener {
    public Button exit;

    public TestFrame() {
        super("Test Frame");

        exit = new Button("Quit");

        Panel controlPanel = new Panel();
        controlPanel.add(exit);

        add("Center", controlPanel);

        exit.addActionListener(this);
    }

    public void actionPerformed(ActionEvent e) {
        System.exit(0);
    }
}

17. Оғози ҷараёнро фаромӯш кардаед

Multithreading дар Java бо истифода аз java.lang.Thread. Давраи ҳаёти ришта аз 4 марҳила иборат аст: оғоз, оғоз, баста ва қатъ. Риштаи навтаъсис дар ҳолати ибтидоӣ қарор дорад. Барои ба ҳолати корӣ даровардани он, шумо бояд онро даъват кунед start(). Баъзан донишҷӯён ришта эҷод мекунанд, аммо оғоз кардани онҳоро фаромӯш мекунанд. Одатан хатогӣ вақте рух медиҳад, ки донишҷӯ дар бораи барномасозии параллелӣ ва мултимедиявӣ дониши нокифоя дорад. (тақрибан. тарҷума: Ман пайвастро намебинам) Барои ислоҳи хато, шумо танҳо бояд риштаро оғоз кунед. Дар мисоли зер донишҷӯ мехоҳад бо истифода аз интерфейс аниматсияи расмро эҷод кунад Runnable, аммо оғоз кардани риштаро фаромӯш кардааст. Намунаи нодуруст
public class AnimCanvas extends Canvas implements Runnable {
        protected Thread myThread;
        public AnimCanvas() {
                myThread = new Thread(this);
        }

        // метод run() не будет вызван,
        // потому что поток не запущен.
        public void run() {
                for(int n = 0; n < 10000; n++) {
                   try {
                     Thread.sleep(100);
                   } catch (InterruptedException e) { }

                   animateStep(n);
                }
        }
        ...
}
Намунаи ислоҳшуда:
public class AnimCanvas extends Canvas implements Runnable {
        static final int LIMIT = 10000;
        protected Thread myThread;

        public AnimCanvas() {
                myThread = new Thread(this);
                myThread.start();
        }

        public void run() {
                for(int n = 0; n < LIMIT; n++) {
                        try {
                          Thread.sleep(100);
                        } catch (InterruptedException e) { }

                        animateStep(n);
                }
        }
        ...
}
Давраи ҳаёти ришта ва муносибати байни риштаҳо ва синфҳое, ки интерфейсро амалӣ мекунанд Runnable, як ҷузъи хеле муҳими барномасозии Java мебошад ва таваҷҷӯҳ ба ин муфид хоҳад буд.

18. Истифодаи усули манъшудаи readLine() синфи java.io.DataInputStream

readLine()Дар versionи Java 1.0, шумо бояд усули синфро барои хондани сатри матн истифода баред java.io.DataInputStream. Версияи Java 1.1 маҷмӯи пурраи синфҳои I/O-ро илова кард, то амалиёти I/O-ро барои матн таъмин намояд: Readerва Writer. Ҳамин тариқ, аз versionи 1.1 барои хондани сатри матн, шумо бояд усули readLine()синфро истифода баред java.io.BufferedReader. Донишҷӯён шояд аз ин тағирот огоҳ набошанд, хусусан агар онҳо аз китобҳои кӯҳна таълим гирифта бошанд. (тақрибан. Тарҷума: воқеан дигар аҳамият надорад. Аз эҳтимол дур нест, ки касе ҳоло аз китобҳои 10 сола таҳсил кунад). Усули кӯҳна readLine()дар JDK боқӣ мемонад, аммо ғайриқонунӣ эълон шудааст, ки аксар вақт донишҷӯёнро ба иштибоҳ меорад. Он чизе ки шумо бояд фаҳмед, ин аст, ки истифодаи усули readLine()синф java.io.DataInputStreamнодуруст нест, он танҳо кӯҳна аст. Шумо бояд синфро истифода баред BufferedReader. Намунаи нодуруст:
public class LineReader {
    private DataInputStream dis;

    public LineReader(InputStream is) {
        dis = new DataInputStream(is);
    }

    public String getLine() {
        String ret = null;

        try {
          ret = dis.readLine();  // Неправильно! Запрещено.
        } catch (IOException ie) { }

        return ret;
    }
}
Намунаи ислоҳшуда:
public class LineReader {
    private BufferedReader br;

    public LineReader(InputStream is) {
        br = new BufferedReader(new InputStreamReader(is));
    }

    public String getLine() {
        String ret = null;

        try {
          ret = br.readLine();
        } catch (IOException ie) { }

        return ret;
    }
}
Усулҳои дигари мамнӯъ дар versionҳои дертар аз 1.0 вуҷуд доранд, аммо ин маъмултарин аст.

19. Истифодаи дукарата ҳамчун шинокунанда

Мисли аксари забонҳои дигар, Java амалиётҳоро дар рақамҳои нуқтаи шинокунанда (рақамҳои касрӣ) дастгирӣ мекунад. Java дорои ду намуди ибтидоӣ барои рақамҳои шинокунанда дорад: doubleдақиқии IEEE 64-бит ва floatдақиқии IEEE 32-бит. Мушкилот ҳангоми истифодаи ададҳои даҳӣ ба монанди 1.75, 12.9e17 ё -0.00003 аст - компилятор онҳоро ба навъи double. Java дар амалиётҳое, ки аз даст додани дақиқӣ ба вуқӯъ мепайвандад, навъҳои таркишро иҷро намекунад. Ин навъи кастинг бояд аз ҷониби барномасоз анҷом дода шавад. Масалан, Java ба шумо иҷоза намедиҳад, ки арзиши навъиро ба intтағирёбандаи навъи byteбидуни интиқоли навъи, тавре ки дар мисоли зер нишон дода шудааст, таъин кунед.
byte byteValue1 = 17; /* неправильно! */
byte byteValue2 = (byte)19; /* правильно */
Азбаски ададҳои касрӣ аз рӯи навъи нишон дода мешаванд doubleва таъинот doubleба тағирёбандаи намуд floatметавонад боиси аз даст додани дақиқ гардад, тартибдиҳанда аз ҳама гуна кӯшиши истифодаи рақамҳои касрӣ ҳамчун float. Ҳамин тавр, истифодаи супоришҳои дар поён овардашуда аз тартиб додани синф пешгирӣ мекунад.
float realValue1 = -1.7;          /* неправильно! */
float realValue2 = (float)(-1.9); /* правильно */
Ин супориш дар C ё C++ кор хоҳад кард, аммо дар Java он хеле сахттар аст. 3 роҳи халос шудан аз ин хато вуҷуд дорад. Шумо метавонед doubleба ҷои type -ро истифода баред float. Ин роҳи ҳалли соддатарин аст. Дарвоқеъ, истифодаи арифметикаи 32-бит ба ҷои 64-бит каме маъно дорад; фарқияти суръатро то ҳол JVM мехӯрад (ғайр аз ин, дар протсессорҳои муосир ҳама рақамҳои касрӣ ба формати протсессори 80-бит табдил дода мешаванд. пеш аз ҳама гуна амалиёт сабти ном кунед). Ягона бартарии истифодаи онҳо floatдар он аст, ки онҳо хотираи камро ишғол мекунанд, ки ҳангоми кор бо миқдори зиёди тағирёбандаҳои касрӣ муфид аст. Шумо метавонед тағирдиҳандаи навъи рақамро истифода баред, то ба компилятор чӣ гуна нигоҳ доштани рақамро бигӯед. Тағйирдиҳанда барои намуд float - 'f'. Ҳамин тариқ, компилятор навъи 1.75-ро ба double, ва таъин мекунад 1.75f - float. Барои намуна:
float realValue1 = 1.7;    /* неправильно! */
float realValue2 = 1.9f;   /* правильно */
Шумо метавонед кастинги навъи возеҳро истифода баред. Ин роҳи камтарин шево аст, аммо он ҳангоми табдил додани тағирёбандаи навъи doubleба type муфид аст float. Мисол:
float realValue1 = 1.7f;
double realValue2 = 1.9;
realValue1 = (float)realValue2;
Шумо метавонед маълумоти бештарро дар бораи рақамҳои нуқтаи шинокунанда дар ин ҷо ва инҷо хонед.

— шархи тарчумон —
Хамин аст.
Дар мисоли 10, хатои 9 воқеан содир шудааст.Ман онро дарҳол пай бурдам, аммо навиштани ёддоштро фаромӯш кардам. вале онро ислох накардааст, то ки бо сарчашмаи аслй ихтилофе набошад.

Муаллиф: A.Grasoff™ Пайванд ба манбаъ: Хатогиҳои барномасозони ибтидоии java
Шарҳҳо
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION