Есть ли в Java указатели? - PullRequest
       65

Есть ли в Java указатели?

54 голосов
/ 13 апреля 2010

Если в Java нет указателей, то что делает ключевое слово new в Java?

Ответы [ 12 ]

47 голосов
/ 13 апреля 2010

Как указывалось, Java имеет ссылки. Чем они отличаются?

  1. вы не можете выполнять арифметические или другие подобные операции с этими
  2. они не указывают на память, содержащую объект (т.е. они не являются указателями на другое имя). JVM может перемещать объекты в памяти виртуальной машины и, скорее всего, будет делать это во время сборки мусора. Ссылки, тем не менее, все еще указывают на этот объект, несмотря на его движение в памяти.

Так что они не похожи на ссылки C ++ (указывающие непосредственно на объект). Возможно, лучшим именем будет handle .

37 голосов
/ 13 апреля 2010

Java не имеет указателей; У Java есть ссылки.

Это замечательно, но у указателя есть дополнительные операции, которые вы можете (или не можете) обычно использовать; в ссылке отсутствуют эти операции, поскольку операции могут быть небезопасными.

Например, если вы используете указатель для индексации первого элемента массива, например:

int squares[] = {1, 4, 9, 16, 25, 36, 49};
int* intPointer = squares;

вы можете разыменовать указатель и получить значение «1», но вы также можете:

intPointer++

и после этого при разыменовании указателя вы получите значение «4». Второй

intPointer++;

при разыменовании даст вам значение "9". Это связано с тем, что операция ++ перемещает указатель на одну единицу вперед в памяти.

Проблема связана с недостатками системы проверки типов C / C ++ (C ++ должен поддерживать совместимость с C, поэтому допускает те же проблемы). Указатель хранит адрес в памяти, а операция ++ добавляет соответствующее количество байтов к адресу. Во многих системах ++ использование int добавляет четыре байта, но если указатель был указателем char ++, то он должен добавлять только один байт. Обратите внимание, что поскольку базовый тип данных указателя является адресом в памяти, допустимо следующее (но не рекомендуется):

char* charPointer = squares;
charPointer++;

void* voidPointer = squares;
voidPointer++;

Поскольку указатели являются адресами в памяти, они могут (правильно) представлять любой бит памяти в компьютере, но на них должным образом разыменовываются, только когда базовые данные соответствуют типу и выравниванию указателя. Для указателей, которые не управляются большим количеством кода для обеспечения их безопасности, это означает, что вы можете отклониться от типа данных (или выравнивания) требуемой информации, и разыменование может закончиться катастрофой. Попытка исправить эту проблему с помощью пользовательского кода имеет тенденцию настолько сильно тормозить работу одного указателя, что вы замечаете проблемы с производительностью, и это открывает двери для добавления ошибок в пользовательский код «управления указателями».

Сторона Java решает все эти проблемы, возвращая ссылку. Ссылка не ссылается на какое-либо место в памяти; Java поддерживает внутреннюю таблицу «ссылка на указатель». Эта таблица берет ссылку и возвращает данные, связанные с ней, где бы эти данные не находились в памяти. Это замедляет выполнение кода, поскольку для каждой «разыменования» выполняется два поиска, один поиск в справочной таблице, другой в памяти машины.

Большим преимуществом использования ссылок на Java является то, что память можно перемещать, не нарушая адреса потенциальных указателей. В программе на Си, если вы перемещаете данные в новое место в памяти, очень трудно узнать, имеет ли какая-либо другая часть программы указатель на данные. Если устаревший указатель будет разыменован после перемещения памяти, программа получит доступ к поврежденным данным, и, как правило, происходит сбой.

Возможность перемещать память в запущенной программе позволяет программам легко перезаписывать память. Любая программа, которая не нуждается в порциях памяти, может освободить неиспользуемую память, но это создает дыры в памяти неиспользуемой памяти между порциями используемой памяти. Внутренне компьютеры используют страницы памяти, которые довольно велики. Если на редко используемой странице памяти могут быть перемещены несколько использованных битов на другую страницу, то страница памяти может быть освобождена. Это увеличивает плотность данных в памяти, улучшая производительность кеша. Иногда это приводит к улучшению производительности, которое может быть весьма значительным.

Сборщик мусора в Java использует преимущества ссылок, временно блокируя доступ к данным для набора ссылок. Во время этой блокировки доступа он перемещает данные (для их сжатия). После блокировки ссылка на таблицу адресов имеет новые адреса памяти. Поскольку «функциональный» слой кода никогда не знал адресов в первую очередь, эта операция не сломает работающую Java-программу.

12 голосов
/ 13 апреля 2010

Java имеет указатели в смысле переменных, которые хранят ссылки на данные в памяти. В этом смысле все переменные типов объектов в Java являются указателями.

Однако язык Java не допускает арифметических операций со значениями указателей, как вы могли бы делать на языке, подобном C.

7 голосов
/ 13 апреля 2010

new делает (примерно) следующее:

  1. Найдите непрерывный свободный блок памяти кучи, равный размеру экземпляра создаваемого вами класса, плюс некоторое пространство для ведения учета
  2. Обнулите указанное место и удалите его из списка свободных
  3. Запустить конструктор
  4. Возвращает ссылку (НЕ указатель, как объяснили другие посты) на созданный экземпляр.
3 голосов
/ 14 августа 2016

Java имеет указатели, которые известны под именем " reference ".

Когда люди говорят «Java не имеет указателей», они обычно путают концепцию указателя с конкретной реализацией и возможностями указателей, найденными в языках, производных от C и C.

В частности:

  • Java-ссылки не могут быть установлены на произвольный адрес . Не могут (стандартные) указатели Паскаля и Фортрана.
  • Java-ссылки не могут указывать на переменную . Также не могут (стандартные) указатели Паскаля.
  • Java-ссылки не поддерживают арифметику указателей . Ни Паскаль, ни Фортран указатели
  • Java-ссылки не могут указывать на части объекта (подобно третьему элементу массива). Также не могут указатели Паскаля.

Кроме того, вопреки распространенному мнению, указатель - это , не обязательно адрес . Указатель обычно реализуется как адрес, но это не требуется, даже в C или C ++.

3 голосов
/ 13 июня 2013

java.lang.NullPointerException

Люди говорили мне "что у java нет указателей" в интервью. Я обычно давал им некоторый код Java и позволял им объяснить, что происходит в этом коде:

public class TestPointers {

    public static void main(String args[]) {
        Object p1, p2;
        p1 = new Object();
        p2 = p1;
        p1 = null;
        System.out.println(p2);
    }
}
1 голос
/ 13 апреля 2010

Java имеет ссылки. Все объекты доступны через ссылки на их экземпляры. Вы создаете новый экземпляр, используя new, который возвращает ссылку на объект.

Ссылки на Java не похожи на указатели в C, вы не можете «заглянуть за уши» в необработанную память, составляющую объект.

0 голосов
/ 23 апреля 2016

Java не поддерживает и не разрешает указатели. (Или, точнее, Java не поддерживает указатели, которые могут быть доступны и / или изменены программистом.) Java не может разрешать указатели, потому что это позволит апплетам Java нарушать межсетевой экран между средой исполнения Java и хост-компьютером. (Помните, что указателю можно дать любой адрес в памяти - даже адреса, которые могут находиться за пределами системы времени исполнения Java.)

0 голосов
/ 13 апреля 2010

В Java мы встречаем определенные ключевые слова, которые используются в качестве ссылки, например, this ключевое слово используется для ссылки на переменные того же класса. Оператор new используется как ссылка на объект.

0 голосов
/ 13 апреля 2010

Java не имеет указателей. Оператор "new" используется для ссылки на переменную в Java.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...