Не сте регистриран! Регистрирайте се БЕЗПЛАТНО, за да използвате услугите на сайта!

   Рубрики
 
 
 
 

 Форуми
» SEO и оптимизация
» Всичко за PHP и Perl
» Всичко за C, C++ и .NET
» Всичко за Java и JSP
» Всичко за SQL и MySQL
» Всичко за XHTML и CSS
» Презентация на сайтове
 Програмиране на основни алгоритми на Java - част 2
  1. Програмиране на основни алгоритми на Java - част 2
     
Автор  eminem (04.02.2005 16:31)  съобщение до автора
Погледнат  7751 пъти  добави към любими
Оценка  добави коментар
Гласове  15  изпрати на приятел
Коментари  (2)  абонирай се за Java
    Страница 1 / 1

 



ИЗКЛЮЧИТЕЛНА СИТУАЦИЯ


При изпълнението на програма може да възникнат грешки (при излизане извън обема на масив; при опит на променлива от даден тип да бъде присвоена стойност от друг тип и т.н.). Когато възникне такава грешка (или има вероятност да възникне), казваме че е налице т.нар. изключителна ситуация. Компилаторът следи за обработката на изключителните ситуации и програмистът е длъжен да осигури тяхната обработка (т.е. как да постъпи компютъра, ако възникне съответната изключителна ситуация). По този начин обработката на изключителни ситуации в Java е част от създаването на програмата.

Съществуват два типа изключителни ситуации – системни и определени от програмиста. При работа с изключителни ситуации се използват следните понятия – генериране на ситуация, прихващане на ситуация и обработка на ситуация.

Прихващане и обработка
Прихващането на ситуация и нейната обработка се извършва с помощта на конструкцията – try-catch-finally, включваща три програмни блока. Последният блок finally се използва рядко. Типичната конструкция се състои от първите два блока и има следният вид:
CODE
1
2
3
4
5
6
try {
//програмен код, в който настъпва  изключителна ситуация
} catch(<изключителнаситуация><обект>) {//прихващане на
                                                                         
//ситуация
//програмен код за обработка на изключителна ситуация
}
Възможно е да съществуват няколко блока catch, всеки за прихващане и обработка на различна ситуация. Тези блокове прихващат обект от клас <изключителна ситуация>, генериран от блока try. Класът <изключителна ситуация> наследява класа Exception и може да съдържа произволни данни и методи, необходими и полезни за обработката на изключителната ситуация.

Пр. 1
Опитайте се да компилирате следната проста програма:
 CODE
1
2
3
4
5
6
import java.io.*;
 
class ExceptionTest {
  
public static void main(String[] args) {
         
System.in.read();
 
}
}

В резултат на компилацията ще бъде открита грешка, че изключителната ситуация “IOException” не е прихваната:
CODE
1
"ExceptionTest.java": Error #: 360 : unreported exception: java.io.IOException; must be caught or declared to be thrown at line 17, column 17
Възможни са две решения. Първото е програмният код да прихване и обработи изключителната ситуация (с конструкция try-catch). Второто е методът main да се освободи от отговорността за нея, като я прехвърли на извикващия го. За тази цел в заглавието на метода се поставя служебната дума throws, следвана от името на изключителната ситуация.

Първо решение:
CODE
1
2
3
4
5
6
7
8
9
10
import java.io.*;
 
class ExceptionTest {
     
public static void main(String[] args) {
         
try {
System.in.read();
         
} catch (IOException e) {
        // код за обработка
}
       }
    }

Второ решение:
CODE
1
2
3
4
5
6
import java.io.*;
 
class ExceptionTest {
     
public static void main(String[] args) throws IOException {
         
System.in.read();
     
}
}

Блокът catch е организиран като функция, получаваща обект от тип изключителна ситуация. Областта на видимост на обекта е само в блока catch. Блокът catch се изпълнява само, ако настъпи съответната ситуация, т.е. в кода на try се генерира обект от тип, съвпадащ с типа на параметъра в catch. В противен случай (при нормална ситуация) след последния оператор в блока try се изпълнява първият оператор след конструктура try-catch.
В случай на един оператор е допустимо изпускане на фигурните скоби.

