Содержание
- Часто используемые примитивные типы
- Массивы
- Операции с базовыми типами и объектами
- Строки
- Дата и время
- Object – базовый класс всех объектов
- Форматирование и парсинг значений
- Циклы
- Структура и соответствие
- Списки значений
- Таблица значений
- Дерево значений
Опишем только основные особенности и часто используемые возможности языка Java в сравнении со встроенным языком 1С, покажем аналоги часто используемых объектов: “структура”, “соответствие”, “таблица значений” и т.п.
Цель этого документа – помочь программисту 1С максимально быстро начать разработку на новом для него языке Java.
Часто используемые примитивные типы
1 2 3 | boolean bValue = true; int iValue = 100; double dValue = 100.00; |
boolean bValue = true; int iValue = 100; double dValue = 100.00;
У примитивных типов есть замещающие классы (классы-обертки), пишутся с большой буквы. Были придуманы для того, чтобы иметь возможность оперировать с простыми числами как с объектами.
1 | Integer intValue = new Integer(100); |
Integer intValue = new Integer(100);
Вы можете использовать их параллельно с примитивными типами, абсолютно прозрачно:
1 2 | Integer x = 1; Boolean a = false; |
Integer x = 1; Boolean a = false;
Массивы
Динамический размер:
1 2 3 | float[] rates = null; ... rates = new float[<перем. количество элементов>]; |
float[] rates = null; ... rates = new float[<перем. количество элементов>];
Краткая форма инициализации при объявлении:
1 2 3 4 | //Скобки [] могут быть указаны после типа или после имени переменной. int[] arr = new int[]{1,2,3}; boolean arr2[] = new boolean[]{true,false,true}; String[] arr3 = new String[]{"String1","String2","String3"}; |
//Скобки [] могут быть указаны после типа или после имени переменной. int[] arr = new int[]{1,2,3}; boolean arr2[] = new boolean[]{true,false,true}; String[] arr3 = new String[]{"String1","String2","String3"};
Многомерные массивы
Для двумерного массива не существует такого понятия как его размеры. Можно определить размер массива только по первому индексу. Причина кроется в организации массива. Он представляет собой массив ссылок на массивы, каждый из которых содержит реальные данные. И эти массивы могут иметь разную длину!
1 2 3 4 5 6 7 8 | // 10 строк по 5 колонок в каждой int[][] array2d = new int[10][5]; //вариант 2 - разная размерность int[][] a = new int[3][]; // линия 1 a[0] = new int[2]; // линия 2 a[1] = new int[4]; // линия 3 a[2] = new int[3]; // линия 4 |
// 10 строк по 5 колонок в каждой int[][] array2d = new int[10][5]; //вариант 2 - разная размерность int[][] a = new int[3][]; // линия 1 a[0] = new int[2]; // линия 2 a[1] = new int[4]; // линия 3 a[2] = new int[3]; // линия 4
Операции с базовыми типами и объектами
- операция присваивания =, но не сравнения
- базовые типы сравнивать через == и != (не равно).
- объекты сравнивать только через метод equals
1 2 3 4 5 6 7 8 9 | String sValue = "Hello"; if(sValue=="Hello"){ //это никогда не выполнится } //надо так if(sValue.equals("Hello")){ } |
String sValue = "Hello"; if(sValue=="Hello"){ //это никогда не выполнится } //надо так if(sValue.equals("Hello")){ }
1 2 3 4 5 6 7 8 9 10 11 | //смотрите также прочие математически функции в модуле Math double result = Math.log(2); //случайное целое в диапазоне 0 - 5 Random rnd = new Random(); … rnd.nextInt(5); //округление до 2 знаков вверх double value = 1234.5678; double round = new BigDecimal(value).setScale(2, RoundingMode.HALF_UP) .doubleValue(); |
//смотрите также прочие математически функции в модуле Math double result = Math.log(2); //случайное целое в диапазоне 0 - 5 Random rnd = new Random(); … rnd.nextInt(5); //округление до 2 знаков вверх double value = 1234.5678; double round = new BigDecimal(value).setScale(2, RoundingMode.HALF_UP) .doubleValue();
Строки
String это не примитивный тип, а класс! Индекс первого символа в строке = 0.
1 2 | String a = "Привет!"; String b = new String("Привет!"); |
String a = "Привет!"; String b = new String("Привет!");
Помните, каждая строка — неизменяемый объект, делая так: String x = «ads» + «dsada», вы сжираете не 8*2 а 16*2 байт. Сначала происходит создание первых двух строк, затем третьей.Чтобы избежать этого были придуманы StringBuffer и StringBuilder.
1 2 3 4 | StringBuilder hi = new StringBuilder; hi.append("Привет, мир"); hi.append(". "); hi.append("Как твои дела?"); |
StringBuilder hi = new StringBuilder; hi.append("Привет, мир"); hi.append(". "); hi.append("Как твои дела?");
Функции работы со строками
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | String str = "Это текстовая строка"; //1C: ВРег(<Строка>) и НРег(<Строка>) String resUp = str.toUpperCase(); String resLw = str.toLowerCase(); //1C: Лев(<Строка>, <Число символов>) String resL = str.substring(0, 5); //1C: Найти(<Строка>, <Подстрока поиска>) int index = str.indexOf("строка"); //1C: ПустаяСтрока(<Строка>) boolean empty = TextUtils.isEmpty(str); //1C: СокрЛП(<Строка>) String resTr = str.trim(); //1C: СтрЗаменить(<Строка>, <Подстрока поиска>, <Подстрока замены>) String resRepl = str.replaceAll("Подстрока поиска", "Подстрока замены"); |
String str = "Это текстовая строка"; //1C: ВРег(<Строка>) и НРег(<Строка>) String resUp = str.toUpperCase(); String resLw = str.toLowerCase(); //1C: Лев(<Строка>, <Число символов>) String resL = str.substring(0, 5); //1C: Найти(<Строка>, <Подстрока поиска>) int index = str.indexOf("строка"); //1C: ПустаяСтрока(<Строка>) boolean empty = TextUtils.isEmpty(str); //1C: СокрЛП(<Строка>) String resTr = str.trim(); //1C: СтрЗаменить(<Строка>, <Подстрока поиска>, <Подстрока замены>) String resRepl = str.replaceAll("Подстрока поиска", "Подстрока замены");
Дата и время
1 2 3 4 5 | //текущая дата,вариант 1 Date date = new Date(System.currentTimeMillis()); //текущая дата,вариант 2 Calendar cal = Calendar.getInstance(); |
//текущая дата,вариант 1 Date date = new Date(System.currentTimeMillis()); //текущая дата,вариант 2 Calendar cal = Calendar.getInstance();
Для манипуляции с датами можно использовать методы из обоих классов, но рекомендуется Calendar. Например, добавить месяц:
1 2 | Calendar cal = Calendar.getInstance(); cal.add(Calendar.MONTH, 1); |
Calendar cal = Calendar.getInstance(); cal.add(Calendar.MONTH, 1);
Вы можете также использовать помощник работы с датами – класс DateHelper, входящий в состав FBA:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | //конструктор даты. Важно! Месяц начинается с нуля Date dt = DateHelper.date(2013, Calendar.JANUARY, 1); //добавить день Date dt2 = DateHelper.addDays(dt, 1); //1C: НачалоДня(<Дата>) Date dtBegin = DateHelper.beginOfDay(date); //1C: КонецДня(<Дата>) Date dtEnd = DateHelper.endOfDay(date); //разность дней int dif = DateHelper.diffDays(dtEnd, dtBegin); //извлечь год, месяц, день года //1C: Год(<Дата>), Месяц(<Дата>), ДеньГода(<Дата>) Calendar c = Calendar.getInstance(); c.setTime(date); int year = c.get(Calendar.YEAR); int month = c.get(Calendar.MONTH); int day = c.get(Calendar.DAY_OF_YEAR); |
//конструктор даты. Важно! Месяц начинается с нуля Date dt = DateHelper.date(2013, Calendar.JANUARY, 1); //добавить день Date dt2 = DateHelper.addDays(dt, 1); //1C: НачалоДня(<Дата>) Date dtBegin = DateHelper.beginOfDay(date); //1C: КонецДня(<Дата>) Date dtEnd = DateHelper.endOfDay(date); //разность дней int dif = DateHelper.diffDays(dtEnd, dtBegin); //извлечь год, месяц, день года //1C: Год(<Дата>), Месяц(<Дата>), ДеньГода(<Дата>) Calendar c = Calendar.getInstance(); c.setTime(date); int year = c.get(Calendar.YEAR); int month = c.get(Calendar.MONTH); int day = c.get(Calendar.DAY_OF_YEAR);
Object – базовый класс всех объектов
Класс Object – корень иерархии классов. Каждый класс имеет Object как суперкласс. Все объекты, включая массивы, реализуют методы этого класса.
Помимо прочего, может использоваться как универсальный тип переменной (в терминах 1С):
1 2 3 4 | Object obj = null; obj = 100; obj = "Hello"; obj = 10.00; |
Object obj = null; obj = 100; obj = "Hello"; obj = 10.00;
Однако, для выполнения операций вы должны выполнить явное приведение типов:
1 2 | Object obj = 100; obj = (Integer)obj + 1; |
Object obj = 100; obj = (Integer)obj + 1;
Форматирование и парсинг значений
Для приведения к строке всех классов наследников от Object используете toString метод. Он же используется везде, где требуется автоматическое преобразование, например, во второй строке будет вызван метод toString автоматически при конкатенации:
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 | Integer value = 100; System.out.print("Intget value = " + value); //форматирование строк String str = "Иванов"; String str2= "Иван"; String str3 = "Иванович"; String result = String.format("ФИО: %s %s %s", str, str2,str3); long n = 461012; System.out.format("%d%n", n); // --> "461012" System.out.format("%08d%n", n); // --> "00461012" double pi = Math.PI; System.out.format("%f%n", pi); // --> "3.141593" System.out.format("%.3f%n", pi); // --> "3.142" //форматирование чисел private DecimalFormat df = new DecimalFormat("####.##"); String str = df.format(<число>); //форматирование даты SimpleDateFormat formatter = new SimpleDateFormat("dd.MM.yyy HH:mm:ss"); String dateString = formatter.format(new Date()); //парсинг значений boolean bValue = Boolean.parseBoolean("true"); int value = Integer.parseInt("100"); double dValue = Double.parseDouble("123.45"); SimpleDateFormat frm = new SimpleDateFormat("dd.MM.yyyy"); Date date = frm.parse("01.01.2012"); |
Integer value = 100; System.out.print("Intget value = " + value); //форматирование строк String str = "Иванов"; String str2= "Иван"; String str3 = "Иванович"; String result = String.format("ФИО: %s %s %s", str, str2,str3); long n = 461012; System.out.format("%d%n", n); // --> "461012" System.out.format("%08d%n", n); // --> "00461012" double pi = Math.PI; System.out.format("%f%n", pi); // --> "3.141593" System.out.format("%.3f%n", pi); // --> "3.142" //форматирование чисел private DecimalFormat df = new DecimalFormat("####.##"); String str = df.format(<число>); //форматирование даты SimpleDateFormat formatter = new SimpleDateFormat("dd.MM.yyy HH:mm:ss"); String dateString = formatter.format(new Date()); //парсинг значений boolean bValue = Boolean.parseBoolean("true"); int value = Integer.parseInt("100"); double dValue = Double.parseDouble("123.45"); SimpleDateFormat frm = new SimpleDateFormat("dd.MM.yyyy"); Date date = frm.parse("01.01.2012");
Циклы
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | //аналог 1С "Для Счетчик = 0 По 10 Цикл" //при этом счетчик автоматически инкрементируется на каждом шаге for(int i = 0; i<10;i++){ //тело цикла } //аналог 1С "Пока <Условие> Цикл" int i = 5; while(i>0){ //тело цикла i--; } //аналог 1С "Для Каждого ТекЭлемент Из МассивЭлементов Цикл" //перебор любых коллекций String[] str = new String[] { "String1", "String2", "String3" }; for (String s : str) { //тело цикла, s - текущий элемент коллекции } |
//аналог 1С "Для Счетчик = 0 По 10 Цикл" //при этом счетчик автоматически инкрементируется на каждом шаге for(int i = 0; i<10;i++){ //тело цикла } //аналог 1С "Пока <Условие> Цикл" int i = 5; while(i>0){ //тело цикла i--; } //аналог 1С "Для Каждого ТекЭлемент Из МассивЭлементов Цикл" //перебор любых коллекций String[] str = new String[] { "String1", "String2", "String3" }; for (String s : str) { //тело цикла, s - текущий элемент коллекции }
Универсальные коллекции значений
Структура и соответствие
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 | //1C: Структура HashMap<String,Object> mapStruct = new HashMap<String, Object>(); mapStruct.put("key1", 100); mapStruct.put("key2", 123.45); mapStruct.put("key3", "value3"); //обход коллекции значений for(String key:mapStruct.keySet()){ Object value = mapStruct.get(key); } //1C: Структура, метод Свойство(<Ключ>, <Найденное значение>) boolean contains = mapStruct.containsKey("key1"); //1C: Структура, метод Количество() mapStruct.size(); //1C: Структура, метод Очистить() mapStruct.clear(); //1C: Структура, метод Удалить(<Ключ>) mapStruct.remove("key2"); //Для «соответствия» все тоже самое, только тип ключа задается как Object HashMap<Object,Object> map = new HashMap<Object, Object>(); |
//1C: Структура HashMap<String,Object> mapStruct = new HashMap<String, Object>(); mapStruct.put("key1", 100); mapStruct.put("key2", 123.45); mapStruct.put("key3", "value3"); //обход коллекции значений for(String key:mapStruct.keySet()){ Object value = mapStruct.get(key); } //1C: Структура, метод Свойство(<Ключ>, <Найденное значение>) boolean contains = mapStruct.containsKey("key1"); //1C: Структура, метод Количество() mapStruct.size(); //1C: Структура, метод Очистить() mapStruct.clear(); //1C: Структура, метод Удалить(<Ключ>) mapStruct.remove("key2"); //Для «соответствия» все тоже самое, только тип ключа задается как Object HashMap<Object,Object> map = new HashMap<Object, Object>();
Элементы коллекции не упорядочены, для создания упорядоченной (в порядке добавления) коллекции:
1 | Map<String,Object> mapSorded = new LinkedHashMap<String,Object>(); |
Map<String,Object> mapSorded = new LinkedHashMap<String,Object>();
Списки значений
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 | //неупорядоченный список уникальных строк Set<String> set = new HashSet<String>(); //упорядоченный (в порядке добавления) список объектов Set<Object> setLinked = new LinkedHashSet<Object>(); //упорядоченный по значению список чисел Set<Integer> treeSet = new TreeSet<Integer>(); treeSet.add(5); treeSet.add(2); treeSet.add(6); //выведет [2,5,6] System.out.print(treeSet.toString()); //список строк, допускается дублирование значений ArrayList<String> arr = new ArrayList<String>(); //перебор значений в коллекции, вариант 1: int size = arr.size(); for(int i=0; i< size;i++){ String value = arr.get(i); } //перебор значений, вариант 2 for(String s: arr){ } |
//неупорядоченный список уникальных строк Set<String> set = new HashSet<String>(); //упорядоченный (в порядке добавления) список объектов Set<Object> setLinked = new LinkedHashSet<Object>(); //упорядоченный по значению список чисел Set<Integer> treeSet = new TreeSet<Integer>(); treeSet.add(5); treeSet.add(2); treeSet.add(6); //выведет [2,5,6] System.out.print(treeSet.toString()); //список строк, допускается дублирование значений ArrayList<String> arr = new ArrayList<String>(); //перебор значений в коллекции, вариант 1: int size = arr.size(); for(int i=0; i< size;i++){ String value = arr.get(i); } //перебор значений, вариант 2 for(String s: arr){ }
Таблица значений
Самый простой вариант создания таблицы значений:
1. Создать класс для строк таблицы, в котором определить колонки, их типы и логику заполнения.
2. Создать список содержащий строки.
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 | public void testTable(){ //таблица значений ArrayList<Row> table = new ArrayList<Row>(); //добавить строку Row row = new Row("Значение1 в первой строке", 1, 123.45); table.add(row); … … } /* * Строка таблицы */ public static class Row { String field1; int field2; double field3; Row(String field1, int field2, double field3) { this.field1 = field1; this.field2 = field2; this.field3 = field3; } } |
public void testTable(){ //таблица значений ArrayList<Row> table = new ArrayList<Row>(); //добавить строку Row row = new Row("Значение1 в первой строке", 1, 123.45); table.add(row); … … } /* * Строка таблицы */ public static class Row { String field1; int field2; double field3; Row(String field1, int field2, double field3) { this.field1 = field1; this.field2 = field2; this.field3 = field3; } }
Дерево значений
Для работы с деревьями вы можете использовать входящие в состав FBA классы GenericTree.java
GenericTreeNode.java
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 | // 1 данные для строки дерева, класс Row идентичен пред. примеру Row rowData = new Row("Значение 1", 1, 123.45); // 1-ая строка дерева GenericTreeNode<Row> row1 = new GenericTreeNode<Row>(rowData); //строки дерева 2-5 GenericTreeNode<Row> row2 = new GenericTreeNode<Row>(new Row("Значение 2", 100, 0)); GenericTreeNode<Row> row3 = new GenericTreeNode<Row>(new Row("Значение 3", 101, 1.00)); GenericTreeNode<Row> row4 = new GenericTreeNode<Row>(new Row("Значение 4", 102, 1.01)); GenericTreeNode<Row> row5 = new GenericTreeNode<Row>(new Row("Значение 5", 103, 1.03)); //построим вот такое дерево: //root // |-- 1 // |-- 2 // | --[3,4] // |-- 5 // корень дерева GenericTreeNode<Row> root = new GenericTreeNode<Row>(new Row("Корень", 0, 0)); //добавить 3 строки в конень root.addChild(row1); root.addChild(row2); root.addChild(row5); //добавить 2 починеные строки row2.addChild(row3); row2.addChild(row4); // создать дерево и установит корень GenericTree<Row> tree = new GenericTree<Row>(); tree.setRoot(root); //построить как линейный список List<GenericTreeNode<Row>> allNode = tree.build(GenericTreeTraversalOrderEnum.PRE_ORDER); for(GenericTreeNode<Row> node: allNode){ Row dataRow = node.getData(); Log.i("Test","dataRow.field1 = " + dataRow.field1); } |
// 1 данные для строки дерева, класс Row идентичен пред. примеру Row rowData = new Row("Значение 1", 1, 123.45); // 1-ая строка дерева GenericTreeNode<Row> row1 = new GenericTreeNode<Row>(rowData); //строки дерева 2-5 GenericTreeNode<Row> row2 = new GenericTreeNode<Row>(new Row("Значение 2", 100, 0)); GenericTreeNode<Row> row3 = new GenericTreeNode<Row>(new Row("Значение 3", 101, 1.00)); GenericTreeNode<Row> row4 = new GenericTreeNode<Row>(new Row("Значение 4", 102, 1.01)); GenericTreeNode<Row> row5 = new GenericTreeNode<Row>(new Row("Значение 5", 103, 1.03)); //построим вот такое дерево: //root // |-- 1 // |-- 2 // | --[3,4] // |-- 5 // корень дерева GenericTreeNode<Row> root = new GenericTreeNode<Row>(new Row("Корень", 0, 0)); //добавить 3 строки в конень root.addChild(row1); root.addChild(row2); root.addChild(row5); //добавить 2 починеные строки row2.addChild(row3); row2.addChild(row4); // создать дерево и установит корень GenericTree<Row> tree = new GenericTree<Row>(); tree.setRoot(root); //построить как линейный список List<GenericTreeNode<Row>> allNode = tree.build(GenericTreeTraversalOrderEnum.PRE_ORDER); for(GenericTreeNode<Row> node: allNode){ Row dataRow = node.getData(); Log.i("Test","dataRow.field1 = " + dataRow.field1); }
результат:
1 2 3 4 5 6 7 8 9 10 11 | //перебор всех строк первого уровня for (GenericTreeNode<Row> node : tree.getRoot().getChildren()) { Row dataRow = node.getData(); Log.i("Test","dataRow.field1 = " + dataRow.field1); //выбрать первую подчиненную строку, если есть if(node.hasChildren()){ GenericTreeNode<Row> child1 = node.getChildAt(0); Log.i("Test","child dataRow.field1 = " + child1.getData().field1); } } |
//перебор всех строк первого уровня for (GenericTreeNode<Row> node : tree.getRoot().getChildren()) { Row dataRow = node.getData(); Log.i("Test","dataRow.field1 = " + dataRow.field1); //выбрать первую подчиненную строку, если есть if(node.hasChildren()){ GenericTreeNode<Row> child1 = node.getChildAt(0); Log.i("Test","child dataRow.field1 = " + child1.getData().field1); } }
результат:
Деревья используются в FBA для построения иерархической выборки из справочников.