Главная Случайная страница


Категории:

ДомЗдоровьеЗоологияИнформатикаИскусствоИскусствоКомпьютерыКулинарияМаркетингМатематикаМедицинаМенеджментОбразованиеПедагогикаПитомцыПрограммированиеПроизводствоПромышленностьПсихологияРазноеРелигияСоциологияСпортСтатистикаТранспортФизикаФилософияФинансыХимияХоббиЭкологияЭкономикаЭлектроника






Использование атрибутов доступа

Рассмотрим классы в том же пакете. Внутри данного пакета любой класс имеет прямой доступ к имени любого другого класса, например для объявления переменных или типов параметров методов. Но переменные и методы, которые являются членами этого другого класса, не обязательно доступны. Их доступность управляется атрибутами доступа. Существуют четыре возможности при определении атрибута доступа для члена класса (включая неопределение ничего), и все они дают различные результаты. В табл. 1.1 показано, как атрибуты доступа, заданные для члена класса, определяют части среды Java, откуда к ним можно получить доступ.

Таблица 1.1

Атрибуты доступа к элементам класса

 

Атрибут Разрешенный доступ
Отсутствие атрибута доступа Из любого класса в том же пакете
public Из любого класса откуда угодно
private Никакого доступа вне класса
protected Из любого класса в том же пакете и из любого подкласса где угодно

 

На рис. 1.1 и 1.2 приведена графическая интерпретация табл. 1.1.

 

Рис. 1.1. Атрибуты доступа в рамках пакета

 

Рис. 1.2. Атрибуты доступа для нескольких пакетов

 

Статические переменные и методы

Объявляются при помощи ключевого слова static.

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

Методы, объявленные как static, могут работать только с переменными и методами, объявленными как static. Такие методы можно вызвать даже если объект не создан. В статических методах нельзя ссылаться на this и на super() (конструктор базового класса).

Метод main() объявляется как static, потому что должен вызваться прежде, чем будут созданы какие-либо объекты.

Cтатические переменные создаются один раз, как глобальные, то есть нет дублирования, как при нестатических переменных. Статические переменные можно вызывать, не создав объекта класса.

 

Пример 1.7

class Myclass

{

static boolean ab_switch = true;

static int a = 1;

static int b;

public static void f1(int x)

{

ab_switch =! ab_switch;

System.out.println("x= "+x);

System.out.println("a= "+a);

}

static{ //статический блок инициализации

b=a*4;}

public static void main(String args[])

{ f1(25);

}

}

 

Ab_switch – изменяемая переменная, и вызов метода f1 из каждого экземпляра объекта или любого метода меняет состояние switch для всех экземпляров объектов, в которых эта переменная определена.

Последовательность выполнения операторов:

a=1;

b=4;

Вызов метода main( ) и, следовательно, метода f1(25).

 

Результат выполнения программы:

x= 25

a= 1

 

Статические переменные объявляют, когда нужна общая переменная на все экземпляры класса. Это может быть, например, счетчик количества экземпляров класса.

 

Пример 1.8

class someclass{

static public int number; //счетчик

public someclass(){

number++;

}

}

class Test{

public static void main(String args[]){

someclass z1 = new someclass();

someclass z2 = new someclass();

System.out.println(someclass. number);

}

}

 

Результат выполнения программы: 2

 

main() – главная функция, с её начинается выполнение любой программы. Она вызывается кодом, который находится вне программы (поэтому main( ) объявляется как public).

 

Потоки

Java-программы выполняют ввод/вывод через потоки. Поток является абстракцией, которая или производит, или потребляет информацию. Поток связывается с физическим устройством с помощью системы ввода/вывода Java (Java I/O system). Все потоки ведут себя одинаковым образом, хотя фактические физические устройства, с которыми они связаны, могут сильно различаться. Таким образом, одни и те же классы и методы ввода/вывода можно применять к устройствам любого типа. Это означает, что поток ввода может извлекать много различных видов входных данных: из дискового файла, с клавиатуры или сетевого разъема. Аналогично, поток вывода может обратиться к консоли, дисковому файлу или сетевому соединению (сокету).

Благодаря потокам, ваша программа выполняет ввод/вывод, не понимая различий между клавиатурой и сетью. Java реализует потоки с помощью иерархии классов, определенных в пакете java.io.

Байтовые и символьные потоки

Java 2 определяет два типа потоков: байтовый и символьный. Байтовые потоки предоставляют удобные средства для обработки ввода и вывода байт. Байтовые потоки используются, например, при чтении или записи данных в двоичном коде. Символьные потоки предоставляют удобные средства для обработки ввода и вывода символов. Они используют Unicode и поэтому могут быть интернационализированы. Кроме того, в некоторых случаях символьные потоки более эффективны, чем байтовые. Первоначальная версия Java (Java 1.0) не включала символьные потоки, и таким образом, весь ввод/вывод был байтовым. Символьные потоки были добавлены в Java 1.1, а некоторые байтовые классы и методы были исключены.

 

Классы байтовых потоков

Байтовые потоки определяются в двух иерархиях классов. Наверху этой иерархии — два абстрактных класса: InputStream и OutputStream. Каждый из этих абстрактных классов имеет несколько конкретных подклассов (табл. 1.2), которые обрабатывают различия между разными устройствами, такими, как дисковые файлы, сетевые соединения и даже буферы памяти.

Абстрактные классы InputStream и OutputStream определяют несколько ключевых методов, которые реализуются другими поточными классами. Два наиболее важных— read() и write(), которые соответственно читают и записывают байты данных. Оба метода объявлены как абстрактные внутри
классов InputStream и OutputStream и переопределяются производными поточными классами.

Таблица 1.2

Классы байтовых потоков

 

Поточный класс Назначение
InputStream OutputStream Абстрактные классы, которые описывают поточный ввод и вывод
BufferedInputStream BufferedOutputStream Буферизированный поток ввода и вывода
ByteArrayInputStream ByteArrayOutputStream Поток ввода, который читает из байт-массива Поток вывода, который записывает в байт-массив
FileInputStream FileOutputStream Поток ввода, который читает из файла Поток вывода, который записывает в файл
RandomAccessFile Поддерживает ввод/вывод файла произвольного доступа

 

Классы символьных потоков

Символьные потоки определены в двух иерархиях классов. Наверху этой иерархии два абстрактных класса: Reader и Writer. Они обрабатывают потоки символов Unicode. В Java существуют несколько конкретных подклассов каждого из них. Классы Reader и Writer – наследники InputStream и OutputStream. Если с их помощью записывать или считывать текст, то сначала необходимо сопоставить каждому символу его числовой код. Такое соответствие называется кодировкой. Классы символьных потоков показаны в таблице 1.3.

Абстрактные классы Reader и Writer определяют несколько ключевых методов, которые реализуются другими поточными классами. Два самых важных метода — read() и write(), которые читают и записывают символы данных, соответственно. Они переопределяются производными поточными классами.

 

Таблица 1.3

Классы символьных потоков

 

Символьный класс Назначение
Reader Writer Абстрактные классы символьного потока ввода и вывода
BufferedReader BufferedWriter Буферизированные символьные потоки ввода и вывода
FileReader FileWriter Поток ввода, который читает поток символов из файла; Выходной поток, который записывает символы в файл
StringReader StringWriter Поток ввода, который читает из строки; Поток вывода, который записывает в строку
PrintWriter Поток вывода, который поддерживает методы print() и println()

 

Известно, что Java использует кодировку Unicode, в которой символы представляются двухбайтным кодом. Байтовые потоки зачастую работают с текстом упрощенно – они просто отбрасывают старший байт каждого символа. В реальных же приложениях они могут использовать различные кодировки (даже для русского языка их существует несколько). Поэтому в версии Java 1.1 появился дополнительный набор классов, основывающийся на типах Reader и Writer.

Эта иерархия очень схожа с аналогичной для байтовых потоков InputStream и OutputStream. Главное отличие между ними – Reader и Writer работают с потоком символов (char). Только чтение массива символов в Reader описывается методом read(char[]), а запись в Writer – write(char[]).

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

Таблица 1.4

Соответствие классов для байтовых и символьных потоков

 

Байтовый поток Символьный поток
InputStream Reader
OutputStream Writer
ByteArrayInputStream CharArrayReader
ByteArrayOutputStream CharArrayWriter
Нет аналога InputStreamReader
Нет аналога OutputStreamWriter
FileInputStream FileReader
FileOutputStream FileWriter
FilterInputStream FilterReader
FilterOutputStream FilterWriter
BufferedInputStream BufferedReader
BufferedOutputStream BufferedWriter
PrintStream PrintWriter
DataInputStream Нет аналога
DataOutputStream Нет аналога
ObjectInputStream Нет аналога
ObjectOutputStream Нет аналога
PipedInputStream PipedReader
PipedOutputStream PipedWriter
StringBufferInputStream StringReader
Нет аналога StringWriter
LineNumberInputStream LineNumberReader
PushBackInputStream PushBackReader
SequenceInputStream Нет аналога

 

Как видно из табл. 1.4, различия крайне незначительны и предсказуемы.

Например, конечно же, отсутствует преобразование в символьное представление примитивных типов Java и объектов (DataInput/Output, ObjectInput/Output). Добавлены классы-мосты, преобразующие символьные потоки в байтовые: InputStreamReader и OutputStreamWriter. Именно на их основе реализованы FileReader и FileWriter. Метод available() класса InputStream в классе Reader отсутствует, он заменен методом ready(), возвращающим булевое значение, – готов ли поток к считыванию (то есть будет ли считывание произведено без блокирования).

В остальном же использование символьных потоков идентично работе с байтовыми потоками.

Классы-мосты InputStreamReader и OutputStreamWriter при преобразовании символов также используют некоторую кодировку. Ее можно задать, передав в конструктор в качестве аргумента ее название. Если оно не будет соответствовать никакой из известных кодировок, будет брошено исключение UnsupportedEncodingException. Вот некоторые из корректных значений этого аргумента (чувствительного к регистру!) для распространенных кодировок: "Cp1251", "UTF-8", "8859_1" и т.д.

В следуюшем примере приведена программа, которая демонстрирует read(), читая символы с консоли, пока пользователь не напечатает «q»:

 

Пример 1.9

import java.io.*;

class BRRead {

public static void main(String args [ ]) throws IOException

{

char c;

BufferedReader br = new

BufferedReader(new InputStreamReader(System.in));

System.out.println("Enter symbols or 'q' to exit");

// чтение символов

do {

c= (char)br.read();

System.out.println(c);

}

while(c != 'q');

}

}

 

Результат выполнения программы:

Enter symbols or 'q' to exit

123abcq

а

b

с

q

 

Следующая программа демонстрирует BufferedReader и метод readLine(). Она читает и отображает строки текста, пока не будет введено слово «stop».

 

Пример 1.10

import java.io.*;

class BRReadLines {

public static void main(String args[])throws IOException

{

// создать BufferedReader, используя System.in

BufferedReader br = new BufferedReader(new

InputStreamReader(System.in));

String str;

System.out.println("Enter text");

System.out.println("Enter 'stop' to exit");

do {

str = br.readLine();

System.out.println(str);

} while(!str.equals("stop"));

}

}

 

Программный код для записи символьных данных в файл приведен в следующем примере.

 

Пример 1.11

String fileName = "d:\\file.txt";

//строка, которая будет записана в файл

String data = "Some data to be written and read.\n";

try{

FileWriter fw = new FileWriter(fileName);

BufferedWriter bw = new BufferedWriter(fw);

System.out.println("Write some data to file: " + fileName);

// несколько раз записать строку

for(int i=(int)(Math.random()*10);--i>=0;)

bw.write(data);

bw.close();

// cчитываем результат

FileReader fr = new FileReader(fileName);

BufferedReader br = new BufferedReader(fr);

String s = null;

int count = 0;

System.out.println("Read data from file: " + fileName);

// cчитывать данные, отображая на экран

while((s=br.readLine())!=null)

System.out.println("row " + ++count + " read:" + s);

br.close();

} catch(Exception e) {e.printStackTrace();}

 

Следующий пример демонстрирует извлечение из строки последовательности подстрок, которые разделены простыми пробелами.

 

Пример 1.12

public class ExtractSubstring

{

public static void main(String[] args)

{

String text = "To be or not to be"; //строка для расчленения

int count = 0; //число подстрок

char separator = ' '; //разделитель подстрок

// определить число подстрок

int index = 0;

do {

++count; //увеличить счетчик подстрок

++index; //перейти за последнюю позицию

index = text.indexOf(separator, index);

}

while (index != -1);

//поместить подстроку в массив

String[] subStr = new String[count]; //выделить для подстрок

index = 0; //индекс начала подстроки

int endIndex = 0; //индекс окончания подстроки

for(int i = 0; i < count; i++)

{

endIndex = text.indexOf(separator,index); //найти

//следующий разделитель

if(endIndex == -1) //если он не найден

subStr[i] = text.substring(index); //извлечь до конца

else //иначе

subStr[i] = text.substring(index, endIndex);

//до конечного индекса

index = endIndex + 1; //задать начало для

//следующего цикла

}

//вывести подстроки

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

System.out.println(subStr[i]);

}

}

 

Результат выпонения программы:

To

be

or

not

to

be

 

В следующем примере создается последовательность точек и линии, соединяющие каждую пару последовательных точек, вычисляется общая длина линии. Пример включает три класса: TryPackage, Point, Line.

 

Пример 1.13

Код класса TryPackage

import Geometry.*; // импортировать классы Point и Line

public class TryPackage

{

public static void main(String[] args)

{

double[][] coords = { {1.0, 0.0}, {6.0, 0.0},

{6.0, 10.0},{10.0,10.0},

{10.0, -14.0}, {8.0, -14.0}};

 

//создать массив точек и заполнить его объектами Point

Point[] points = new Point[coords.length];

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

points[i] = new Point(coords[i][0],coords[i][1]);

//создать массив линий и заполнить его с помощью пар

//объектов Point

Line[] lines = new Line[points.length - 1];

double totalLength = 0.0; //сохранить общую длину линии

for(int i = 0; i < points.length - 1; i++)

{

//создать Line

lines[i] = new Line(points[i], points[i+1]);

//добавить ее длину

totalLength += lines[i].length();

System.out.println("\nLine "+(i+1)+' ' +lines[i] +

" Length is " + lines[i].length());

}

//вывести общую длину

System.out.println("\n\nTotal line length = " + totalLength);

}

}

 

Код класса Point

package Geometry;

public class Point

{

//создать точку (Point) по ее координатам

public Point(double xVal, double yVal)

{

x = xVal;

y = yVal;

}

//создать точку (Point) из существующего объекта (Point)

public Point(final Point aPoint)

{

x = aPoint.x;

y = aPoint.y;

}

//переместить точку

public void move(double xDelta, double yDelta)

{

//значения параметров являются приращениями для текущих координат

x += xDelta;

y += yDelta;

}

//вычислить расстояние до другой точки public double distance (final Point aPoint)

{

return Math.sqrt(

(x - aPoint.x)*(x - aPoint.x) +

(y - aPoint.y)*(y - aPoint.y) );

}

//преобразовать точку (Point) в строку

public String toString()

{

return Double.toString(x) + ", " + y; //Как "x, y"

}

//извлечь координату х

public double getX()

{ return x; }

//извлечь координату y

public double getY()

{ return y; }

//задать координату x

public void setX(double inputX)

{ x = inputX; }

//задать координату y

public void setY(double inputY)

{ y = inputY; }

//координаты точки

private double x;

private double y;

}

 

Код класса Line

package Geometry;

public class Line

{

//создать прямую (Line) по двум точкам

public Line(final Point start, final Point end)

{

this.start = new Point(start);

this.end = new Point(end);

}

//создать прямую (Line) из двух пар координат

public Line(double xStart, double yStart, double xEnd, double yEnd)

{

start = new Point(xStart, yStart); //создать начальную точку

end = new Point(xEnd, yEnd); //создать конечную точку

}

//вычислить длину прямой

public double length()

{

return start.distance(end); //использовать метод из класса Point

}

//вернуть точку как пересечение двух прямых

public Point intersects(final Line line1)

{

Point localPoint = new Point(0, 0);

double num =

(this.end.getY() - this.start.getY())*(this.start.getX() - line1.start.getX()) -

(this.end.getX() - this.start.getX())*(this.start.getY() - line1.start.getY());

double denom =

(this.end.getY() - this.start.getY())*(line1.end.getX() - line1.start.getX()) -

(this.end.getX() - this.start.getX())*(line1.end.getY() - line1.start.getY());

localPoint.setX(line1.start.getX() + (line1.end.getX() - line1.start.getX())*num/denom);

localPoint.setY(line1.start.getY() + (line1.end.getY() - line1.start.getY())*num/denom);

return localPoint;

}

//преобразовать прямую (Line) в строку

public String toString() {

return "(" + start+ "):(" + end + ")"; //Как "(start):(end)"

} //т.е."(x1, y1):(x2, y2)"

// Data members

Point start; //начальная точка прямой

Point end; //конечная точка прямой

}

 

Откомпилировав файлы и запустив программу, получим следующий результат работы программы:

Line 1 (1.0, 0.0) : (6.0, 0.0) Length is 5.0

Line 2 (6.0, 0.0) : (6.0, 10.0) Length is 10.0

Line 3 (6.0, 10.0) : (10.0, 10.0) Length is 4.0

Line 4 (10.0, 10.0) : (10.0, -14.0) Length is 24.0

Line 5 (10.0, -14.0) : (8.0, -14.0) Length is 2.0

Total line length = 45.0

 

Задания для самостоятельного выполнения

 

1. Создать массив переменных String и инициализировать массив названиями месяцев от января до декабря. Создать массив, содержащий 12 случайных десятичных значений между 0.0 и 100.0. Вывести название каждого месяца вместе с соответствующим десятичным значением. Вычислить и вывести среднее значение 12 значений.

2. Написать программу, которая задает переменную String, содержащую параграф текста на выбор. Извлечь слова из текста и отсортировать их в алфавитном порядке. Вывести отсортированный список слов.

3. Создать массив из десяти переменных String, каждая из которых содержит произвольную строку – месяц/день/год, например 01/10/06. Проанализировать каждый элемент в массиве и вывести представление даты в форме 10 января 2006.

4. Написать программу для создания случайной последовательности прописных букв, которая не включает гласные буквы.

5. Написать программу для создания случайной последовательности строчных букв, которая не включает гласные буквы.

6. Создать объект типа String и проинициализировать его текстовой строкой. Определить количество гласных, пробелов и общее количество букв.

7. Создать массив объектов типа String и проинициализировать его следующими текстовыми строками: «To be or not to be that is the question», «I am the student of economical department», «My name is John», «Hello world». Воспользоваться методом indexOf(), чтобы определить в массиве подстроки «be», «is»,«am»,«department», «hello». Вывести номер строки и для нее номер указанного элемента.

8. Создать массив объектов типа String и проинициализировать его следующими строками: «To;be:or*not;to:be*that;is:the*question», «I;am:the*student;of:economical*department», «My;name:is*John», «Hello;world». Использовать метод indexOf() совместно с методом substring() для извлечения из исходного массива строк последовательности подстрок, которые разделены символами «;», «:»,«*».

9. Написать программу, с помощью которой создается последовательность точек и линия, соединяющая каждую пару последовательных точек. Затем вычисляется общая длина линии. Найти на этой отрезок минимальной длины.

10. Написать программу для создания прямоугольного массива, содержащего таблицу умножения от 1×1 до 12×12. Вывести таблицу как 13 столбцов с числовыми значениями, выровненными справа в столбцах (рис. 1.3). Первая строка вывода – это заголовки столбцов без заголовка для первого столбца, затем числа от 1 до 12 для остальных столбцов. Первый элемент в каждой из последующих строк является заголовком строки, изменяющимся от 1 до 12.

 

1 2 3 4 5 6 7 8 9 10 11 12

1 1 2 3 4 5 6 7 8 9 10 11 12

2 2 4 6 8 10 12 14 16 18 20 22 24

3 3 6 9 12 15 18 21 24 27 30 33 36

4 4 8 12 16 20 24 28 32 36 40 44 48

5 5 10 15 20 25 30 35 40 45 50 55 60

6 6 12 18 24 30 36 42 48 54 60 66 72

7 7 14 21 28 35 42 49 56 63 70 77 84

8 8 16 24 32 40 48 56 64 72 80 88 96

9 9 18 27 36 45 54 63 72 81 90 99 108

10 10 20 30 40 50 60 70 80 90 100 110 120

11 11 22 33 44 55 66 77 88 99 110 121 132

12 12 24 36 48 60 72 84 96 108 120 132 144

 

Рис. 1.3. Результат вывода программы

 

11. Написать программу, с помощью которой создается бы последовательность точек и линия, соединяющая каждую пару последовательных точек. Затем вычисляется средняя длина линии. Найти на этой линии отрезок максимальной длины.

12. Диаметр Солнца равен приблизительно 865 000 милям, а диаметр Земли – 7600 милям. Вычислить с помощью методов класса Math:

– объем Земли в кубических милях;

– объем Солнца в кубических милях;

– отношение объема Солнца к объему Земли.

Затем вывести эти значения. Считать, что Земля и Солнце являются шарами. Объем шара задается формулой 4пr³/3, где r – радиус шара.

13. Написать программу, которая по трем точкам определит вид треугольника: прямоугольный, равнобедренный, равносторонний или разносторонний.

14. Написать программу, которая в матрице произвольного порядка определит индекс строки с минимальным элементом и индекс столбца с максимальным элементом этой матрицы.

15. Написать программу, которая в матрице произвольного порядка определит отношение среднего значения элементов, расположенных на главной диагонали, к среднему значению элементов, расположенных на побочной диагонали этой матрицы.


ЛАБОРАТОРНАЯ РАБОТА №2

РАБОТА С ФАЙЛАМИ

 

Цель: разработка консольных приложений с возможностью записи и чтения в/из файла.

 

Последнее изменение этой страницы: 2016-08-11

lectmania.ru. Все права принадлежат авторам данных материалов. В случае нарушения авторского права напишите нам сюда...