Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
методичка Java-технологии.doc
Скачиваний:
12
Добавлен:
01.05.2019
Размер:
793.09 Кб
Скачать

Контрольні питання.

  • Назвіть основні керуючі конструкції.

  • У чому основне розходження операторів Break й Continue?

  • Чи можна використати числа, як значення типу Boolean?

  • Що таке інструкція перемикання?

Завдання.

  1. Написати додаток із графічним користувальницьким інтерфейсом, у якому по натисканню на кнопку ілюструється дія операторів циклу for , while , do...while – залежно від того, яка із кнопок JRadioButton натиснута. За допомогою цих циклів повинна обчислюватися площа під кривою, що задає функцією f(x)=a∙ x2+b∙ x+c, при x мінливому від x1 до x2, де величини a,b,c, x1 й x2 повинні вводитися користувачем у відповідних пунктах уведення.

  2. Додати в цей додаток обчислення з речовинним лічильником циклу для якого-небудь із операторів (for , while або do...while) у випадку, коли відзначена відповідна опція за допомогою кнопки JCheckBox. Показати наявність нестійкості при дуже малій зміні вхідних параметрів (який-небудь із величин a,b,c, x1,x2). Пояснити, чому зміна одних параметрів приводить до нестійкості, а інших - ні.

  3. Написати додаток із графічним користувальницьким інтерфейсом, у якому по натисканню на кнопку JButton ілюструється дія операторів переривання continue, break, return, System.exit - залежно від того, яка із кнопок JToggleButton натиснута.

Лабораторна робота № 3.

Тема: Найважливіші об'єктні типи. Робота із графікою, рядками й масивами.

Ціль: Одержання практичних навичок у роботі з масивами й рядками

Мови Java, а також робота з графікой.

Короткі теоретичні відомості.

Робота з рядками:

Об'єкти String створені щоб бути незмінними. Якщо ви ознайомитеся з документацією по класі String, ви побачите що всі методи цього класу, які змінюють об'єкт String насправді лише створюють і повертають абсолютно новий об'єкт String утримуючої зміни. При цьому об'єкт-оригінал String залишається незмінним.

Оскільки об'єкт String незмінний, ви можете багаторазово дублювати посилання на нього. Оскільки він є об'єктом тільки для читання, немає ніякої небезпеки що дії з однієї з посилань приведуть до зміни об'єкта, що відіб'ється на роботі з іншими посиланнями. Так в об'єктах тільки для читання вирішується проблема дублюючих посилань.

Також представляється можливим обробка всіх случаяв, при яких вам необхідно вносити зміни в об'єкт. Із цією метою створюється зовсім новий варіант об'єкта із уже внесеними змінами, як це реалізовано в String. Однак, у деяких випадках це не ефективно. Прикладом є використання оператора '+', перевантаженого для об'єктів String. Термін "перевантажений" означає, що при використанні із класом певного типу оператор виконує специфічні функції. (Оператори '+' й '+=' для String - єдині перевантажені оператори в Java й в Java програміст не має можливості перевантажувати які-небудь інші оператори). Коли '+' використається з об'єктами String, він виконує операцію об'єднання двох і більше об'єктів String:

String s = "abc" + foo + "def" + Integer.toString(47);

Працює це так: в об'єкта String "abc" є метод append(), що створює об'єкт String, що містить "abc", об'єднаний із умістом foo. Новий об'єкт String у свою чергу створює новий об'єкт String, у який додається "def" і так далі.

Це вимагає створення безлічі об'єктів String лише для об'єднання цих нових об'єктів String, і в результаті у вас вийшла б величезна кількість проміжних об'єктів String, що вимагають збору сміття. Рішенням є використання класу-компаньйона, що модифікує, відповідно до розглянутого раніше принципу. Для об'єкта String класом-компаньйоном є StringBuffer, і компілятор автоматично створює StringBuffer для обробки деяких виражень, зокрема при використанні операторів '+' й '+=' стосовно до об'єктів String. От приклад того як це відбувається:

// Демонстрація StringBuffer.

public class ImmutableStrings {

public static void main(String[] args) {

String foo = "foo";

String s = "abc" + foo +

"def" + Integer.toString(47);

System.out.println(s);

// "Рівність" з використанням StringBuffer:

StringBuffer sb =

new StringBuffer("abc"); // Створює String!

sb.append(foo);

sb.append("def"); // Створює String!

sb.append(Integer.toString(47));

System.out.println(sb);

}

}

