Вопрос о выделении памяти?

public static void Main()
        {
            Test t1 = new Test();
}

когда будет, t1 (ссылочная переменная) получит память, во время компиляции или время выполнения.
Я думаю, что это должно быть время выполнения. Но когда я поместил точку останова в Основной метод и Помещенный Часы для t1, это было пустым. Таким образом, это означает, что t1 был в памяти.

Исправьте меня, Если я неправ.

Править: Я слышал, что Статические членские Переменные присвоены во время компиляции.

5
задан Vaibhav Jain 21 January 2010 в 11:53
поделиться

7 ответов

Последовательность - это массив символов. Поскольку это массив, он не может быть примитивом!: -)

-121--1706247-

Это зависит от того, что вы имеете в виду под «primitive»

«Primitive» в Java обычно принимают за «value type». Однако C # имеет ключевое слово последовательностей , которое действует точно так же, как и Последовательность Java, оно просто выделяется редактором по-разному. Они являются псевдонимами для классов System. Последовательность или java.lang. Последовательность . Последовательность не является типом значения ни на одном языке, поэтому таким образом она не является примитивом.

Если под «примитивом» подразумевается встроенный в язык, то последовательность является примитивом. Просто используется заглавная буква. Строковые литералы (в кавычках) автоматически преобразуются в System.String и + используется для конкатенации. Таким образом, они (и Массивы) являются такими же примитивными, как ints, longs и т. д.

Во-первых, что такой Ряд?

Последовательность не является оберткой. Последовательность - это ссылочный тип , а примитивные типы - типы значений . Это означает, что если у вас есть:

int x = 5;
int y = x;

Память x и y оба содержат «5». Но с:

String x = "a";
String y = x;

Память x и y оба содержат указатель на символ «a» (и длину, смещение, указатель ClassInfo и монитор). Последовательности ведут себя как примитив, потому что они незыблемы, поэтому обычно это не проблема, однако если вы, скажем, использовали отражение, чтобы изменить содержимое последовательности ( не делать этого! ), как x, так и y увидят изменение. На самом деле, если у вас есть:

char[] x = "a".toCharArray();
char[] y = x;
x[0] = 'b';
System.out.println(y[0] == 'b'); // prints "true"

Так что не просто использовать char [] (если это не поведение вы хотите, или вы действительно пытаетесь уменьшить использование памяти).

Каждый объект является ссылочным типом - это означает все записываемые классы, каждый класс в структуре и даже массивы. Единственными вещами, которые являются ценностными типами, являются простые числовые типы (int, long, short, byte, float, double, char, bool и т. д.)

Почему последовательность не может изменяться как char []?

Для этого есть несколько причин, но в основном это сводится к психологии и деталям реализации:

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

Почему у нас нет версии последовательности типа value?

В основном, данные о производительности и реализации,а также сложность наличия 2 различных типов последовательностей. Другие типы значений имеют фиксированный объем памяти. Int - это всегда 32 бит, long - это всегда 64 бит, bool - это всегда 1 бит и т. д. 2 Помимо прочего, это означает, что они могут храниться в стеке, так что все параметры функции живут в одном месте. Кроме того, создание гигантских копий последовательностей по всему месту может убить производительность.

См. также: Почему в C # последовательность является ссылочным типом, который ведет себя как тип значения? . Относится к .NET, но это так же применимо в Java.

1 - В C/C + + и других самокомпилируемых языках это верно, потому что они помещаются в сегмент кода процесса, который ОС обычно останавливает редактирование. В Java это на самом деле обычно не соответствует действительности, так как JVM загружает файлы классов в кучу, чтобы там можно было редактировать последовательность. Однако нет причин, по которым Java-программа не может быть скомпилирована (есть инструменты, которые делают это), и некоторые архитектуры (особенно некоторые версии ARM) выполняют непосредственно байт-код Java.

2 - На практике некоторые из этих типов имеют различный размер на уровне машины. E.x. буллы хранятся в стеке как WORD-size (32 бита на x86, 64 бита на x64). В классах/массивах они могут обрабатываться по-разному. Это все детали реализации, которые остались до JVM - спецификация говорит, что булы являются либо истинными, либо ложными, и машина может выяснить, как это сделать.

-121--1706242-

