Java для программиста 1С

Содержание

Опишем только основные особенности и часто используемые возможности языка 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&lt;Row&gt; node : tree.getRoot().getChildren()) {
    Row dataRow = node.getData();
    Log.i("Test","dataRow.field1 = " + dataRow.field1);
 
    //выбрать первую подчиненную строку, если есть
    if(node.hasChildren()){
            GenericTreeNode&lt;Row&gt; child1 = node.getChildAt(0);
            Log.i("Test","child dataRow.field1 = " + child1.getData().field1);
    }
}
//перебор всех строк первого уровня
for (GenericTreeNode&lt;Row&gt; node : tree.getRoot().getChildren()) {
   	Row dataRow = node.getData();
   	Log.i("Test","dataRow.field1 = " + dataRow.field1);

   	//выбрать первую подчиненную строку, если есть
   	if(node.hasChildren()){
          	GenericTreeNode&lt;Row&gt; child1 = node.getChildAt(0);
          	Log.i("Test","child dataRow.field1 = " + child1.getData().field1);
   	}
}

результат:

Деревья используются в FBA для построения иерархической выборки из справочников.

Похожие записи: