isDefined - это то, как вы будете проверять нулевое значение. В AbstractTemplate у вас есть вызываемый метод isDefined(Object anObject). Проверьте скомпилированные версии jsp и java вашего шаблона isml.
In AbstractШаблон
public Boolean isDefined(Object anObject){
...
return anObject != null ? Boolean.TRUE : Boolean.FALSE;
}
Код в вашем примере немного вводит в заблуждение, он фактически не проверяет нулевую ссылку. Потерпите меня.
Первое утверждение:
<isset name="woot" value="" scope="request">
Компилируется в:
Object temp_obj = ("");
getPipelineDictionary().put("woot", temp_obj);
Это просто устанавливает переменную woot в пустую строку. Если вы добавите следующий скриптлет в свой isml, вы увидите, что он действительно не нулевой.
Отказ от ответственности: не используйте скриптлеты в производственном коде, это только для демонстрации точки зрения
<%
Object woot = getPipelineDictionary().get("woot");
out.print(woot == null); //print false
%>
Вторая линия:
<isif condition="#isDefined(woot)#">
Оценивает, существует ли переменная и существует ли она. В качестве значения он имеет пустую строку, а не null, как вы могли бы подумать.
Так что же происходит здесь тогда?
<isif condition="#woot EQ null#">
Глядя на скомпилированную версию:
context.getFormattedValue(getObject("woot"),null).equals(context.getFormattedValue(getObject("null"),null))
context.getFormattedValue(getObject("null"),null)
здесь важный бит. Он пытается получить переменную с именем null, она не существует, поэтому возвращает null. Затем метод getFormattedValue возвращает пустую строку для нулевого аргумента (см. TemplateExecutionConfig::getFormattedValue). Затем все утверждение становится истинным. Не потому, что woot имеет значение null, а потому, что вы сравниваете его с несуществующей переменной, поэтому вы непреднамеренно оцениваете две пустые строки. Это поведение согласуется с оператором EQ, поскольку он используется для сравнить строки.
Вы бы получили тот же результат, если бы использовали это утверждение.
<isif condition="#woot EQ iDontExistButImAlsoNotNull#"> //true
Третий оператор сравнивает переменную woot с пустым строковым значением, которое возвращает true.
<isif condition="#woot EQ ''#">
Скомпилированная версия:
context.getFormattedValue(getObject("woot"),null).equals(context.getFormattedValue("",null))
Итак, настоящая проблема в том, что woot не имеет буквального значения null. См. следующий код:
<isset name="foo" value="#IDontExitPrettySureAboutThat#" scope="request">
<%
Object foo = getPipelineDictionary().get("foo");
out.print("foo is null? ");
out.print(foo == null);
//prints : foo is null? true
%>
<isif condition="#isDefined(foo)#">
<h1>foo1</h1> //is never printed
</isif>
Я злоупотребляю тем фактом, что IDontExitPrettySureAboutThat
не существует, чтобы установить нулевое значение для foo. Затем isDefined начинает работать так, как вы ожидаете. Это до тех пор, пока кто-то не инициализирует мою переменную чем-то отличным от нуля.
Однако я бы не рекомендовал вам использовать этот метод. Я думаю, что лучший совет — не использовать null для представления отсутствующего значения или недопустимого состояния. В этой ветке подробно рассматриваются некоторые детали этой темы.
person
Willem Evertse
schedule
01.09.2017