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

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

Java Syntax
2 уровень , 6 лекция
Открыта

— Привет, Амиго, это снова я – Элли. Прости, что постоянно так говорю, так просто принято на Земле в 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, 2 уровень, 6 лекция
Недоступна
Логотип решает все
Логотип решает все
2
Задача
Java Syntax Pro, 2 уровень, 6 лекция
Недоступна
Пустота и пробелы
Пустота и пробелы
2
Задача
Java Syntax Pro, 2 уровень, 6 лекция
Недоступна
Конкатенация строк и чисел
Конкатенация строк и чисел
2
Задача
Java Syntax Pro, 2 уровень, 6 лекция
Недоступна
С каждым разом огромнее
С каждым разом огромнее
2
Задача
Java Syntax Pro, 2 уровень, 6 лекция
Недоступна
Получаем длину строки
Получаем длину строки
2
Задача
Java Syntax Pro, 2 уровень, 6 лекция
Недоступна
Причешем резюме
Причешем резюме
2
Задача
Java Syntax Pro, 2 уровень, 6 лекция
Недоступна
Попрошу регистр на меня не повышать!
Попрошу регистр на меня не повышать!
Комментарии (503)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Кэрривайт Уровень 25
16 февраля 2026
swap - это Collections.swap() — метод класса java.util.Collections в Java, который меняет местами элементы на двух указанных позициях в списке.
vlafriday Уровень 1
11 февраля 2024
11.02.2024 check, мой уровень 2
nescafe Уровень 30
17 июня 2023
Уважаемые обучающиеся, добрый день! Решил показать свой взгляд на тему - примитивы хранят в себе значение, а ссылочные объекты - только ссылку. Возможно моё "объяснение" кому то да поможет)

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 Уровень 1
25 июля 2022
Сдаётся мне, что классы

class Primitives
и

class References
нужно переименовать один на другого.
Сергей Уровень 2
22 января 2022
Все же не все понятно с переменными ссылочного типа, напишу свои рассуждения и прошу тех кто знает поправить и подсказать: Пример

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
1. Когда мы объявляем объект, но не создаем, то вместо ссылки будет null. 2. Jvm выделяет память исходя из переменных. Int=16, long=32. Так как любой класс состоит из полей и методов, то при объявлении нового экземпляра класса, учитывая какие переменные и каких типов будут внутри,выделяется память. 3. Cat cat=null;
SkyGod Уровень 26
30 марта 2022
По все видимости, при создании Cat cat = new Cat() Java выделит память объекту и будет хранить пустым это место в памяти, пока жива ссылка на объект, а при создании просто Cat cat Java удалит ссылку на этот объект сразу после создания, если я правильно все понимаю.
Benjam1nBTN Уровень 24
25 июля 2022
Если мы пишем просто "Cat murzik;", то murzik хранит ссылку в никуда (null), для этого в памяти выделяется 4 бита (размер для ссылки). Вроде так, насколько я понял
Александр Уровень 3
9 января 2022
Ребят, поясните , зачем мы создаем Тип переменной свой. Cat cat = new Cat(); Есть типы, int, string и так далее. Зачем придумываем свой тип? Когда нам это понадобится? От этих кат кат кат голова кругом.
Alexey Уровень 15
13 января 2022
Везде, на одних примитивах далеко не уедешь)
Денис Уровень 3
1 февраля 2022
Почитай историю программирования, как пришли к ООП, спойлер, не от хорошей жизни. Сначала и переменных не было - машинных кодов хватало, программы становились сложнее и сложнее и пришлось применять код ассемблер, потом процедурные языки, но и они не справлялись, так и дошли до ООП с их Классами, позволяющими создавать бесконечное множество новых ссылочных типов данных.
Mr. Hat Уровень 9
9 февраля 2022
Попробую объяснить, как понял я строчку Cat Kot = new Cat();: Здесь левая часть это похоже на объявление пустой переменной как int Chislo, String Stroka. После этого переменным будет автоматически присвоено значение по-умолчанию. Chislo - 0, Stroka - ""(ни одного символа), а переменная Kot будет содержать Null (значение по-умолчанию для объектов) Правая сторона как раз и создание объекта(со всеми переменными которые ты в нем перечисляешь) и его нужно сразу куда-то закинуть, иначе останется нигде, и обратиться к нему не сможешь уже. Поэтому сразу создал и присвоил. А то что в курсе тавтология - это действительно смущает. Насчет зачем свой тип - потому что ты захочешь создать свой сложный объект который будет хранить больше чем 1 вид переменных(контакт например должен содержать телефон и имя), а такого типа еще нет в языке, и придется создавать свой.
Eugene Shoo Уровень 4
23 декабря 2021
ребят, еще такой момен, понимаю что дальше не пойду без понимания этой строки... объясните пожалуйста... Cat cat = new Cat; за что отвеяает каждое из трех написанных Саt cat Cat. Сори за ленивый вопрос, закипаю уже =/
vitek987 Уровень 6
24 декабря 2021
В задании лекции 2 было описано: ТипПеременной имяПеременной = new ТипСоздаваемогоОбъекта(); Cat cat Cat
Eugene Shoo Уровень 4
24 декабря 2021
спасибо
Дмитрий Уровень 5
6 сентября 2022
Я не могу понять почему они в примере не могли имя переменной написать не cat а хотя бы Vasya, везде эти cat только в заблуждение лично меня вводят
Артем Уровень 9
13 января 2023
Тоже долго над этим думал и вот к чему пришел. Cat cat, потому, что класс Cat создает котов, то есть cat. У каждого кота может быть свое имя, возраст, вес и т.д. Причем в момент создания этого объекта, эти значения могут быть неизвестны, а появятся позже. Если же назвать объект vasya (причем по правилам именно с маленькой буквы, но это другая тема), то во-первых, как минимум имя этого кота будет уже не изменить, во-вторых никуда его не передать, а в-третьих если где-то в коде встретить vasya, то с ходу не понять, это кот, пес, или его хозяин) А когда видишь cat, cat1, cat2 то уже понятнее)
Eugene Shoo Уровень 4
22 декабря 2021
a = m(5), b = n(6). а = b. 5 = 6??? как???
Mr. Hat Уровень 9
9 февраля 2022
Не понятный вопрос.

a = m(5), b = n(6). 
Это присвоение, а не сравнение

 а = b.
После этого a(было 5) затрется значением b(6) И будет а = 6, b = 6
Pavel Уровень 23
20 ноября 2021
Объясните, пожалуйста, почему в методе ageSwap(Student a, Student b) к возрасту мы обращаемся через a.age, а не можем обратиться через переменную olga.age?
Dmitriy Уровень 28
29 ноября 2021
Мы обращаемся через a.age потому что передали переменной 'a' ссылку на объект Student (на который ссылается переменная 'olga') т.е. переменные 'olga' и 'a' имеют одну и ту же ссылку на один и тот же объект Student во время выполнения кода Насчёт того, почему не можем обратиться через olga.age ... вообще это возможно ... было бы, но из-за того, что переменная olga объявлена в методе main(), а не на более глобальном уровне - к ней нет доступа из метода ageSwap() ... нет доступа именно к переменной olga т.к. она в main(), а main() и ageSwap() находятся на одном уровне
Алёна Жу Уровень 37
29 ноября 2021
Потому что при создании метода ageSwap мы создаем шаблон с аргументами. В данном случае аргументами являются как раз a и b, принадлежащие к классу Student: ageSwap(Student a, Student b). А уже при вызове этого метода в методе main, мы в качестве аргументов задаем не (Student a, Student b), а (olga, vera) - то есть уже реальные объекты, но метод считает по своему абстрактному шаблону.
Maria Volkova Уровень 3
18 сентября 2021
Так классы внутри других классов ещё можно объявлять? Круто! (цит.) - Шановни, а где в последнем примере объявляется класс в классе? Кто это четко видит?)
Masha Frolova Уровень 22
18 сентября 2021
static class Student внутри public class Primitives видно же по скобкам)
Maria Volkova Уровень 3
23 сентября 2021
Я думала, здесь объявление класса в методе ageSwap(
FuzzyDIK Уровень 3
28 сентября 2021
В последней задаче предыдущей лекции класcы Cat, Dog, Fish и Woman вполне себе определены внутри public class Solution