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 лекция
Недоступна
Логотип решает все
В переменную tagline нужно записать строку "JustDoIt". Используй s1, s2, s3 и конкатенацию строк.
2
Задача
Java Syntax Pro, 2 уровень, 6 лекция
Недоступна
Пустота и пробелы
Заполни пробелы пустотой... или наоборот. Используй переменную emptiness, строки с одним пробелом и конкатенацию строк, чтобы записать в переменную fullness строку "пустота пустота пустота".
2
Задача
Java Syntax Pro, 2 уровень, 6 лекция
Недоступна
Конкатенация строк и чисел
В переменную digits нужно записать строку "60". Используй переменные x, y, z, пустую строку и конкатенацию строк.
2
Задача
Java Syntax Pro, 2 уровень, 6 лекция
Недоступна
С каждым разом огромнее
В переменную hugeAmount нужно записать число 100500. Используй переменные bigAmount, greatAmount и преобразование строки в число. Для объявления и инициализации hugeAmount используй одну команду.
2
Задача
Java Syntax Pro, 2 уровень, 6 лекция
Недоступна
Получение длины строки
В методе main на экран выводятся значения трех строк. Внеси изменения в код, чтобы вместо значений строк, вывелись их длины.
2
Задача
Java Syntax Pro, 2 уровень, 6 лекция
Недоступна
Причешем резюме
Метод main выводит на экран четыре строки. Все они - яркий пример злоупотребления заглавными буквами. Внеси изменения в код, чтобы все буквы в этих строках стали строчными.
2
Задача
Java Syntax Pro, 2 уровень, 6 лекция
Недоступна
Попрошу регистр на меня не повышать!
В методе main на экран выводятся три строки. Внеси изменения в код, чтобы все буквы в этих строках стали заглавными.
Комментарии (502)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
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
Ян Уровень 24
9 сентября 2021
И я немного запутался. Хотя вроде знал про это в общих чертах. В общем примитивы передают значения, их значения копируются и эти копии автономно используются, источник сам не затронут - всё, они отделились друг от друга. В случае с ссылочными типами передаётся пульт управления, как бы сам источник, даже если источник присвоен другой ссылочной переменной (другая и источник ведут к одной и тоже области памяти), поэтому когда Другая переменная ссылочная указывает на тот же Источник, а затем Другая что-то меняет в полях, то это меняется и у Источника. Так как они указывают на одно и тоже в памяти. Два пульта управляют одним и тем же. Если второй пульт меняет это что-то, то само собой и первый пульт указывающий на этот объект отобразит, что объект изменился тот на который указывают оба этих пульта (ссылочные переменные). В С++ вот есть и по значению передача. по ссылке, указатели.