[Назад]   [Вперед]

Виктор Кон,   vkBook, Java-First

Третий класс

Класс MyPro будем писать в отдельном файле. Он является таким же стандартным классом, как и первые два. Точнее это обязательная часть нашего шаблона. Но в отличие от первых двух классов, которые написаны практически полностью, этот класс можно наращивать бесконечно. Сейчас мы запишем в него только то, что нам нужно. Итак

import java.awt.*;
import java.io.*;

public class MyPro{
 public static String mtit;
 public static int isn;

 public static String readLine(String fn, int n){
  int i; String arg = " "; String ls = null; File fs = new File(fn);
  if( fs.exists() ){
   try{
    BufferedReader ins = new BufferedReader(new FileReader(fs));
    for( i=0; i < n; i++ ){ls = ins.readLine();} ins.close();
   }catch(IOException ex){ex.printStackTrace();}
  } if( ls != null ){arg=ls;}  
  return arg;
 }

 public static String[] split(String ls, char c){
  char[] p = ls.toCharArray(); int i,i1,i2,im,n; im=p.length; n=1;
  for( i=0; i < im; i++ ){if(p[i] == c){n++;}}
  String[] as = new String[n]; n=0; i1=0;
  for( i=0; i < im; i++ ){if(p[i] == c){i2=i-i1; as[n] = new String(p,i1,i2); i1=i+1; n++;}}
  if( i1 < im ){i2=im-i1; as[n] = new String(p,i1,i2);}else{as[n] = null;}
  return as;
 }

 public static Frame parent(){ int i,k,l;
  Frame[] frm = Frame.getFrames(); k=frm.length; l=-1;
  for(i=0; i < k; i++){if(frm[i].getTitle().equals(mtit)){l=i;}} 
  if(l != -1){return frm[l];}else{return frm[0];}
 }
}
Так как этот класс выполняет стандартные функции, то его можно ставить в любую программу без изменений, даже не понимая, что тут написано. Это очень похоже на примитивные языки, в которых можно было использовать чужие библиотеки не разбираясь в их коде и зная только то, что надо подать на вход и получить на выходе. Но так как наша задача научиться программировать, то начнем комментировать.

Первая функция имеет два аргумента: строку fn с именем файла в текущей папке программы (или полного, если в ней указан весь путь к файлу) и номер строки внутри этого файла. Прежде всего формируется объект класса File по имени файла. Логическая функция exists() этого объекта выдает true если файл существует. В этом случае начинаем работать. Строка
BufferedReader ins = new BufferedReader(new FileReader(fs));
объявляет объект ins, способный читать наш файл. Мы заказали процесс двухступенчатого чтения файла. Сначала файл большими кусками (в нашем случае размер куска по умолчанию) считывается из файла в буфер в памяти компьютера, а затем мы уже читаем файл из буфера. Так быстрее и это фактически без вариантов.
for( i=0; i < n; i++ ){ls = ins.readLine();} ins.close();
Нам нужна всего лишь n-ая строка этого файла. Функция readLine() объекта ins читает файл с самого начала строку за строкой. Мы не знаем ни размера строк, ни сколько их вообще в файле. Но на всякий случай считываем в цикле подряд ровно n строк. При этом мы не гарантированы от ошибки, которую сами не обрабатываем. Это конечно плохо, но мы можем делать проверки еще до обращения к нашей процедуре и здесь уже быть уверенными, что n строк у нас есть. Но Java нам не верит и требует обрабатывать наш процесс на возможную ошибку. Это делается конструкцией типа try{...}catch(){...}. Она необходима, потому что в данном случае мы не написали "throws IOException" при объявлении класса. Значит мы обязаны написать указанную конструкцию в тексте, которая означает, что мы конкретно предлагаем свои действия в случае ошибки. В аргумент функции catch поступит объект класса IOException с названием ex и далее мы можем воспользоваться его методами. Но мы как раз использовали стандартный метод, который срабатывает при добавлении текста "throws IOException" в объявление класса. Правда теперь у нас есть возможность в любой момент исправить обработку на более развернутую. Функция ex.printStackTrace(); просто указывает в окне нашего batch файла на место ошибки в коде программы. Это тоже очень полезная информация. Так как указывается конкретная строка файла, то нужен редактор, показывающий положение курсора (хотя бы строку). Ну и полезно закрывать объект ins, отправляя его тем самым в мусор. А сборщик мусора его уберет.

Далее - надо все таки проверить, считана строка или нет. Если она не считана, она будет null, то есть не существует. Так мы ее определили с самого начала. А если считана, то пересылаем в arg. Исходно arg задана как имеющая один пробел. Вот и все.

Вторая функция расщепляет строку по заданному символу. Сначала метод класса String с названием toCharArray() преобразует эту строку в массив символов. Определяя длину этого массива, мы в цикле по элементам сначала определяем сколько раз символ, являющийся вторым аргументом функции, встречается в данном наборе символов. Число строк должно быть на 1 больше, поэтому отсчет идет от 1. Зная число будущих строк, мы определяет необходимый массив и затем конкретизируем каждую строку, используя конструктор класса String, позволяющий преобразовывать массив символов в строку new String(p,i1,i2). Здесь число i1 - это первый элемент массива, попадающий в строку, i2 - полное число элементов. Остальное очевидно.

Но здесь появилась еще и третья функция, которая нам понадобится позднее. Увы, я сам додумался до этой функции только через три года работы. Без нее тоже все работало, но немного странно. Эта функция как раз возвращает нам наше главное окно программы, к которому надо приклеивать диалоги, так как они не иконизируются. Если этого не делать, то есть задавать вместо окна null, то диалоги гуляют сами по себе, а программное окно само по себе. И если не открывать других окон Windows, то никаких проблем не возникает. Но если открывать - то их надо тут же закрывать. Если открыть окно программы после открытия чужого окна, то мы не увидим в нем диалога - он не приклеен. Как это делается. Метод возвращает объект класса Frame. Наше окно JFrame. Но это не беда, так как JFrame является прямым потомком Frame. Статический метод getFrames() класса Frame возвращает все окна, открытые программой. Метод getTitle() берет у каждого окна его заглавие и сравнивает с заглавием нашего окна mtit. Приставку MyPro уже не надо, так как мы и так в классе MyPro. При совпадении названий данное окно возвращается как объект.

И еще два небольших замечания. У этого класса нет конструктора. Если мы его не пишем - не беда, он автоматически подставляется в пустом виде. По этой причине мы могли не писать конструктор и во втором классе. Но там он все таки написан на предмет того, что возможно мы его все таки исправим. А здесь мы с самого начала договорились ставить только статические поля и статические методы. Ну и второе, этот класс является фактически библиотекой стандартных функций, как было в старых языках. Его можно наращивать как угодно долго и добавлять другие классы такого же типа. Фактически это наш золотой фонд в чистом виде. Примеры функций можно списывать из учебников, статей и т. д., которых полно в интернете.


[Назад]   [Вперед]
Hosted by uCoz