Пр. 2
try System.in.read();
catch (IOException e); //празен оператор в частта catch
Името на параметъра в блока catch не може да съвпада с никое от имената на локалните променливи!

Генериране на изключителна ситуация
Генерирането на системна изключителна ситуация се извършва от системата, а на потребителска – с оператора throw . Този оператор се поставя в програмния код на блока try, на мястото, където не може да продължи нормалното изпълнение на програмата. При използването му с оператора new се генерира обект от тип <изключителна ситуация>.

Пр. 3
CODE
1
2
3
4
5
6
7
8
9
10
11
12
try {
        //действия
       
if (<условие за ненормална ситуация>)
           
throw new <тип-изключителна-ситуация>;
        //нормални действия
} catch (<тип-изключителна-ситуация> е) {
        //обработка на изключителна ситуация
}

class <тип-изключителна-ситуация> extеnds Throwable {
        …
}

В класа изключителна ситуация може да се дефинират конструктори и при настъпване на ситуация да се предават параметри на обекта.

Задача 1 Да се организира клас, представляващ масив от цели числа, така че да се обработват следните изключителни ситуации: грешен размер на масива при неговата дефиниция и индексиране извън границите на масива.

Проектиране:
За да се обработват тези две ситуации, необходимо е за всяка от тях да се дефинира клас, разширяващ класа Exception. При втората ситуация е добре да се предава и индексът, при който тя е настъпила. За тази цел трябва да се въведат два класа, единият от коите е тривиален.



Програмиране:
CODE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class Size extends Exception {}
class Range extends exception {
    
private int index;
    
public Range( int anIndex ) {index = anIndex;}
    
public int getIndex() { return index; }
}

//основния клас е:
class ArrayOfInteger {
    
private int [] theArray;
    
private int theSize;
    
public ArrayOfOnteger( int size ) throws Size {
          
if ( size <= 0)
           
throw new Size();
          
theSize = size;
          
theArray = new int [size];
          
for( int index = 0; index < size; index++)
           
theArray[index]=index;
    
}
    
public int get( int index ) throws Range {
          
if ( index <= 0 || index > theSize)
           
throw new Range ( index );
          
return (theArray [index-1]);
    
}
}
class Example {
   
// example обработва Range, но прехвърля Size
     void example
(int size) throws Size {
          
try {
           
ArrayOfInteger array = new ArrayOfInteger(size);
           
int x = array.get(0); //get(1)
           
System.out.println(Okey);
          
} catch(Range r) {
           
System.out.println(Index out of range:” + r.getIndex());
          
}
     }
    
public static void main(String [] args) {
          
try {
           
Example e = new Example();
           
e.example(-1); // e.example(10)
           }
catch(Size s) {
           
System.out.println(Invalid size.”);
          
}
     }
}

Разучете програмата. Забележете, че методът example на класа Example обработва ситуацията Range, но се освобождава и прехвърля на извикващият го метод main ситуацията Size. Методите ArrayOfInteger и get, в които настъпват ситуациите (генерират се обектите) се освобождават от тях. В случай, че не се зададе ключовата дума throws след параметрите, компилаторът ще сигнализира за грешка.
Прехвърлянето на обработката на една изключителна ситуация на извикващия метод от извиквания става с поставяне на името й в заглавния ред на метод:

CODE
1
2
3
<тип> <име-на-метод>([<параметър>,,,]) throws <изключ. ситуация>,,, {
                      …
throw new <>;…
}

Въведете и стартирайте горната програма. След това променете и пак стартирайте програмата последователно, както следва: първо, обръщението e.example(-1) на e.example(10) в метода main и второ int x = array.get(0) в метода example на int x = array.get(1).
Ако е необходимо двете ситуации да се обработват в example, програмният код на класа Example ще изглежда така:
CODE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Example {
   
//example Range Size
     void example
(int size) {
          
try {
           
ArrayOfInteger array = new ArrayOfInteger(size);
           
int x = array.get(0); // get(1);
           
System.out.println(Okey);
          
} catch( Range r ) {
           
System.out.println(Index out of range:” + r.getIndex());
          
} catch( Size s ) {
           
System.out.println(Invalid size.”);
          
}
     }
    
public static void main( String [] args) {
          
Example e = new Example();
          
e.example(-1); //e.example(10);
    
}
}
На метода main не се прехвърля изключителна ситуация и поради тази причина в него няма конструкция try-catch. В метода example има два блока catch.

Блокът finally
Блокът finally позволява задаване на програмен код, който да се изпълнява винаги при напускане на конструктцията try-catch. Това изначава, че независимо дали настъпва ситуация или не след try (при нормална работа) и след catch (при настъпила ситуация) се изпълнява кодът от блока finally.

Йерархия на класа Exception


•    Изключение се нарича неочаквано събитие (грешка) в програмата
•    В рамките на програмата вие определяте изключенията като класове
•    За да започне търсене на изключения се използва оператора try
•    За да прихване конкретно изключение, програмата използва оператора catch
•    За да предизвика изключение в момента на възникване на грешка, програмата използва оператора throw
•    Когато програмата прихване изключение, тя го обработва

РАБОТА С ТЕКСТОВЕ


Компютрите не биха имали толкова широко приложение, ако с тяхна помощ се обработваха само числови данни. В ежедневните си дейности човек най-често си служи с текстове. Компютрите са незаменими помощници в този вид дейност, особено когато се налага обработка на големи по обем текстове.  Например при търсене на литературни източници в електронни библиотечни каталози или търсене на думи в електронни речници, при превод на текстове (романи, научни издания, новини) от един естествен език на други др.

Тип знаков низ
Низът е подредена съвкупност от краен брой знакове.
Броят на елементите на даден низ се нарича дължина на низа. Важно свойство на низовете е, че броят на знаковете, т.е. дължината на низа, може да се променя  по време на обработката на структурата в програмата.
Основните операции за работа със знакови низове са конкатенация (слепване), сравнение, намиране на подниз, вмъкване на низ в друг, изтриване на подниз, намиране на дължината на низ, преобразуване на елементите (знаците) на низа и анализ на знаците.
а) конкатенация – операция между два знакови низа (отбелязва се с +), в резултат на която се получава нов низ, съдържащ елементите на първия, следвани от елементите на втория.
б) сравнение – сревнението се извършва на лексико-графичен принцип. То се извършва знак по знак, като се започне от първите. Ако съответните знаци не са равни, за по-малък се взема този с по-малък код. В случай на съвпадение, се преминава на следващия. Ако при това елементите на един низ се изчерпят, той е подниз на другия и е по-малък.
в) операции за промяна на съдържанието на низ – съдържанието на низ може да се промени с вмъкване на низ или изтриване на подниз.

Особености на представянето на знаковите низове в Java
Знаковите низове в Java се представят с обекти. Съществуват два вида знакови низа – класовете String и StringBuffer. Първият се използва за константни знакови низове и веднъж създадени, те не могат да се променят. Вторият осигурява възможност за работа със знакови низове, променящи стойността и дължината си по време на изпълнение на програмата.
Всички обекти в Java трябва да се създават явно с помощта на оператора new. За създаване на два типа обекти, обаче има особен синтаксис. Единият бе разгледан в тема 13 – това е масивът. Другият е знаковият низ String. Когато в програма се срещне серия от знаци – текст, заградени в кавички, компилаторът създава автоматично обект от тип String и го инициализира с текста. Последното е еквивалентно на създаване на обект с new.

Пр. 1:
“Пловдив” // е еквивалентно на
new String(“Пловдив”);


Операторът “+” предизвиква конкатенация на знакови низове, когато такива се явяват левият и десният операнд. Ако единият операнд на оператора “+” е низ, то другият автоматично се преобразува в знаков низ и тогава се прави сливането. Вградените типове данни в Java автоматично се преобразуват в низове, докато за обектите това е невъзможно. Във всеки клас е реализиран методът toString(), който се използва при необходимост за преобразуване на обекта в знаков низ.
 
Знаков низ с фиксирана дължина – клас String
След като се създаде един обект от тип String той неможе да се променя. Той представлява икономично представяне на знаков низ с фиксирана дължина.
Типът String е последен (final) и не може да се препокрива. Методите му позволяват обработка на отделни знаци, сравнение, търсене, извличане на подниз, създаване на копие и други операции, извършвани без модификация на оригинала.

Конструктори
Типът поддържа множество конструктори, позволяващи създаването на знаков низ от друг обект от тип String и StringBuffer или от масив от знаци.
Конструктор    Създава обект от:
CODE
1
2
3
4
public String(String value)    друг обект от клас
public String(StringBuffer buffer)    обект от клас
public String(char[] value)    масив от знаци
р
ublic String(char[] value, int offset, int count)    от област в масив от знаци

Общи методи
• public String toString(); //връща като резултат самия //обект
• public char[] toCharArray(); //връща масив от знаци, //съотвестващи на знаците от обекта
• public int length(); //връща дължината на знаковия низ // т.е. броя знаци
• public char charAt(int index); // връща знак, разположен // на позиция index

Методи за сравняване
CODE
1
2
3
public boolean equals(Object anObject); //връща true, ако //обектът е знаков низ със същите знаци
public boolean equalsIgnoreCase(String anString); //връща true, ако двата низа са еднакви, без отчитане //на разликата в големи и малки букви
public int compareTo(String anString); //лексико-графично сравняване на двата низа, като ако са //еднакви връща 0, ако се различават връща разликата // между първите два различни знака

Методи за намиране на позиция на данни в знаков низ:
Следните методи връщат първата позиция на срещане на зададения знак или знаков низ, като се започне търсене от началото на низа. Ако не се срещне, методите връщат минус 1. когато се използва с допълнителен параметър fromIndex, търсенето започва не отначало, а от зададената позиция:
CODE
1
2
3
4
5
6
•    public int indexOf(int ch); //търси знак от началото
•   
public int indexOf(int ch, int fromIndex); // търси знак от //зададена позиция
•   
public int indexOf(String str); //търси знаков низ от
//началото
•   
public int indexOf(String str, int fromIndex);
//търси знаков низ от зададена позиция

Следните методи връщат първата позиция на срещане на зададения знак или знаков низ като се започне търсене от края към началото на низа. Ако не се срещне, методите връщат минус единица (-1). Когато се използва с допълнителен параметър fromIndex, търсенето започва не от края, а от зададената позиция:
CODE
1
2
3
4
•    public int lastIndexOf(int ch); // търси знак от края
•   
public int lastIndexOf(int ch, int fromIndex); // търси знак //от зададена позиция
•   
public int lastIndexOf(String str); //търси знако низ от //края
•   
public int lastIndexOf(String strint fromIndex); //търси // знаков низ от зададена позиция

1.    Обект
CODE
1
2
3
4
5
•    public String substring(int beginIndex);//създаване на //обект, който е подниз
•   
public String substring(int bIndex,int eIndex); //създаване на обект, подниз на обекта със зададени //начална и крайна позиция
•   
public String concat(String str); //създаване на обект, // който е конкатенация на два обекта
•   
public String toLowerCase();//създаване на нов обект // от съответстващите малки букви на обекта
•   
public String toUpperCase();//създаване на нов обект // от съответстващите големи букви на обекта

