OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Четверг, 21 Ноябрь, 2019 22:04

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 9 ] 
Автор Сообщение
 Заголовок сообщения: Java: (двумерный массив).clone() = ?
СообщениеДобавлено: Среда, 06 Октябрь, 2010 16:19 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2316
Откуда: Россия, Томск
Решил вот я подучить Java, сижу, разбираюсь. Подскажите мне кто-нибудь, что происходит в тестовом коде. Суть кода вот в чём. Заводим одномерный массив int[8] из нулей в процедуре test, передаём его в процедуру modify, и в этой процедуре заменяем, например, первый элемент на 1. Вопрос: изменится ли содержание массива в процедуре test? Поскольку в Java нет VAR-параметров, то вроде бы модификация должна остаться локальной в процедуре modify, и по возвращении в test массив снова должен быть нулевым (как если бы в modify передавалась копия массива). Тест VAR-test1 показывает, что это не так: массив оказывается модифицирован в обоих процедурах, как будто это VAR-параметр. Хорошо, значит у нас массив в куче и мы передали ссылку на него. Чтобы избавиться от VAR-эффекта, при передаче параметра вызовем массив.clone(). В этом случае модификация в modify не "всплывает" обратно в процедуру test. Проблема решена.

Теперь попробуем то же самое проделать с двумерным массивом. Здесь без вызова .clone() имеем VAR-эффект, как и в первом случае, НО с добавлением вызова .clone() VAR-эффект не пропадает! Я попробовал добавить проверку .equals(), и увидел, что проверка возвращает истину при передаче исходного массива и ложь при передаче клона. Это так и должно быть. Тем не менее, изменение массива, который !equals(), изменяет исходный массив аналогично VAR-параметру.

Объясните мне, пожалуйста:
- есть ли в Java VAR-параметры? Если да, то ими могут быть только массивы или ещё что-то?
- почему .clone() не срабатывает для двумерного массива так же, как срабатывает для одномерного?
- как так получается, что два массива, которые не .equals(), ссылаются на общие данные?

Код (на метод test1 не обращайте внимание):
Код:
import java.util.Arrays;
import java.util.List;

public class MyTest {

   private static int[] arr8;
   private static int[][] arr88;
   
   private static void test1 () {
      // note that Arrays.asList returns a collection, which, being modified, modifies the originally passed array      
      String[] arr = {"1", "2", "3"};
      List<String> lst = Arrays.asList(arr); // use arr.clone() to unlink from the collection
      lst.set(0, lst.set(2, lst.get(0))); // swap 0 and 2
      for (String i : lst) {
         System.out.print(i);
      }
      System.out.println();
      // note that in 'arr' the elements are swapped, too
      for (String i : arr) {
         System.out.print(i);
      }
      System.out.println();
   }

   private static void test2 () {
      // this test shows that arrays are passed by reference, i.e. as VAR-parameters
      // local variables are no different from the global static ones
      arr8 = new int[8];
      Arrays.fill(arr8, 0);
      modifyArr8(arr8);
      System.out.print("VAR-test1: ");
      System.out.println(arr8[0] == 1 ? "Modified" : "Not modified");
      // to avoid modification, use .clone() method
      Arrays.fill(arr8, 0);
      modifyArr8(arr8.clone()); // clone the array
      System.out.print("VAR-test1(clone): ");
      System.out.println(arr8[0] == 1 ? "Modified" : "Not modified");
      // this test shows that .clone() doesn't work for two-dimensional arrays
      arr88 = new int[8][8];
      Arrays.fill(arr88[0], 0);
      modifyArr88(arr88);
      System.out.print("VAR-test2: ");
      System.out.println(arr88[0][0] == 1 ? "Modified" : "Not modified");
      Arrays.fill(arr88[0], 0);
      modifyArr88(arr88.clone()); // clone the array
      System.out.print("VAR-test2(clone): ");
      System.out.println(arr88[0][0] == 1 ? "Modified" : "Not modified");
   }
   
   private static void modifyArr8 (int[] arr) {
      System.out.print("modifyArr8: equals before modification: ");
      System.out.println(arr.equals(arr8));
      arr[0] = 1;
      System.out.print("modifyArr8: equals after modification: ");
      System.out.println(arr.equals(arr8));
   }
                                            
   private static void modifyArr88 (int[][] arr) {
      System.out.print("modifyArr88: equals before modification: ");
      System.out.println(arr.equals(arr88));
      arr[0][0] = 1;
      System.out.print("modifyArr88: equals after modification: ");
      System.out.println(arr.equals(arr88));
      // NB! .equals() returns false for the .clone()d object, but the original one gets modified anyway
   }

   public static void main (String[] args) {
      test1();
      test2();
   }

}
Выдача при запуске:
Код:
321
321
Equals before modification: true
Equals after modification: true
VAR-test1: Modified
Equals before modification: false
Equals after modification: false
VAR-test1(clone): Not modified
Equals before modification: true
Equals after modification: true
VAR-test2: Modified
Equals before modification: false
Equals after modification: false
VAR-test2(clone): Modified


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Java: (двумерный массив).clone() = ?
СообщениеДобавлено: Среда, 06 Октябрь, 2010 16:34 

Зарегистрирован: Четверг, 23 Апрель, 2009 18:01
Сообщения: 219
Выскажу предположение. Массивы это объекты. Двумерные массивы - массивы объектов. Как и в javascript, передавая массив, вы передаёте объект и его изменение аналогично var-параметру. clone() создаёт новый массив и присваевает его элементам значения исходного массива. Только вот для двумерного массива эти значения сами объекты-массивы.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Java: (двумерный массив).clone() = ?
СообщениеДобавлено: Среда, 06 Октябрь, 2010 16:35 
Модератор
Аватара пользователя

Зарегистрирован: Среда, 16 Ноябрь, 2005 00:53
Сообщения: 4526
Откуда: Россия, Орёл
хехе. есть предположение, что клонируется массив ссылок на одномерные массивы :)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Java: (двумерный массив).clone() = ?
СообщениеДобавлено: Среда, 06 Октябрь, 2010 16:49 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2316
Откуда: Россия, Томск
Действительно, .clone() клонирует только первое измерение двумерного массива.
Добавление вот такой процедуры помогает:
Код:
   private static int[][] deepClone (int[][] arr) {
      int[][] res = arr.clone();
      for (int i = 0; i < arr.length; i++) {
         res[i] = arr[i].clone();
      }
      return res;
   }
   


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Java: (двумерный массив).clone() = ?
СообщениеДобавлено: Среда, 06 Октябрь, 2010 17:36 

Зарегистрирован: Суббота, 07 Март, 2009 15:39
Сообщения: 3109
Откуда: Астрахань
В Яве реализована следующая дисциплина передачи параметров по умолчанию:
1. Элементарные типы данным передаются по значению. Это те же самые типы, что и в С++.
2. Объектные типы ВСЕГДА передаются по ссылке.
Программист этим не управляет.
Кроме того, надо смотреть методы сравнения - в каких-то вариантах сравниваются тоже ссылки, а не сами объекты (просто подробностей не помню - надо документацию смотреть)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Java: (двумерный массив).clone() = ?
СообщениеДобавлено: Среда, 06 Октябрь, 2010 18:22 

Зарегистрирован: Четверг, 08 Май, 2008 19:13
Сообщения: 959
Откуда: Киев
N-мерных массивов нет - есть только массивы массивов. Массивы - это объекты.

Всё передаётся по значению, в том числе и объекты. Точнее не сами объекты, а указатели на них. При работе с этими указателями как в Обероне происходит незримое разыменование, вот только зримое отсутствует. Нельзя сделать так a^ = b^, всегда присваиваются указатели.

Если не секрет, зачем Вам Java?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Java: (двумерный массив).clone() = ?
СообщениеДобавлено: Четверг, 07 Октябрь, 2010 14:35 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 18:55
Сообщения: 2272
Откуда: Россия, Нижний Новгород
Путаница из-за терминологии.

В Яве аргументы в процедуры передаётся по значению, но Дельфийский, Явский и Шарповый "class" это "POINTER TO RECORD", а массив на самом деле не массив, а "POINTER TO ARRAY".


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Java: (двумерный массив).clone() = ?
СообщениеДобавлено: Четверг, 07 Октябрь, 2010 15:35 
Аватара пользователя

Зарегистрирован: Пятница, 25 Ноябрь, 2005 12:02
Сообщения: 8196
Откуда: Троицк, Москва
Сергей Губанов писал(а):
Путаница из-за терминологии.

В Яве аргументы в процедуры передаётся по значению, но Дельфийский, Явский и Шарповый "class" это "POINTER TO RECORD", а массив на самом деле не массив, а "POINTER TO ARRAY".
Путаница -- да, но как легко с ней разбираться, интерпретируя на Обероне.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Java: (двумерный массив).clone() = ?
СообщениеДобавлено: Четверг, 07 Октябрь, 2010 20:13 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2316
Откуда: Россия, Томск
Comdiv писал(а):
Если не секрет, зачем Вам Java?
Для собеседования на работу.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 9 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 0


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2019, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB