Я знаю, что в Java нет указателей, но я слышал, что программы на Java можно создавать с помощью указателей, и что это могут делать немногие специалисты в java. Это правда?
Я знаю, что в Java нет указателей, но я слышал, что программы на Java можно создавать с помощью указателей, и что это могут делать немногие специалисты в java. Это правда?
Ответы:
Все объекты в 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.
Вы можете сделать это безопасным, сначала убедившись, что больше нет необходимости в старом значении second или присвоив другому указателю значение second.
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 этого нет.
В Java есть указатели. Каждый раз, когда вы создаете объект в Java, вы фактически создаете указатель на объект; этот указатель может быть установлен на другой объект или наnull
, а исходный объект все еще будет существовать (ожидающая сборка мусора).
Что вы не можете сделать в Java, так это арифметику указателей. Вы не можете разыменовать конкретный адрес памяти или увеличить указатель.
Если вы действительно хотите получить низкоуровневую работу, единственный способ сделать это - использовать собственный интерфейс Java ; и даже тогда низкоуровневая часть должна быть выполнена на C или C ++.
Поскольку в Java нет типов данных указателя, в Java невозможно использовать указатели. Даже немногие специалисты не смогут использовать указатели в java.
См. Также последний пункт в: Среда языка Java
В Java есть указатели, но вы не можете манипулировать ими так, как в C ++ или C. Когда вы передаете объект, вы передаете указатель на этот объект, но не в том же смысле, как в C ++. Этот объект нельзя разыменовать. Если вы установите его значения с помощью его собственных средств доступа, он изменится, потому что Java знает свое местоположение в памяти через указатель. Но указатель неизменен. Когда вы пытаетесь установить указатель на новое место, вместо этого вы получаете новый локальный объект с тем же именем, что и другой. Исходный объект не изменился. Вот краткая программа, демонстрирующая разницу.
import java.util.*;
import java.lang.*;
import java.io.*;
class Ideone {
public static void main(String[] args) throws java.lang.Exception {
System.out.println("Expected # = 0 1 2 2 1");
Cat c = new Cat();
c.setClaws(0);
System.out.println("Initial value is " + c.getClaws());
// prints 0 obviously
clawsAreOne(c);
System.out.println("Accessor changes value to " + c.getClaws());
// prints 1 because the value 'referenced' by the 'pointer' is changed using an accessor.
makeNewCat(c);
System.out.println("Final value is " + c.getClaws());
// prints 1 because the pointer is not changed to 'kitten'; that would be a reference pass.
}
public static void clawsAreOne(Cat kitty) {
kitty.setClaws(1);
}
public static void makeNewCat(Cat kitty) {
Cat kitten = new Cat();
kitten.setClaws(2);
kitty = kitten;
System.out.println("Value in makeNewCat scope of kitten " + kitten.getClaws());
//Prints 2. the value pointed to by 'kitten' is 2
System.out.println("Value in makeNewcat scope of kitty " + kitty.getClaws());
//Prints 2. The local copy is being used within the scope of this method.
}
}
class Cat {
private int claws;
public void setClaws(int i) {
claws = i;
}
public int getClaws() {
return claws;
}
}
Это можно запустить на Ideone.com.
В Java нет указателей, как в C, но она позволяет вам создавать новые объекты в куче, на которые «ссылаются» переменные. Отсутствие указателей препятствует тому, чтобы программы Java незаконно ссылались на ячейки памяти, а также позволяет виртуальной машине Java автоматически выполнять сборку мусора.
Вы можете использовать адреса и указатели, используя класс Unsafe. Однако, как следует из названия, эти методы НЕ БЕЗОПАСНЫ и вообще плохая идея. Неправильное использование может привести к случайной смерти вашей JVM (на самом деле та же проблема возникает при неправильном использовании указателей в C / C ++)
Хотя вы, возможно, привыкли к указателям и думаете, что они вам нужны (потому что вы не умеете кодировать по-другому), вы обнаружите, что это не так, и вам от этого будет лучше.
Технически все объекты Java являются указателями. Однако все примитивные типы являются значениями. Невозможно вручную контролировать эти указатели. Java просто внутренне использует передачу по ссылке.
Не на самом деле нет.
В Java нет указателей. Если бы вы действительно хотели, вы могли бы попытаться имитировать их, построив что-то вроде отражения, но это будет иметь всю сложность указателей без каких-либо преимуществ .
В Java нет указателей, потому что они ей не нужны. Какие ответы вы надеялись получить от этого вопроса, т.е. в глубине души вы надеялись, что сможете использовать их для чего-то, или это было просто любопытством?
Все объекты в java передаются функциям посредством ссылочной копии, кроме примитивов.
Фактически это означает, что вы отправляете копию указателя на исходный объект, а не копию самого объекта.
Пожалуйста, оставьте комментарий, если вы хотите, чтобы пример понял это.
swap
функцию на Java, которая меняет местами два объекта.
Как говорили другие, короткий ответ - «Нет».
Конечно, вы могли бы написать код JNI, который работает с указателями Java. В зависимости от того, чего вы пытаетесь достичь, возможно, это приведет вас к чему-то, а может и нет.
Вы всегда можете имитировать указатели, создав массив и работая с индексами в массиве. Опять же, в зависимости от того, чего вы пытаетесь достичь, это может быть полезно, а может и нет.
из книги Годфри Нолана "Декомпиляция Android"
Безопасность диктует, что указатели не используются в Java, поэтому хакеры не могут взломать приложение и проникнуть в операционную систему. Отсутствие указателей означает, что что-то еще - в данном случае JVM ---- должно позаботиться о распределении и освобождении памяти. Утечки памяти тоже должны уйти в прошлое, по крайней мере, согласно теории. Некоторые приложения, написанные на C и C ++, печально известны утечкой памяти как решето, потому что программисты не обращают внимания на освобождение нежелательной памяти в нужное время - не то чтобы кто-то, читающий это, был бы виновен в таком грехе. Сборка мусора также должна сделать программистов более продуктивными, с меньшими затратами времени на отладку проблем с памятью.
у вас также могут быть указатели на литералы. Вы должны сами их реализовать. Для знатоков это довольно просто;). Используйте массив int / object / long / byte и вуаля, у вас есть основы для реализации указателей. Теперь любое значение int может быть указателем на этот массив int []. Вы можете увеличить указатель, вы можете уменьшить указатель, вы можете умножить указатель. У вас действительно есть арифметика указателей! Это единственный способ реализовать 1000 классов атрибутов int и иметь общий метод, применимый ко всем атрибутам. Вы также можете использовать массив byte [] вместо int []
Однако я бы хотел, чтобы Java позволяла передавать буквальные значения по ссылке. Что-то в этом роде
//(* telling you it is a pointer)
public void myMethod(int* intValue);
Все объекты java являются указателями, потому что переменная, которая содержит адрес, называется указателем, а объект удерживает адрес. Таким образом, объект является переменной указателя.