JavaRush/Курсы/Java Syntax/Переменные-ссылки

Переменные-ссылки

Открыта

— Привет, Амиго, это снова я – Элли. Прости, что постоянно так говорю, так просто принято на Земле в 31 веке. Я хочу рассказать тебе об особенностях переменных-ссылок и передаче в функции(методы) аргументов-ссылок.

— Я готов.

— Отлично, тогда слушай. Переменные-ссылки – это переменные всех типов, кроме примитивных. Такие переменные содержат в себе только адрес объекта (ссылку на объект).

— Переменные примитивных типов хранят в себе значения, а переменные типов-классов хранят ссылку на объекты этого же класса, ну или хранят null. Я все правильно говорю?

— Абсолютно верно.

— Так что же это такое — эта ссылка?

— Объект и ссылка на него связаны, примерно, как человек и его телефонный номер. Телефонный номер не является человеком, но номер можно использовать, чтобы звонить человеку, спрашивать у него какую-то информацию, руководить им или давать команды. Ссылка тоже используется для взаимодействия с объектом. Все объекты взаимодействуют друг с другом при помощи ссылок.

— Это как если бы люди общались друг с другом по телефону?

— Именно. При присваивании примитивного объекта, его значение копируется (дублируется). При присваивании же ссылочной переменной, копируется только адрес объекта (телефонный номер), сам же объект при этом не копируется.

— Ок, понял.

— Ссылка даёт ещё одно преимущество: можно передать ссылку на объект в какой-нибудь метод, и этот метод будет в состоянии модифицировать (изменять) наш объект используя ссылку на него, вызывая его методы и обращаясь к данным внутри объекта.

Пример 1
Тут значение m и n не меняется.
public class References
{
  public static void main (String[] args)
  {
    int m = 5; int n = 6;

    System.out.println("M=" +m+ " N=" + n);
    swap(m, n);
    System.out.println("M=" +m+ " N=" + n);
  }

  private static void swap(int a, int b)
  {
    int c = a;
    a = b;
    b = c;
  }
}
И вот почему.
Данный код аналогичен коду слева
public class References
{
  public static void main (String[] args)
  {
    int m = 5; int n = 6;

    System.out.println("M=" +m+ " N=" + n);
    int a = m, b = n;

    int c = a;
    a = b;
    b = c;

    System.out.println("M=" +m+ " N=" + n);
  }
}

— Переменным a и b присваиваются только значения 5(m) и 6(n) соответственно, a и b ничего не знают про (никак не влияют на) m и n.

— Честно говоря, я понял, что я ничего не понял. Можно еще пару примеров?

— В случае со ссылочным типом, можно было сделать так:

Пример 2
Тут данные объектов меняются
public class Primitives
{
  public static void main(String[] args)
  {
    Student olga = new Student(); olga.name = "Olga"; olga.age = 21; Student vera = new Student(); vera.name = "Veronika"; vera.age = 15;

    System.out.println("Olga is " + olga.age);
    System.out.println("Vera is " + vera.age);

 ageSwap(olga, vera);

    System.out.println("Olga is " + olga.age);
    System.out.println("Vera is " + vera.age);
  }

  private static void ageSwap(Student a,
                                    Student b)
  {
    int c = a.age; a.age = b.age; b.age = c;
  }

  static class Student
  {
    String name;
    int age;
  }
}
И вот почему.
Данный код аналогичен коду слева
public class Primitives
{
  public static void main(String[] args)
  {
    Student olga = new Student(); olga.name = "Olga"; olga.age = 21; Student vera = new Student(); vera.name = "Veronika"; vera.age = 15;
    System.out.println("Olga is " + olga.age);
    System.out.println("Vera is " + vera.age);

    Student a = olga, b = vera;

    int c = a.age; a.age = b.age; b.age = c;

    System.out.println("Olga is " + olga.age);
    System.out.println("Vera is " + vera.age);
  }





  static class Student
  {
    String name;
    int age;
  }
}

— Переменным a и b присваиваются ссылки на olga и vera соответственно, a и b меняют значения внутри объектов olga и vera.

— Так классы внутри других классов ещё можно объявлять? Круто!

— Но в остальном не очень-то и понятно.

— Не все сразу.

2
Задача
Java Syntax Pro Beta,  2 уровень6 лекция
Недоступна
Логотип решает все
В переменную tagline нужно записать строку "JustDoIt". Используй s1, s2, s3 и конкатенацию строк.
2
Задача
Java Syntax Pro Beta,  2 уровень6 лекция
Недоступна
Пустота и пробелы
Заполни пробелы пустотой... или наоборот. Используй переменную emptiness, строки с одним пробелом и конкатенацию строк, чтобы записать в переменную fullness строку "пустота пустота пустота".
2
Задача
Java Syntax Pro Beta,  2 уровень6 лекция
Недоступна
Конкатенация строк и чисел
В переменную digits нужно записать строку "60". Используй переменные x, y, z, пустую строку и конкатенацию строк.
2
Задача
Java Syntax Pro Beta,  2 уровень6 лекция
Недоступна
С каждым разом огромнее
В переменную hugeAmount нужно записать число 100500. Используй переменные bigAmount, greatAmount и преобразование строки в число. Для объявления и инициализации hugeAmount используй одну команду.
2
Задача
Java Syntax Pro Beta,  2 уровень6 лекция
Недоступна
Получение длины строки
В методе main на экран выводятся значения трех строк. Внеси изменения в код, чтобы вместо значений строк, вывелись их длины.
2
Задача
Java Syntax Pro Beta,  2 уровень6 лекция
Недоступна
Причешем резюме
Метод main выводит на экран четыре строки. Все они - яркий пример злоупотребления заглавными буквами. Внеси изменения в код, чтобы все буквы в этих строках стали строчными.
2
Задача
Java Syntax Pro Beta,  2 уровень6 лекция
Недоступна
Попрошу регистр на меня не повышать!
В методе main на экран выводятся три строки. Внеси изменения в код, чтобы все буквы в этих строках стали заглавными.
Комментарии (503)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Anonymous #1883657
Уровень 8
16 февраля, 07:44
swap - это Collections.swap() — метод класса java.util.Collections в Java, который меняет местами элементы на двух указанных позициях в списке.
vlafriday
Уровень 1
11 февраля 2024, 04:46
11.02.2024 check, мой уровень 2
nescafe
Уровень 30
17 июня 2023, 13:22
Уважаемые обучающиеся, добрый день! Решил показать свой взгляд на тему - примитивы хранят в себе значение, а ссылочные объекты - только ссылку. Возможно моё "объяснение" кому то да поможет)
public class Solution {
    public static void main(String[] args) {
        int a = 5;
        int b = a;
        b = 6;
        System.out.printf("1st int was 5, and now - %d.  2nd int was 5, and now - %d\n",a,b);
        Student olya = new Student("Olya",15);
        Student olya2 = olya;
        olya2.age = 20;
        System.out.printf("Olya's age was - 15, and now %d\n",olya2.age);
        /* ВЫВОД
        1st int was 5, and now - 5.  2nd int was 5, and now - 6
        Olya's age was - 15, and now 20. Sofa's age was - 20, and now 15
         */
        // то есть мы создали второй объект, присвоили ему значение от первого. Произвели изменение этого поля ТОЛЬКО на втором объекте.
        // так как примитивы передаются по значению - в первом выводе переманная "а" осталась == 5, а переменная "b" == 6
        // а ссылочная переменная olya2 ссылается на объект olya (в 19 строке), и все изменения производимые над объектом olya2
        // влияют на объект olya, так как по факту объект 1 (new Student()), а ссылки на него 2 (olya,olya2)
        // для понимания этого попробуем поменять возраст через объект olya
        olya.age = 25;
        System.out.printf("Olya's age was - 20, and now %d\n",olya.age);
    }

    public static class Student {
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
        String name;
        int age;
    }
}
Для объяснения, строчки a=5; b=a; b=6; Integer a = new Integer(5); Integerb = new Integer(5)(т.е две независимые "5") Int b = 6; а запись Student olya = new Student(); Student olya2= olya; (1 объект new Student(); и на него ссылаются 2 ссылочные переменные olya и olya2)
Perl Developer Perl Developer
25 июля 2022, 16:34
Сдаётся мне, что классы
class Primitives
и
class References
нужно переименовать один на другого.
Сергей
Уровень 2
22 января 2022, 20:11
Все же не все понятно с переменными ссылочного типа, напишу свои рассуждения и прошу тех кто знает поправить и подсказать: Пример
Cat murzik = new Cat();
мы создали ссылочную переменную и сразу передали ссылку на объект в котором хранится "null", но что происходит когда мы просто создаем переменную и ничего в нее не передаем? т.е:
Cat murzik;
что хранит в данный момент murzik? В лекциях писали, что хранится ссылка на объект, но ведь объект еще не создан, если по аналогии с простыми типами данных:
int a;
до того как в переменную "а" мы что-то положим JVM выделит память для хранения переменной, но со сложными типами объем памяти которую нужно зарезервировать заранее неизвестен, верно? Значит о резерве речь не идет и переменная хранит ссылку, но куда на тот класс который мы создали для описания данного типа "Cat", т.е. буквально на файл cat.java, если класс описан в отдельном файле? Тогда логично, что при написании "Cat cat = new Cat()" мы по сути даем команду собрать объект по классу Cat который описывает тип Cat. Понимаю что много букв, если совсем коротко и без моих домыслов, то - Что хранит "cat" при записи Cat cat?
Максимка
Уровень 9
25 января 2022, 11:19
1. Когда мы объявляем объект, но не создаем, то вместо ссылки будет null. 2. Jvm выделяет память исходя из переменных. Int=16, long=32. Так как любой класс состоит из полей и методов, то при объявлении нового экземпляра класса, учитывая какие переменные и каких типов будут внутри,выделяется память. 3. Cat cat=null;
SkyGod
Уровень 26
30 марта 2022, 11:29
По все видимости, при создании Cat cat = new Cat() Java выделит память объекту и будет хранить пустым это место в памяти, пока жива ссылка на объект, а при создании просто Cat cat Java удалит ссылку на этот объект сразу после создания, если я правильно все понимаю.
Benjam1nBTN
Уровень 24
25 июля 2022, 14:42
Если мы пишем просто "Cat murzik;", то murzik хранит ссылку в никуда (null), для этого в памяти выделяется 4 бита (размер для ссылки). Вроде так, насколько я понял
Александр
Уровень 3
9 января 2022, 15:47
Ребят, поясните , зачем мы создаем Тип переменной свой. Cat cat = new Cat(); Есть типы, int, string и так далее. Зачем придумываем свой тип? Когда нам это понадобится? От этих кат кат кат голова кругом.
Alexey
Уровень 15
13 января 2022, 07:59
Везде, на одних примитивах далеко не уедешь)
Денис
Уровень 3
1 февраля 2022, 20:18
Почитай историю программирования, как пришли к ООП, спойлер, не от хорошей жизни. Сначала и переменных не было - машинных кодов хватало, программы становились сложнее и сложнее и пришлось применять код ассемблер, потом процедурные языки, но и они не справлялись, так и дошли до ООП с их Классами, позволяющими создавать бесконечное множество новых ссылочных типов данных.
Mr. Hat
Уровень 9
9 февраля 2022, 11:44
Попробую объяснить, как понял я строчку Cat Kot = new Cat();: Здесь левая часть это похоже на объявление пустой переменной как int Chislo, String Stroka. После этого переменным будет автоматически присвоено значение по-умолчанию. Chislo - 0, Stroka - ""(ни одного символа), а переменная Kot будет содержать Null (значение по-умолчанию для объектов) Правая сторона как раз и создание объекта(со всеми переменными которые ты в нем перечисляешь) и его нужно сразу куда-то закинуть, иначе останется нигде, и обратиться к нему не сможешь уже. Поэтому сразу создал и присвоил. А то что в курсе тавтология - это действительно смущает. Насчет зачем свой тип - потому что ты захочешь создать свой сложный объект который будет хранить больше чем 1 вид переменных(контакт например должен содержать телефон и имя), а такого типа еще нет в языке, и придется создавать свой.
Eugene Shoo
Уровень 4
23 декабря 2021, 16:58
ребят, еще такой момен, понимаю что дальше не пойду без понимания этой строки... объясните пожалуйста... Cat cat = new Cat; за что отвеяает каждое из трех написанных Саt cat Cat. Сори за ленивый вопрос, закипаю уже =/
vitek987
Уровень 6
24 декабря 2021, 13:06
В задании лекции 2 было описано: ТипПеременной имяПеременной = new ТипСоздаваемогоОбъекта(); Cat cat Cat
Eugene Shoo
Уровень 4
24 декабря 2021, 13:33
спасибо
Дмитрий
Уровень 5
6 сентября 2022, 11:43
Я не могу понять почему они в примере не могли имя переменной написать не cat а хотя бы Vasya, везде эти cat только в заблуждение лично меня вводят
Артем
Уровень 9
13 января 2023, 15:02
Тоже долго над этим думал и вот к чему пришел. Cat cat, потому, что класс Cat создает котов, то есть cat. У каждого кота может быть свое имя, возраст, вес и т.д. Причем в момент создания этого объекта, эти значения могут быть неизвестны, а появятся позже. Если же назвать объект vasya (причем по правилам именно с маленькой буквы, но это другая тема), то во-первых, как минимум имя этого кота будет уже не изменить, во-вторых никуда его не передать, а в-третьих если где-то в коде встретить vasya, то с ходу не понять, это кот, пес, или его хозяин) А когда видишь cat, cat1, cat2 то уже понятнее)
Eugene Shoo
Уровень 4
22 декабря 2021, 23:54
a = m(5), b = n(6). а = b. 5 = 6??? как???
Mr. Hat
Уровень 9
9 февраля 2022, 11:57
Не понятный вопрос.
a = m(5), b = n(6).
Это присвоение, а не сравнение
а = b.
После этого a(было 5) затрется значением b(6) И будет а = 6, b = 6
Pavel
Уровень 23
20 ноября 2021, 19:43
Объясните, пожалуйста, почему в методе ageSwap(Student a, Student b) к возрасту мы обращаемся через a.age, а не можем обратиться через переменную olga.age?
Dmitriy
Уровень 28
29 ноября 2021, 07:02
Мы обращаемся через a.age потому что передали переменной 'a' ссылку на объект Student (на который ссылается переменная 'olga') т.е. переменные 'olga' и 'a' имеют одну и ту же ссылку на один и тот же объект Student во время выполнения кода Насчёт того, почему не можем обратиться через olga.age ... вообще это возможно ... было бы, но из-за того, что переменная olga объявлена в методе main(), а не на более глобальном уровне - к ней нет доступа из метода ageSwap() ... нет доступа именно к переменной olga т.к. она в main(), а main() и ageSwap() находятся на одном уровне
Алёна Жу
Уровень 37
29 ноября 2021, 15:48
Потому что при создании метода ageSwap мы создаем шаблон с аргументами. В данном случае аргументами являются как раз a и b, принадлежащие к классу Student: ageSwap(Student a, Student b). А уже при вызове этого метода в методе main, мы в качестве аргументов задаем не (Student a, Student b), а (olga, vera) - то есть уже реальные объекты, но метод считает по своему абстрактному шаблону.
Maria Volkova
Уровень 3
18 сентября 2021, 05:38
Так классы внутри других классов ещё можно объявлять? Круто! (цит.) - Шановни, а где в последнем примере объявляется класс в классе? Кто это четко видит?)
Masha Frolova учу java
18 сентября 2021, 10:55
static class Student внутри public class Primitives видно же по скобкам)
Maria Volkova
Уровень 3
23 сентября 2021, 08:01
Я думала, здесь объявление класса в методе ageSwap(
FuzzyDIK
Уровень 3
28 сентября 2021, 11:18
В последней задаче предыдущей лекции класcы Cat, Dog, Fish и Woman вполне себе определены внутри public class Solution