Ссылка t1 назначается в стеке метода Main - присвоенное ей значение (т.е. часть «new Test ()») назначается в куче во время выполнения - поэтому переменная t1 существует до выполнения этой строки и имеет значение null.

3
ответ дан 18 December 2019 в 11:56
поделиться

Память выделяется только во время выполнения (во время компиляции Ваше приложение не работает).

Во время выполнения ваша T1 переменная будет иметь значение только (то есть не NULL после того, как присвоение произошло, так что это зависит от того, где вы помещаете точку останова. Если вы поместите свою точку останова на закрывающуюся скобу вашего метода Main и проверьте окно часов, когда он ударит, вы увидите, что я имею в виду.

I.e. Если вы поместите свою точку останова на строку назначения TEST1 T1 = NEW TEST1 (); , то эта линия еще не выполнена, поэтому назначение не произошло.

5
ответ дан 18 December 2019 в 11:56
поделиться
Test t1;

Эта часть выделяет достаточно места только для ссылки (вероятно, 4 байта во многих случаях, но я думаю, что это действительно зависит от реализации .NET Framework), и определяется при компиляционном времени и выделено (я думаю), когда называется Main Отказ

t1 = new Test();

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

Редактировать: Чтобы ответить на ваше редактирование, статические переменные элемента разные, и ваша локальная переменная ведет себя по-разному, чем они. Тем не менее, я не верю, что статические переменные участника выделяются при компиляционном времени. Я думаю, что они выделяются, когда тип, содержащий их, загружен (который, кажется, когда вызывается любая функция, которая относится к типу).

class Test2
{
   public static Test f1 = new Test();
}

Этот код создаст новый экземпляр теста, как только функция, которая содержит любую ссылку на Type Test2.

2
ответ дан 18 December 2019 в 11:56
поделиться

в начале «основного», память кучи для экземпляра не была выделена Тем не менее (и не будет до нового теста () ). Он останется выделенным до тех пор, пока не собирается мусор.

Локальная переменная, Test T1 (на основе стека), что будет ссылаться на память кучи (и существует в течение всего времени, что «главное» выполняется).

Оба из них являются заданиями времени выполнения, но различаются с точки зрения того, где находится память, и для того, как долго.

Статические поля выделяются при нагрузках типа (и инициализированы некоторое время между первым использованием типа).

С помощью «Compile Time» я не уверен, что вы относитесь к JIT Compile - но в зависимости от того, что память выделяется отдельно от компиляции.

2
ответ дан 18 December 2019 в 11:56
поделиться

Вы должны быть в состоянии понять это одно самостоятельно. Просто подумайте об этом:

  • , когда вы распределите память, вы «используете» память для чего-то.
  • Программа, которая не работает, не использует память.
  • Программа, которую работает , использует память.
  • Во время выполнения означает, что программа работает.
  • используется память, выделенная во время выполнения.

Выделение компиляции памяти - просто не имеет никакого смысла ...

1
ответ дан 18 December 2019 в 11:56
поделиться

Нет, это означает, что T1 еще не назначен. После того, как вы позвоните в новый тест T1 () T1, будет выделено память для хранения размера объекта , и присваивается адрес памяти.

Да память выделяется только во время выполнения.

1
ответ дан 18 December 2019 в 11:56
поделиться

Ссылка t1 назначается в стеке метода Main - присвоенное ей значение (т.е. часть «new Test ()») назначается в куче во время выполнения - поэтому переменная t1 существует до выполнения этой строки и имеет значение null.

-121--4648512-

В окнах необходимо получить доступ к идентификатору необработанного устройства в виде файла. Он должен работать, если вы передаете файл «\\.\c: », вы используете UNC-имя устройства\.\c: (\. означает эту машину).

Для Vista и более поздних версий я не думаю, что это будет работать правильно, так как существуют механизмы для предотвращения необработанного доступа к диску для чего-либо, кроме драйверов устройств (не цитируйте меня на этом)

-121--2313435-

запустить приложение в режиме отладки, F5 в основном является сочетанием клавиш в Visual Studio. Установите точку останова в этом заявлении. Используйте F10 для перехода к следующей инструкции. Как только отладчик выполнит следующую инструкцию, вы увидите создаваемый объект.

0
ответ дан 18 December 2019 в 11:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: