Полагаю, я понимаю, о чем вы спрашиваете. Хотя вы говорите, что хотите «вернуть» его (по сути) из метода выборки, достаточно сказать, что вы просто хотите использовать значение, полученное после завершения выборки. Если это так, это то, что вам нужно сделать:
. После того, как ваша выборка завершится успешно, вы можете делать много вещей с переменной. 4а и 4b - некоторые простые примеры:
4a. Изменить. В качестве примера использования вы можете запустить все, что вам нужно для запуска в вашем классе, который использует yourNameVariable
(и вы можете быть уверены, что yourNameVariable
не является нулевым)
4b. Изменить: в качестве примера использования вы можете использовать переменную в функции, которая запускается кнопкой onClickListener.
Попробуйте это.
// 1. Create a variable at the top of your class
private String yourNameVariable;
// 2. Retrieve your value (which you have done mostly correctly)
private void getUserName(String uid) {
databaseReference.child(String.format("users/%s/name", uid))
.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
// 3. Set the public variable in your class equal to value retrieved
yourNameVariable = dataSnapshot.getValue(String.class);
// 4a. EDIT: now that your fetch succeeded, you can trigger whatever else you need to run in your class that uses `yourNameVariable`, and you can be sure `yourNameVariable` is not null.
sayHiToMe();
}
@Override
public void onCancelled(DatabaseError databaseError) {}
});
}
// (part of step 4a)
public void sayHiToMe() {
Log.d(TAG, "hi there, " + yourNameVariable);
}
// 4b. use the variable in a function triggered by the onClickListener of a button.
public void helloButtonWasPressed() {
if (yourNameVariable != null) {
Log.d(TAG, "hi there, " + yourNameVariable);
}
}
Затем вы может использовать yourNameVariable
, где бы вы ни захотели на протяжении всего вашего класса.
Примечание: просто убедитесь, что вы проверяете, что yourNameVariable
не является нулевым при его использовании, поскольку onDataChange
является асинхронным и может не завершиться в то время, когда вы пытаетесь использовать его в другом месте.
Я попробовал следующее объяснение, но не уверен, является ли это «правильным» объяснением.
blockquote>Не совсем, но он несколько близок.
blockquote>
t
содержит адресA[0]
, но посколькуA
является массивом, аA[0]
является указателем на массив
A[0]
является массивом , в частности, его тип -int[4]
.(который является «не совсем» указателем), C не выделяет память для указателя
blockquote>A
илиA[0]
специально НЕОБХОДИМО другие переменные указателя.Массивы и указатели представляют собой принципиально разные типы объектов. Не путайте их.
Тот факт, что в большинстве случаев выражение типа
array of T
преобразуется в значение типаpointer to T
(указывающее на первый элемент массива), несомненно, способствует путанице, но нельзя забывать, что это преобразование . В частности, для многомерных массивов или массивов массивов тип элемента массива сам по себе является типом массива, поэтому результат преобразования является указателем на массив.It выделяет память только для массива в целом. Таким образом, адрес
blockquote>A[0]
иA[0]
(который является адресомA[0][0]
), по сути, один и тот же,Нет, они существенно отличаются друг от друга, один -
A[0]
- это массив,int[4]
, другой -&A[0]
- указатель на массив из четырехint
,int(*)[4]
. Также&A[0][0]
.Но когда
A[0]
преобразуется в указатель на его первый элемент,&A[0][0]
, результирующий адрес обычно совпадает с адресомA[0]
(обычно, a указатель на объект содержит адрес байта с наименьшим адресом, принадлежащим этому объекту, и посколькуA[0]
принадлежит (является частью) объектаA
, тот, у которого самый младший адрес, первый байт, который является частьюA[0]
является первым байтом, который является частьюA
).Итак,
&A[0]
и&A[0][0]
обычно имеют одно и то же представление, но одно -int(*)[4]
, другое - [int*
.оба принадлежат под одной крышей и не являются «отдельными» сущностями. В результате
blockquote>t
в свою очередь косвенно удерживает адресA[0][0]
и*t
, дает значениеA[0][0]
, которое равно 1.Эта часть, кроме несоответствие типа, которое делает разыменование
t
неопределенным поведением более или менее правильным. Формально неопределенное поведение допускает что-либо.На практике, если
sizeof(int) == sizeof(int*)
, разыменованиеt
интерпретируетint
1, который являетсяA[0][0]
в качестве адреса, и если вы печатаете это какint
(еще одно неопределенное поведение), вы получите1
. Еслиsizeof(int*) == 2*sizeof(int)
, как это обычно бывает в 64-битных системах, разыменованиеt
обычно интерпретирует дваint
sA[0][0]
иA[0][1]
вместе как адрес -0x200000001
или0x100000002
в зависимости от того, .
Массивы не являются указателями.
Ну, еще больше ...
Многомерные массивы не являются двойными, тройными и т. д. указатели.
Итак, все, что у вас есть, неверно, ваша программа несколько раз вызывает неопределенное поведение, и вы ничего не можете ожидать.
Учитывая, что массивы смежны в памяти , вы можете переписать свой пример следующим образом:
int A[3][4] = {{1,2,3,4},{5,6,7,8,},{9,10,11,12}};
int *p = &A[0][0];
printf("%d %d %p\n", A[0][0], *p, (void *)p);