Перенос кода с C# на Java


Недавно была пара заказов по переписыванию кода с C# на Java, и вот я решил поделиться некоторыми мыслями по этому поводу. Если кратко, то портирование проекта с одного языка на другой – это не только изучение синтаксиса.

Давайте рассмотрим конкретный пример: имеем программу, созданную на языке C#. Это приложение генерирует случайный лабиринт заданных размеров, а потом ищет из него выход.



Если посмотреть в проект, то увидим, что вся логика работы заключена в одной форме – чуть более 300 строк кода. Ура? Несложно же, можно просто перенести построчно и все будет в порядке? Увы, это не совсем так. В процессе переноса придется столкнуться со множеством проблем; и хотя все они решаемы, придется повозиться.

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



Интерфейс создали, теперь идем непосредственно в код. Можно начать с обработчиков кнопок или других методов, но логичнее все же с наших «глобальных» переменных. Код на C#:

int widthMaze;
int heightMaze;
Stack<int> stackPath;
int tekCell;
Random r;
string myClr = "Black";
string quitClr = "Lime";
int indLastCell;
Код на Java:

int widthMaze;
int heightMaze;
Stack<Integer> stackPath;
int tekCell;
Random r;
String myClr = "BLACK";
String quitClr = "Lime";
int indLastCell;
Отличий практически нет, верно? И программист, знакомый с синтаксисом обоих языков без труда сделает данное преобразование. Переходим к методам. Возьмем, например, метод, выдающий массив свободных ячеек. Код на C#:

int[] getFreeCells(){
		int[] freeCells = new int[0];
			for(int i = 0; i < panel1.Controls.Count; i++){
				if(panel1.Controls[i].Tag == null){
					Array.Resize(ref freeCells, freeCells.Length + 1);
					freeCells[freeCells.Length - 1] = i;
				}
			}
		return freeCells;
		}
И тут нас настигает первая неожиданность: в Java нет метода Array.Resize. Вот совсем нет. Хорошо, попробуем понять, что делает данный код и переписать его с помощью возможных методов. В данном случае это несложно. По сути в этой функции getFreeCells() программа пробегает по объектам, расположенным на панели, сравнивает свойство объекта Tag и если оно равно null, то заносит в массив порядковый номер элемента на панели. Решить задачу на Java можно не так изящно, но зато без Array.Resize: например, создать промежуточный массив какого-либо размера (заведомо большего, чем число элементов), занести в него все порядковые номера объектов со свойством null, а потом из одного массива скопировать значения в другой (чтобы не было пустых ячеек).

То есть по сути мы сделали не как на C#: не увеличивали размер массива, а наоборот уменьшили заведомо больший. Примечание: можно было сделать все с помощью коллекций Java, которые мы разбирали в прошлых материалах, однако, это все усложняет программу для студентов, и снижает производительность, так что обойдемся обычными массивами.

Отлично. Но это еще не все проблемы данного метода. IDE Netbeans выдаст ошибку на попытку получить число элементов на панели (panel1.Controls.Count) надо заменить на:

Component[] components = jPanel1.getComponents();
for(int i = 0; i < components.length; i++){
Но и это далеко не все. В оригинальной программе на C# для отображения элементов лабиринта на панели используются PictureBox-ы – они либо закрашиваются, либо подставляется изображение стены. В Java, увы, нет PictureBox; для нашего «конвертирования» вполне достаточно в роли их использовать JLabel.

Правда, тут возникает еще одно затруднение: у JLabel нет свойства Tag. Давайте заменим его на ToolTipText – в общем, по большому счету нам без разницы, в чем будет храниться информация. Таким образом, метод на Java:

int[] getFreeCells(){
			int[] prom = new int[10000];
                        int chet=0;
                        Component[] components = jPanel1.getComponents();
			for(int i = 0; i < components.length; i++){
                         JLabel   jl = (JLabel) components[i];
				if(jl.getToolTipText() == null){          
                          prom[chet] =  i;
                          chet++;
				}
			}  
			int[] freeCells = new int[chet];
                        for(int i = 0; i < chet; i++){
                         freeCells[i] =  prom[i];                            
                        }                    
			return freeCells;                     
		}
Немного изменился наш метод, не правда ли? Причем это самый простой. Если дальше разбирать программу, то нам придется научиться создавать таймеры на Java (а это немного по-другому, чем на C#), научиться вставлять картинки задним фоном в метки; управлять стеком (методы очень похожие, здесь сложностей не будет); сравнивать цвет JLabel (кстати, задний фон не поменяется, пока не сделаем так: jl.setOpaque(true); ). Также надо будет учесть обновление и удаление элементо на панели для перезапуска генерации лабиринта.

И самое интересное: после полной конвертации программы с C# на Java, она не заработает, а вылетит с ошибкой ArrayIndexOutOfBoundsException, хотя визуал студио такой ошибки не выдает. Так что надо будет либо отлавливать эту jшибку, либо хотя бы заключить её в try – catch.

И только сделав все это, мы получим портированный лабиринт на Java:



Как видите, перенос кода с C# на Java возможен. И в большинстве случаев проще именно перенести готовый код, чем писать с нуля. Однако, если вы «плаваете» в обоих языках, то это может занять немало времени. Есть вопросы – пишите, всегда рад ответить за небольшую плату: я проконсультирую вас или перенесу код с/на Java, C#, C++, JavaScript и PHP. Цена зависит от сложности. Также есть готовые программы.
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.

тегизаметки, java, си шарп, портирование, перенос кода




Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.




Методы в C#
Алгоритм двоичного поиска
Привязка выпадающего списка к перечислению C#