2.    Други данни
CODE
1
2
3
4
5
6
7
8
9
•    public static String valueOf(Object obj); //от произволен  обект
•   
public static String valueOf(char[] data); //от масив от  знаци
•   
public static String valueOf(char[] data, int offset, int count); // от област в масив от знаци
•   
public static String valueOf(boolean b); //създава обект с ”true” или “false
•   
public static String valueOf(char c); //знаков низ от //един  знак
•   
public static String valueOf(int i); //знаково(текстово) // представяне на цяло число
•   
public static String valueOf(long l); //знаково //(текстово) представяне на цяло число
•   
public static String valueOf(float f); //знаково //(текстово) представяне на реално число
•   
public static String valueOf(double d); //знаково // (текстово) представяне на реално число

Извикване на метод
Знаковите низови константи се представят с обекти. Поради това е възможно директното прилагане върху тях на методи и получаване на техния резултат. Обикновено това се използва за сравняване:

Пр. 2
CODE
1
2
3
4
5
6
public int compare(String x) {
   
if (add”.equals(x)) {
        …
   
else if (mov”.equals(x)) {
        …
}

Изразът “add”.equals(x)) е еквивалентен на x.equals(“add”).

Знаков низ с променлива дължина – клас StringBuffer
Обектите от тип StringBuffer са като обектите от тип String, но могат да бъдат изменяни. Промяната може да бъде както в съдържанието на низа, така и в неговата дължина. Този тип се нарича знаков низ с променлива дължина. Неговото представяне заема повече ресурси в сравнение с типа String.
Методите на тип StringBuffer позволяват добавяне и вмъкване на знаци в него, както и промяна на дължината на буфера. StringBuffer се характеризира с две величини – дължина на буфера и дължина на низа.

Конструктори
Съществуват три конструктора - за създаване на празен буфер, за създаване на буфер със зададена дължина и за създаване на буфер от знаков низ с фиксирана дължина:
CODE
1
2
3
•    public StringBuffer(); //създаване на буфер с празен // низ и дължина 16
•   
public StringBuffer(int length); //създаване на буфер с //празен низ и зададена дължина
•   
public StringBuffer(String str); //създаване на буфер, //съдържащ зададения низ и дължина равна на //дължината на низа плюс 16

Пр. 3

CODE
1
2
3
4
5
6
StringBuffer strEmpty = new StringBuffer();
//празен знаков низ
(с нулева дължина)
StringBuffer strSize = new StringBuffer(7);
//знаков низ с дължина
7
StringBuffer strString = new StringBuffer(“Пловдив”);
//низ Пловдив

Метод за генериране на знаков низ с фиксирана дължина
CODE
1
public String toString();
Създава нов обект знаков низ с фексирана дължина и последващите изменения на низа от буфера не променят създадения знаков низ.

Методи за работа с дължината на низа и големината на буфера
CODE
1
2
3
4
•    public int length(); //връща дължината на низа
•   
public void setLength(int newLength); //променя //дължината на низа с отсичане или добавяне на // знака nullu000
•   
public int capacity(); //връща големината на буфера
•   
public void ensureCapacity(int minimumCapasity); // когато големината на буфера е по-малка от //параметъра, се създава нов вътрешен буфер с по-//голяма големина, равна на по-голямото число //minimumCapasity и удвоената стара големина плюс 2


Методи за работа със знаци на низа
CODE
1
2
3
•    public char charAt(int index); //връща знака на //зададената позиция                                                
•   
public void setCharAt(int index, char ch); //зададеният 
                     
//знак ch се записва на зададената позиция

Метод за добавяне в края на низа
Параметърът на този метод се преобразува до знаков низ (подобно на String.valueOf) и знаците от този низ се добавят в края на низа от обекта StringBuffer. Всички методи връщат самия обект като резултат, което е удобно за създаване на съставни операции.
• public StringBuffer append (Object obj);
• public StringBuffer append (String str);
• public StringBuffer append (char[] str);
• public StringBuffer append (char[] str, int offset, int len);
• public StringBuffer append (boolean b);
• public StringBuffer append (char c);
• public StringBuffer append (int i);
• public StringBuffer append (long l);
• public StringBuffer append (float f);
• public StringBuffer append (double d);

Реализация на конкатенацията (добавянето, слепването)
Този тип се използва за реализация на конкатенацията при създаване на нов знаков низ.

Пр. 4
CODE
1
2
3
4
5
6
String a = “Стара”;
String b = “Загора”;
//изразът
a+” ”+b
//е еквивалентен на израза
new StringBuffer().append(a).append(“ ”).append(b).toString()

Метод за вмъкване на определена позиция в низа
Параметърът на този метод се преобразува до знаков низ (подобно на String.valueOf) и знаците от този низ се вмъкват в зададената позиция в SringBuffer. Всички методи връщат самия обект като резултат, което е удобно за създаване на съставни операции.
CODE
1
2
3
4
5
6
7
8
9
•    public StringBuffer insert(int offset, Object obj);
•   
public StringBuffer insert(int offset, String str);
•   
public StringBuffer insert(int offset, char[] str);
•   
public StringBuffer insert(int offset, boolean b);
•   
public StringBuffer insert(int offset, char c);
•   
public StringBuffer insert(int offset, int i);
•   
public StringBuffer insert(int offset, long l);
•   
public StringBuffer insert(int offset, float f);
•   
public StringBuffer insert(int offset, double d);

Пр. 5
CODE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
StringBuffer sbExample;

// следните две операции са еквивалентни
sbExample.append(data)
sbExample.insert(sbExample.length().data)

Метод за “огледално” обръщане на знаковия низ
public StringBuffer reverse();
Огледалният знаков низ на един низ съдържа знаците на оригинала в обратен ред. Например, оригинал “Пловдив” има огледален низ “видволП”.
Пр.
6
StringBuffer x = new StringBuffer(“СтараЗагора”);
StringBuffer у = new StringBuffer(“Пловдив”);

//вмъкване на знак в знаков низ
x.insert(5, ‘ ’); //х е “Стара Загора”
//вмъкване на един знаков низ в друг
y.insert(4, “ - ”); //у е “Плов - див”
//добавяне към знаков низ
x.append(“, Хасковска област”); //х е“Стара Загора, // Хасковска област”

//промяна на дължината на буфера
y.setLength(20); // у има дължина 20

// дължина и капацитет
int k = y.length(); //обикновено буферът е с 16 байта по-дълъг
int m = y.capacity(); //от инициализиращият го знаков низ

Въвеждане на знаков низ от клавиатурата
В показания по-долу клас readString се извършва въвеждане на знаков низ от клавиатурата до натискане на клавиша Enter, при което знаците последователно се записват в обект от тип StringBuffer. Cлед това той се преобразува до знаков низ от тип String.
CODE
1
2
3
4
5
6
7
8
9
10
import java.io.*;
class readString {
       
public static String read() {
           
StringBuffer sb = new StringBuffer(0);
           
char c;
           
while((c = (char) Sistem.in.read()) != 10)
               
sb.append(c);
           
return sb.toString();
       
}
}

Изключителни ситуации
При използване на методите на обектите от тип знаков низ е възможно да възникнат изключителни ситуации. Необходимо е програмистите да осигурят обработката на тези ситуации:
1.    IndexOutOfBoundsException – при опит да се прочете (запише) знак на позиция, която не съществува т.е. тази позиция е по-голяма от дължината на низа или е зададено отрицателно число.
2.    NegativeArraySizeException – при опит да се създаде буфер с отрицателна големина.
3.    NullPointerException – при опит да се промени или използва неинициализиран обект.

 



   


Ключови думи: javascript програмиране code код script алгоритъм


Още уроци от тази рубрика


 
  • Подобни теми от myLinks
 

 1 посетител чете този урок (0 потребители и 1 гост)  
Активни потребители: ---
   
  

Еmail  
 

Казва се "Изключение" по-скоро от колкото "Изключителна ситуация" 

  SOMNIVM на 18.11.2007 02:33

Статията добра, но има