Все объекты в Java являются ссылками, и вы можете использовать их как указатели.
abstract class Animal
{...
}
class Lion extends Animal
{...
}
class Tiger extends Animal
{
public Tiger() {...}
public void growl(){...}
}
Tiger first = null;
Tiger second = new Tiger();
Tiger third;
Разыменование нулевого значения:
first.growl(); // ERROR, first is null.
third.growl(); // ERROR, third has not been initialized.
Проблема алиасинга:
third = new Tiger();
first = third;
Проигрышные клетки:
second = third; // Possible ERROR. The old value of second is lost.
Вы можете сделать это безопасно, сначала убедившись, что больше нет необходимости в старом значении секунды, или назначив другому указателю значение секунды.
first = second;
second = third; //OK
Обратите внимание, что присвоение секунде значения другими способами (NULL, new ...) является такой же потенциальной ошибкой и может привести к потере объекта, на который она указывает.
Система Java выдает исключение (OutOfMemoryError
), когда вы вызываете new, и распределитель не может выделить запрошенную ячейку. Это очень редко и обычно является результатом рекурсии бегства.
Обратите внимание, что с языковой точки зрения отказ от объектов в сборщике мусора вовсе не является ошибкой. Это просто то, что программист должен знать. Одна и та же переменная может указывать на разные объекты в разное время, и старые значения будут возвращены, когда на них не ссылается ни один указатель. Но если логика программы требует сохранения хотя бы одной ссылки на объект, это вызовет ошибку.
Новички часто делают следующую ошибку.
Tiger tony = new Tiger();
tony = third; // Error, the new object allocated above is reclaimed.
То, что вы, вероятно, хотели сказать, было:
Tiger tony = null;
tony = third; // OK.
Неправильный кастинг:
Lion leo = new Lion();
Tiger tony = (Tiger)leo; // Always illegal and caught by compiler.
Animal whatever = new Lion(); // Legal.
Tiger tony = (Tiger)whatever; // Illegal, just as in previous example.
Lion leo = (Lion)whatever; // Legal, object whatever really is a Lion.
Указатели в C:
void main() {
int* x; // Allocate the pointers x and y
int* y; // (but not the pointees)
x = malloc(sizeof(int)); // Allocate an int pointee,
// and set x to point to it
*x = 42; // Dereference x to store 42 in its pointee
*y = 13; // CRASH -- y does not have a pointee yet
y = x; // Pointer assignment sets y to point to x's pointee
*y = 13; // Dereference y to store 13 in its (shared) pointee
}
Указатели на Java:
class IntObj {
public int value;
}
public class Binky() {
public static void main(String[] args) {
IntObj x; // Allocate the pointers x and y
IntObj y; // (but not the IntObj pointees)
x = new IntObj(); // Allocate an IntObj pointee
// and set x to point to it
x.value = 42; // Dereference x to store 42 in its pointee
y.value = 13; // CRASH -- y does not have a pointee yet
y = x; // Pointer assignment sets y to point to x's pointee
y.value = 13; // Deference y to store 13 in its (shared) pointee
}
}
ОБНОВЛЕНИЕ: , как предлагается в комментариях, следует отметить, что C имеет арифметику указателей. Однако в Java этого нет.