Когда вы объявляете ссылочную переменную (т. е. объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа int
:
int x;
x = 10;
В этом примере переменная x является int
, и Java инициализирует ее для 0. Когда вы назначаете его 10 во второй строке, ваше значение 10 записывается в ячейку памяти, на которую указывает x.
Но когда вы пытаетесь объявить ссылочный тип, произойдет что-то другое. Возьмите следующий код:
Integer num;
num = new Integer(10);
Первая строка объявляет переменную с именем num
, но она не содержит примитивного значения. Вместо этого он содержит указатель (потому что тип Integer
является ссылочным типом). Поскольку вы еще не указали, что указать на Java, он устанавливает значение null, что означает «Я ничего не указываю».
Во второй строке ключевое слово new
используется для создания экземпляра (или создания ) объекту типа Integer и переменной указателя num
присваивается этот объект. Теперь вы можете ссылаться на объект, используя оператор разыменования .
(точка).
Exception
, о котором вы просили, возникает, когда вы объявляете переменную, но не создавали объект. Если вы попытаетесь разыменовать num
. Перед созданием объекта вы получите NullPointerException
. В самых тривиальных случаях компилятор поймает проблему и сообщит вам, что «num не может быть инициализирован», но иногда вы пишете код, который непосредственно не создает объект.
Например, вы можете имеют следующий метод:
public void doSomething(SomeObject obj) {
//do something to obj
}
В этом случае вы не создаете объект obj
, скорее предполагая, что он был создан до вызова метода doSomething
. К сожалению, этот метод можно вызвать следующим образом:
doSomething(null);
В этом случае obj
имеет значение null. Если метод предназначен для того, чтобы что-то сделать для переданного объекта, целесообразно бросить NullPointerException
, потому что это ошибка программиста, и программисту понадобится эта информация для целей отладки.
Альтернативно, там могут быть случаи, когда цель метода заключается не только в том, чтобы работать с переданным в объекте, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething
может быть записано как:
/**
* @param obj An optional foo for ____. May be null, in which case
* the result will be ____.
*/
public void doSomething(SomeObject obj) {
if(obj != null) {
//do something
} else {
//do something else
}
}
Наконец, Как определить исключение & amp; причина использования Трассировки стека
В новейших версиях (начиная с бета-версии 3.5.1315.0) вы можете использовать элемент MajorUpgrade вместо своего собственного.
Например, мы используем этот код для автоматического обновления. Он предотвращает понижение версии, выдавая локализованное сообщение об ошибке, а также предотвращает обновление уже существующей идентичной версии (т.е. обновляются только более низкие версии):
<MajorUpgrade
AllowDowngrades="no" DowngradeErrorMessage="!(loc.NewerVersionInstalled)"
AllowSameVersionUpgrades="no"
/>
Наконец я нашел решение - я отправляю его здесь для других людей, у которых могла бы быть та же проблема (все 5 из Вас):
Под продуктом добавляют следующее:
<Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
<Upgrade Id="YOUR_GUID">
<UpgradeVersion
Minimum="1.0.0.0" Maximum="99.0.0.0"
Property="PREVIOUSVERSIONSINSTALLED"
IncludeMinimum="yes" IncludeMaximum="no" />
</Upgrade>
Под InstallExecuteSequence добавьте:
<RemoveExistingProducts Before="InstallInitialize" />
С этого времени каждый раз, когда я устанавливаю продукт, он удалил предыдущие установленные версии.
Примечание: идентификатор обновления замены с Вашим собственным GUID
Элемент Обновления в элементе продукта, объединенном с надлежащим планированием действия, выполнит удаление, которое Вы после. Обязательно перечислите коды обновления всех продуктов, которые Вы хотите удалить.
<Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
<Upgrade Id="00000000-0000-0000-0000-000000000000">
<UpgradeVersion Minimum="1.0.0.0" Maximum="1.0.5.0" Property="PREVIOUSVERSIONSINSTALLED" IncludeMinimum="yes" IncludeMaximum="no" />
</Upgrade>
Примечание, что, если Вы осторожны со своими сборками, можно предотвратить людей от случайной установки более старой версии продукта по более новому. Это - то, для чего поле Maximum. Когда мы создаем установщики, мы устанавливаем Максимум UpgradeVersion на создаваемую версию, но IncludeMaximum = "нет" для предотвращения этого сценария.
у Вас есть выбор относительно планирования RemoveExistingProducts. Я предпочитаю планировать его после InstallFinalize (а не после InstallInitialize, как другие рекомендовали):
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallFinalize"></RemoveExistingProducts>
</InstallExecuteSequence>
Это оставляет предыдущую версию продукта установленной до окончания новых файлов, и ключи реестра копируются. Это позволяет мне переместить данные от старой версии до нового (например, Вы переключили устройство хранения данных пользовательских настроек от реестра до XML-файла, но Вы хотите быть вежливыми и переместить их настройки). Эта миграция сделана в задержанном пользовательском действии незадолго до InstallFinalize.
Другое преимущество является эффективностью: если существуют неизменные файлы, Windows Installer не потрудился копировать их снова, когда Вы планируете после InstallFinalize. Если Вы планируете после InstallInitialize предыдущая версия полностью удалена сначала, и затем новая версия установлена. Это приводит к ненужному удалению и перекопированию файлов.
Для других опций планирования, посмотрите тему справки RemoveExistingProducts в MSDN. На этой неделе ссылка: http://msdn.microsoft.com/en-us/library/aa371197.aspx
Вы могли бы лучше спрашивать это относительно эти WiX-пользовательский список рассылки .
WiX лучше всего используется с твердым пониманием того, что делает Windows Installer. Вы могли бы рассмотреть получение" Полное руководство к Windows Installer ".
действие, которое удаляет существующий продукт, действие RemoveExistingProducts . Поскольку последствия того, что это делает, зависят от того, где это запланировало - а именно, заставляет ли отказ старый продукт быть переустановленным, и копируются ли неизменные файлы снова - необходимо запланировать его сами.
RemoveExistingProducts
процессы <Upgrade>
элементы в текущей установке, соответствуя эти @Id
атрибут к UpgradeCode
(определенный в <Product>
элемент) всех установленных продуктов в системе. Эти UpgradeCode
определяет семью сопутствующих товаров. Будут удалены любые продукты, которые имеют этот UpgradeCode, версии которого попадают в диапазон, определенный, и где эти UpgradeVersion/@OnlyDetect
атрибут no
(или опущен).
документация для RemoveExistingProducts
упоминания, устанавливающие UPGRADINGPRODUCTCODE
свойство. Это означает, что процесс удаления для продукта, удаляемого , получает то свойство, значение которого Product/@Id
для устанавливаемого продукта.
, Если Ваша исходная установка не включала UpgradeCode
, Вы не будете в состоянии использовать эту функцию.
Я использовал этот сайт, чтобы помочь мне понять основы об Обновлении WiX:
http://wix.tramontana.co.hu/tutorial/upgrades-and-modularization
Впоследствии я создал демонстрационный Установщик, (установил тестовый файл), затем создал установщик Обновления (установил 2 демонстрационных тестовых файла). Это даст Вам основное понимание того, как механизм работает.
И поскольку Mike сказал в книге от Apress, "Полное руководство к Windows Installer", это выручит Вас для понимания, но это не записано с помощью WiX.
Другой сайт, который был довольно полезен, был этим:
Следующее является видом синтаксиса, который я использую для значительных обновлений:
<Product Id="*" UpgradeCode="PUT-GUID-HERE" Version="$(var.ProductVersion)">
<Upgrade Id="PUT-GUID-HERE">
<UpgradeVersion OnlyDetect="yes" Minimum="$(var.ProductVersion)" Property="NEWERVERSIONDETECTED" IncludeMinimum="no" />
<UpgradeVersion OnlyDetect="no" Maximum="$(var.ProductVersion)" Property="OLDERVERSIONBEINGUPGRADED" IncludeMaximum="no" />
</Upgrade>
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallInitialize" />
</InstallExecuteSequence>
Как @Brian Gillespie отметил, что существуют другие места для планирования RemoveExistingProducts в зависимости от желаемой оптимизации. Обратите внимание, что PUT-GUID-HERE должен быть идентичным.
Предлагаю взглянуть на учебник Алекса Шевчука. Он объясняет «серьезное обновление» через WiX на хорошем практическом примере в От MSI до WiX, часть 8 - Основное обновление .
Я использую последнюю версию WiX (3.0), и мне не удалось заставить вышеуказанное работать. Но это сработало:
<Product Id="*" UpgradeCode="PUT-GUID-HERE" ... >
<Upgrade Id="PUT-GUID-HERE">
<UpgradeVersion OnlyDetect="no" Property="PREVIOUSFOUND"
Minimum="1.0.0.0" IncludeMinimum="yes"
Maximum="99.0.0.0" IncludeMaximum="no" />
</Upgrade>
Обратите внимание, что PUT-GUID-HERE должен быть таким же, как GUID, который вы определили в свойстве UpgradeCode продукта.