OberonCore https://forum.oberoncore.ru/ |
|
Java: (двумерный массив).clone() = ? https://forum.oberoncore.ru/viewtopic.php?f=26&t=2895 |
Страница 1 из 1 |
Автор: | Александр Ильин [ Среда, 06 Октябрь, 2010 16:19 ] |
Заголовок сообщения: | Java: (двумерный массив).clone() = ? |
Решил вот я подучить 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 |
Автор: | Александр Шостак [ Среда, 06 Октябрь, 2010 16:34 ] |
Заголовок сообщения: | Re: Java: (двумерный массив).clone() = ? |
Выскажу предположение. Массивы это объекты. Двумерные массивы - массивы объектов. Как и в javascript, передавая массив, вы передаёте объект и его изменение аналогично var-параметру. clone() создаёт новый массив и присваевает его элементам значения исходного массива. Только вот для двумерного массива эти значения сами объекты-массивы. |
Автор: | Евгений Темиргалеев [ Среда, 06 Октябрь, 2010 16:35 ] |
Заголовок сообщения: | Re: Java: (двумерный массив).clone() = ? |
хехе. есть предположение, что клонируется массив ссылок на одномерные массивы |
Автор: | Александр Ильин [ Среда, 06 Октябрь, 2010 16:49 ] |
Заголовок сообщения: | Re: Java: (двумерный массив).clone() = ? |
Действительно, .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; } |
Автор: | Валерий Лаптев [ Среда, 06 Октябрь, 2010 17:36 ] |
Заголовок сообщения: | Re: Java: (двумерный массив).clone() = ? |
В Яве реализована следующая дисциплина передачи параметров по умолчанию: 1. Элементарные типы данным передаются по значению. Это те же самые типы, что и в С++. 2. Объектные типы ВСЕГДА передаются по ссылке. Программист этим не управляет. Кроме того, надо смотреть методы сравнения - в каких-то вариантах сравниваются тоже ссылки, а не сами объекты (просто подробностей не помню - надо документацию смотреть) |
Автор: | Comdiv [ Среда, 06 Октябрь, 2010 18:22 ] |
Заголовок сообщения: | Re: Java: (двумерный массив).clone() = ? |
N-мерных массивов нет - есть только массивы массивов. Массивы - это объекты. Всё передаётся по значению, в том числе и объекты. Точнее не сами объекты, а указатели на них. При работе с этими указателями как в Обероне происходит незримое разыменование, вот только зримое отсутствует. Нельзя сделать так a^ = b^, всегда присваиваются указатели. Если не секрет, зачем Вам Java? |
Автор: | Сергей Губанов [ Четверг, 07 Октябрь, 2010 14:35 ] |
Заголовок сообщения: | Re: Java: (двумерный массив).clone() = ? |
Путаница из-за терминологии. В Яве аргументы в процедуры передаётся по значению, но Дельфийский, Явский и Шарповый "class" это "POINTER TO RECORD", а массив на самом деле не массив, а "POINTER TO ARRAY". |
Автор: | Info21 [ Четверг, 07 Октябрь, 2010 15:35 ] |
Заголовок сообщения: | Re: Java: (двумерный массив).clone() = ? |
Сергей Губанов писал(а): Путаница из-за терминологии. Путаница -- да, но как легко с ней разбираться, интерпретируя на Обероне.
В Яве аргументы в процедуры передаётся по значению, но Дельфийский, Явский и Шарповый "class" это "POINTER TO RECORD", а массив на самом деле не массив, а "POINTER TO ARRAY". |
Автор: | Александр Ильин [ Четверг, 07 Октябрь, 2010 20:13 ] |
Заголовок сообщения: | Re: Java: (двумерный массив).clone() = ? |
Comdiv писал(а): Если не секрет, зачем Вам Java? Для собеседования на работу.
|
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |