Что происходит с программой, когда при присвоении значения переменной используется сразу несколько методов?

Есть строки кода (никак не связанные между собой):

mCrime = CrimeLab.get(getActivity()).getCrime(crimeId); 

UUID crimeId = (UUID) getIntent().getSerializableExtra(EXTRA_CRIME_ID);

fm.beginTransaction().add(R.id.fragment_container, fragment).commit();

Насколько я понимаю, данные строки являются компактным вариантом присвоения значения переменной. Но, мне не всегда понятно, что именно происходит в коде, при таких записях, почему методы вызываются именно в этой последовательности. И, главное, как бы это было записано в некомпактном виде?


Ответы (1 шт):

Автор решения: Alex_Skvortsov

Первые две строки действительно выполняют присвоение (хотя я не очень понял, почему Вы назвали его компактным).

В третьей строке нет присвоения.

Подробнее:

mCrime = CrimeLab.get(getActivity()).getCrime(crimeId);

Можно развернуть, как:

Activity activity = getActivity();
CrimeLab crimeLab = CrimeLab.get(activity);
mCrime = crimeLab.getCrime(crimeId);

То есть сначала на основе Activity конструируется объект класса CrimeLab, затем из этого объекта получается объект класса Crime через метод getCrime, который уже в свою очередь присваивается в переменную mCrime.

Теперь вторая из Ваших строк:

UUID crimeId = (UUID) getIntent().getSerializableExtra(EXTRA_CRIME_ID);

Её можно разбить так:

Intent i = getIntent(); //получаем интент
Object id = i.getSerializableExtra(EXTRA_CRIME_ID); //получаем id без указания типа
UUID crimeId = (UUID) id; //приводим тип и сохраняем в crimeId 

То есть и в первой и во второй строке действительно происходит присвоение, но, так как Вам нужен только конечный объект и не нужны промежуточные, то им (промежуточным объектам) не задаются имена, они нигде не сохраняются.

Во второй строке присвоения нет.

fm.beginTransaction().add(R.id.fragment_container, fragment).commit();

Так же детальный разбор:

FragmentTransaction transaction = fm.beginTransaction(); //создать транзакцию
transaction.add(R.id.fragment_container, fragment); //добавить действие в транзакцию
transaction.commit(); //запустить транзакцию

Если переписать Вашу третью строку так, как я сделал выше, то присвоение действительно будет (и оно будет в bytecode). Однако, Вам нет необходимости хранить объект транзакции, Вам нужно создать её и сразу запустить.

Методы, очевидно, вызываются в порядке слева-направо и сверху-вниз. То есть Вашу третью строку, например, можно переписать ещё и так:

fm
.beginTransaction()
.add(R.id.fragment_container, fragment)
.commit();

Форма записи в кратком виде является более удобной и короткой, потому (обычно) используют именно ее. При создании bytecode всё будет выглядеть так же, как если бы Вы написали все присвоения.

И ещё по поводу порядка вызовов методов! Из правила слева-направо, сверху-вниз есть небольшое исключение:

mCrime = CrimeLab.get(getActivity()).getCrime(crimeId);

Конкретно здесь сначала будет вызван метод getActivity, а уже потом CrimeLab.get. В действительности перед вызовом метода проверяются его параметры. Если среди них есть метод (1) (вместо переменной), то сначала вызовутся все методы для получения параметров, а уже потом сам метод (1)

→ Ссылка