При створенні рядка String s компілятор створює грубу копію наступного коду, що використає sb: створюється StringBuffer і використається append() для додавання нових символів безпосередньо в об'єкт StringBuffer (це краще чим щораз створювати нові копії). При тім що це більш ефективно, слід зазначити, що щораз при створенні рядків ув'язнених у лапки, таких як "abc" або "def", компілятор перетворює їх в об'єкти String. Тому насправді створюється більше об'єктів чим вам могло здатися, незважаючи на ефективність StringBuffer.

У таблице 16 представлений огляд методів для класу String. Тут розглянуті не всі методи, а тільки найбільш важливі, що мають відношення до обговорюваної теми.

Таблиця 16.

Метод

Параметри, Перевантаження

Застосування

Constructor

Перевантажені: значення за замовчуванням, String, StringBuffer, масиви char, масиви byte.

Створює об'єкти String.

length( )

Кількість символів в String.

charAt()

int індекс

Повертає символ із зазначеним індексом осередку String.

getChars( ), getBytes( )

Початковий і кінцевий осередки, які будуть скопійований й осередок у зовнішнього масиву, у яку буде зроблене копіювання.

Копіює char або byte у зовнішній масив.

toCharArray( )

Створює масив char[], що зберігає символи з String.

equals( ), equals-IgnoreCase( )

String з якої проводиться порівняння.

Перевірка на рівність умісту двох Strings.

compareTo( )

String з якої проводиться порівняння.

Результат негативний, нуль або позитивний, на підставі лексиграфического впорядкування String і параметра. Заголовні й прописні символи не рівні!

regionMatches( )

Зсув у поточної String, інший String і зсув і довжина фрагмента для порівняння. Перевантаження додає "ігнорувати регістр символів."

Результат boolean, що свідчить про збіг фрагментів.

startsWith( )

String, що може починати поточний String. Перевантаження додає параметр для вказівки зсуву.

Результат boolean свідчить про те, чи починається String з переданої як параметр рядка.

endsWith( )

String, що може завершувати поточний String.

Результат boolean свідчить про те, чи завершується String переданої як параметр рядком.

indexOf( ), lastIndexOf( )

Перевантажені: char, char й індекс початку, String, String й індекс початку.

Повертає -1 якщо аргумент не знайдений у даному String, інакше повертається індекс початку знайденого фрагмента. lastIndexOf( ) здійснює пошук починаючи з кінця рядка.

substring( )

Перевантажений: Індекс початку, індекс початку, і індекс кінця.

Повертає новий об'єкт String, що містить зазначений набір символів.

concat( )

String для об'єднання

Повертає новий об'єкт String, содерщащий символи оригінального об'єкта String і розташовані слідом за ними символи передані як параметр.

replace( )

Старий символ використовуваний для пошуку, новий символ використовуваний для заміни.

Повертає новий об'єкт String з результатами проведеної заміни. Якщо шуканий символ не знайдений, використається старий String.

toLowerCase( ) toUpperCase( )

Повертає новий об'єкт String зі зміненими на відповідний регістр символами. Якщо зміни не потрібно, використається старий String.

trim( )

Повертає новий об'єкт String зі скороченням з обох кінців пробілів до одинарних. Якщо зміни не потрібні, використається старий String.

valueOf( )

Перевантаження: Object, char[], char[] і зсув і покажчик, boolean, char, int, long, float, double.

Повертає String, що містить символьне подання параметра.

intern( )

Створює один і тільки один String з унікальною послідовністю символів.

Тепер розглянемо клас StringBuffer, його методи представлені в таблиці 17:

Таблиця 17.

Метод

Параметри, перевантаження

Застосування

Constructor

Перевантажений: значення за замовчуванням, довжина створюваного буфера, String використовуваний як джерело.

Створює новий об'єкт StringBuffer.

toString( )

Створює String використовуючи поточний StringBuffer.

length( )

Кількість символів в StringBuffer.

capacity( )

Повертає поточний обсяг займаної пам'яті.

ensure- Capacity( )

Integer визначальний бажаний обсяг пам'яті.

StringBuffer резервує як мінімум зазначений обсяг пам'яті.

setLength( )

Integer визначальну нову довжину рядка символів у буфері.

Чи розширює укорочує рядок символів. Якщо рядок розширюється, нові осередки заповнюються нулями.

charAt( )

Integer, що вказує на позицію елемента.

Повертає char для заданої позиції буфера.

setCharAt( )

Integer, що вказує на позицію елемента й нове значення char для цього елемента.

Змінює значення в зазначеній позиції.

getChars( )

Початок і кінець копируемого фрагмента, масив у який виробляється копіювання, індекс у цільовому масиві.

Виконує копіювання символів char у зовнішній масив. На відміну від String тут немає методу getBytes( ).

append( )

Перевантажений: Object, String, char[], char[] зі зсувом і довжиною, boolean, char, int, long, float, double.

Параметр перетвориться в рядок і додається в кінець поточного буфера. При необхідності розмір буфера збільшується.

insert( )

Перевантажений, для всіх першим параметром є зсув з яким виконується вставка: Object, String, char[], boolean, char, int, long, float, double.

Другий параметр перетвориться в рядок й уставляється в поточний буфер починаючи із зазначеного зсуву. При необхідності розмір буфера збільшується.

reverse( )

Порядок проходження символів у буфері міняється на протилежний.

Робота з масивами:

Масив (array) - це впорядкований набір однаково влаштованих осередків, доступ до яких здійснюється по індексі. Наприклад, якщо в масиву ім'я a1, то a1[i] - ім'я осередку цього масиву, що має з індекс i.

В Java масиви є об'єктами, але особливого роду – їхнє оголошення відрізняється від оголошення інших видів об'єктів. Змінна типу масив є посилальної - у ній утримується адреса об'єкта, а не сам об'єкт, як і для всіх інших об'єктних змінних в Java. Як елементи (осередків) масиву можуть виступати значення як примітивних типів, так і посилальних типів, у тому числі - змінні типу масив.

Тип осередку масиву називається базовим типом для масиву.

Для завдання масиву, на відміну від об'єктів інших типів, не потрібно попередньо задавати клас, і мати спеціальне ім'я для даного об'єктного типу. Замість імені класу при оголошенні змінної використається ім'я базового типу, після якого йдуть порожні квадратні дужки.

Наприклад, оголошення

int[] a1;

задає змінну a1 типу масив. При цьому розмір масиву (число осередків у ньому) заздалегідь не задається й не є частиною типу.

Для того, щоб створити об'єкт типу масив, варто скористатися зарезервованим словом new, після чого вказати ім'я базового типу, а за ним у квадратних дужках число осередків у створюваному масиві:

a1=new int[10];

Можна сполучити оголошення типу змінної й створення масиву :

int[] a1=new int[10];

Після створення масиви Java завжди инициализированы - в осередках утримуються нулі. Тому якщо базовий тип масиву примітивний, елементи масиву будуть нулями відповідного типу. А якщо базовий тип посилальний - в осередках будуть значення null.

Довжина масиву зберігається в поле length, що доступно тільки по читанню - змінювати його шляхом присвоювання нового значення не можна.

Приклад роботи з масивом:

int[] a=new int[100];

for(int i=0;i<a.length;i++){

a[i]=i+1;

};

Якщо в нас є змінна типу масив, і їй зіставлений масив заданої довжини, у будь-який момент цієї змінної можна зіставити новий масив. Наприклад,

a1=new int[20];

При цьому колишній масив^-масив-об'єкт-масив, що перебуває в динамічній області пам'яті, буде загублений і перетвориться в сміття.

Змінні типу масив можна привласнювати один одному. Присвоювання змінних типу масив приводить до того, що імена змінних стають синонімами того самого масиву - копіюється адреса масиву. А зовсім не приводить до копіювання елементів з одного масиву в іншій, як це відбувається в деяких інших мовах програмування.

Двовимірний масив являє собою масив осередків, кожна з яких має тип “одномірний масив”. Відповідним чином він і задається. Наприклад, завдання двовимірного масиву цілих чисел буде виглядати так:

int[][] a=new int[10][20];

Буде заданий осередок типу “двовимірний масив”, а також створений і призначений цієї посилальної змінної масив, що має по першому індексі 10 елементів, а по другому 20. Тобто ми маємо 10 осередків типу “одномірний масив”, кожна з яких посилається на масив з 20 цілих чисел. При цьому базовим типом для осередків по першому індексі є int[], а для осередків по другому індексі int.

Розглянемо роботу із двовимірними масивами на прикладі заповнення двовимірного масиву випадковими числами:

int m=10;//10 рядків

int n=20;//20 стовпців

int[][] a=new int[m][n];

for(int i=0;i<m;i++){ //цикл по рядках

for(int j=0;j<n;j++){ //цикл по стовпцях

a[i][j]=(int)(100*Math.random());

System.out.print(a[i][j]+" ");

};

System.out.println();//переклад на новий рядок після виводу рядка матриці

};

Після створення масиву потрібно його инициализировать - записати потрібні значення в осередки. Дотепер ми робили це шляхом завдання значень у циклі по деякій формулі, однак часто потрібно задати конкретні значення. Дуже зручний наступний варіант синтаксису:

int[] a=new int[] {2,0,0,6};

При ініціалізації двовимірних і багатомірних масивів використають вкладені масиви, що задають за допомогою фігурних дужок. Наприклад, фрагмент коду

int[][] b= new int[][]

{

{2,0,0,0}, //це b[0]

{2,0,0,1}, //це b[1]

{2,0,0,2}, //це b[2]

{1,0,0,0}, //це b[3]

{2,0,0,0}, //це b[4]

{3,0,0,0}, //це b[5]

};

З об'єктів-масивів можна викликати метод clone(), що дозволяє створювати копію (клон) масиву:

a=new int[] {2,0,0,6};

int[] a1=a.clone();

Копіювання масивів можна здійснювати в циклі, але набагато швидше використати метод System.arraycopy.

int[] b=new int[a.length+10];

System.arraycopy(a,index1a,b, index1b,count);

Швидке заповнення масиву однаковими значеннями може здійснюватися методом Arrays.fill(масив, значення). Клас Arrays розташований у пакеті java.util. Заелементне порівняння масиву варто виконувати за допомогою методу Arrays.equals(a,a1). Сортування (упорядкування за значеннями) масиву a виробляються методами Arrays.sort(a) і Arrays.sort(a,index1,index2). Перший з них упорядковує в порядку зростання весь масив, другий – частина елементів (від індексу index1 до індексу index2).

Робота із графікою:

Вивід графіки здійснюється за допомогою об'єктів типу java.awt.Graphics. Для них визначений ряд методів, описаних у таблиці 18.

Мається на увазі, що w- ширина області або фігури, h- висота; x,y- координати лівого верхнього кута області. Для фігури x,y- координати лівого верхнього кута прямокутника, у який уписана фігура.

Таблиця 18.

Параметри виводу графіки

Color getColor()

Довідатися поточні кольори малювання.

setColor(Color c)

Задати поточні кольори малювання.

Font getFont()

Довідатися поточний фонт для виводу текстової інформації.

setFont(Font f)

Установити поточний фонт для виводу текстової інформації. Екземпляр фонта створюється за допомогою конструктора Font(“имяФонта”,стильФонта,размерФонта)

FontMetrics getFontMetrics()

Довідатися параметри поточного фонта

FontMetrics getFontMetrics(Font f)

Довідатися параметри для довільного фонта f

setXORMode(Color c1)

Установка режиму малювання XOR (“ щовиключає або”) для кольорів c1. При цьому вивід крапки кольори color дає кольори, дорівнює побітовому значенню color ^ c1 (тобто color XOR c1) для числового RGB-кодування кольорів. Повторний вивід графічного зображення на те ж місце приводить до відновлення первісного зображення в області виводу.

setPaintMode()

Повернення у звичайний режим з режиму малювання XOR.

translate(x0,y0)

Зрушення початку координат графічного контексту в крапку x0,y0. Всі координати, зазначені при виводі графічних примітивів, відраховують щодо цього початку координат.

Малювання контурних фігур

drawLine(x1,y1,x2,y2)

Вивід лінії із крапки з координатами x1,y1 у крапку x2,y2

drawRect(x,y,w,h)

Вивід прямокутника.

drawRoundRect(x,y,w,h,arcWidth,arcHeight)

Вивід округленого прямокутника.

draw3DRect(x,y,w,h,isRaised)

Вивід “об'ємного” прямокутника. Якщо змінна isRaised ==true, він “опуклий” (raised), інакше - “втиснений”.

drawPolygon(Polygon p);

drawPolygon(int[] xPoints, int[] yPoints, int nPoints)

Вивід багатокутника по масиві крапок, nPoints – число крапок.

drawPolyline(int[] xPoints,int[] yPoints, int nPoints)

Вивід незамкнутої ламаної лінії по масиві крапок, nPoints – число крапок.

drawOval(x,y,w,h)

Вивід еліпса.

drawArc(x,y,w,h,startAngle,arcAngle)

Вивід дуги еліпса. Початковий кут startAngle і кут, що задає кутовий розмір дуги arcAngle, задаються в градусах.

drawImage(Image img,int x,int y, ImageObserver observer) і інші перевантажені варіанти методу

Вивід зображення.

Малювання заповнених фігур

clearRect(x,y,w,h)

Очищення прямокутника (заповнення поточними кольорами)

fillRect(x,y,w,h)

Вивід прямокутника, заповненого поточними кольорами.

fillRoundRect(x,y,w,h,arcWidth,arcHeight)

Вивід округленого прямокутника, заповненого поточними кольорами.

fill3DRect(x,y,w,h, isRaised)

Вивід “об'ємного” прямокутника, заповненого поточними кольорами. Якщо змінна isRaised ==true, він “опуклий” (raised), інакше - “втиснений”.

fillPolygon(Polygon p)

fillPolygon(int[] xPoints, int[] yPoints, int nPoints)

Вивід багатокутника, заповненого поточними кольорами.

fillOval(x,y,w,h)

Вивід еліпса, заповненого поточними кольорами.

fillArc(x,y,w,h,startAngle,arcAngle)

Вивід сектора еліпса, заповненої поточними кольорами. Заповнюється сектор, обмежений відрізками із центра еліпса в кінці дуги, і самою дугою.

copyArea(x,y,w,h,dx,dy)

Копіювання області на нове місце, зрушене від старого на dx,dy

Вивід текстової інформації

drawString(s,x,y)

Вивід рядка s

drawChars(char[] data,int offset,int length,int x,int y)

Вивід масиву символів

drawBytes(byte[] data,int offset,int length,int x,int y)

Вивід символів, представлених як послідовність байт

Керування областю виводу

setClip(x,y,w,h)

setClip(Shape clip)

Установка нових границь області виводу. Поза цією областю при виводі графічних примітивів вони усікаються (не виводяться).

clipRect(x,y,w,h)

Звуження області виводу.

Rectangle getClipBounds()

Rectangle getClipBounds(Rectangle r)

Повертає параметри прямокутника, у який уписана область виводу.

Graphics create()

g1=g.create()- створення копії графічного об'єкта g

dispose()

Деструктор - знищення графічного об'єкта з одночасним вивільненням ресурсів (без очікування, коли це зробить збирач сміття).

Приклад методу, що працює із графікою.

java.awt.Graphics g,g1;

private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {

java.awt.Graphics g,g1;

g=jPanel1.getGraphics();

int x1=20,x2=120,y1=20,y2=120;

int x3=20,y3=20,w3=60,h3=80;

int x4=30,y4=60,w4=30,h4=40;

int x0=10,y0=10,w0=10,h0=10;

int w1=80,h1=120;

g.setClip(0,0,60,80);//границі області виводу

g.drawLine(x1,y1,x2,y2);//лінія

g.drawOval(x3,y3,w3,h3);//еліпс

g.clipRect(x4,y4,20,20);//звуження області виводу

g.clearRect(x4,y4,w4,h4);//очищення прямокутника

g.setClip(0,0,200,280); //нові границі області виводу

g.copyArea(x1,y1,w1,h1,60,0);

g.draw3DRect(10,20,w1,h1,false);

g.drawPolygon(new java.awt.Polygon(new int[]{10,10,20,40},

new int[]{10,20,30,60},4) );

}

У випадку спроби такого використання виникає проблема: при перемальовуванні графічного контексту все виведене зображення зникає. А перемальовування викликається автоматично при зміні розміру вікна додатка, а також його відновленні після мінімізації або перекриття іншим вікном.

Для того щоб результати виводу не пропадали, у класі додатка потрібно перевизначити метод paint, викликуваний при отрисовке. Код цього методу може виглядати так:

public void paint(java.awt.Graphics g){

super.paint(g);

g=jPanel1.getGraphics();

... - команди графічного виводу

}

Правда, при зміні розміру вікна додатка цей код не спрацює, і для панелі треба буде призначити оброблювач

private void jPanel1ComponentResized (java.awt.event.ComponentEvent evt) {

... - команди графічного виводу

}

У випадку отрисовки з оброблювача якої-небудь події зміни графічного контексту не відбувається до закінчення оброблювача. Це принципова особливість роботи з ідеології оброблювачів подій - поки не скінчиться один оброблювач, що випливає не починається. Для дострокової отрисовки безпосередньо під час виконання оброблювача події служить виклик методу update(Graphics g). Приклад:

for(int i=0;i<=100;i++){

FiguresUtil.moveFigureBy(figure,dx,dy);

update(g);

};

При роботі зі статичними зображеннями викладених алгоритмів цілком достатньо. Однак при використанні елементів, що рухаються, у багатьох графічних системах виникає мельтешение, пов'язане з постійними перемальовуваннями. У цих випадках звичайно застосовують ідеологію подвійний буферизации: отрисовку елементів по невидимому буферному зображенню, а потім показ цього зображення в якості видимого. А те зображення, що було видиме, при цьому стає невидимим буфером.