Оператор ==
проверяет, указывают ли две ссылки на один и тот же объект или нет. .equals()
проверьте фактическое содержимое строки (значение).
Обратите внимание, что метод .equals()
принадлежит классу Object
(суперкласс всех классов). Вам необходимо переопределить его в соответствии с вашим требованием к классу, но для String оно уже реализовано и проверяет, имеет ли две строки одно и то же значение.
String s1 = "Stack Overflow";
String s2 = "Stack Overflow";
s1 == s2; //true
s1.equals(s2); //true
Причина: строка литералы, созданные без нуля, хранятся в пуле строк в области перментонов кучи. Таким образом, оба s1 и s2 указывают на один и тот же объект в пуле. String s1 = new String("Stack Overflow");
String s2 = new String("Stack Overflow");
s1 == s2; //false
s1.equals(s2); //true
Причина. Если вы создаете объект String с использованием ключевого слова new
, ему выделяется отдельное пространство в куче. Это потому, что анонимные классы недоступны за пределами пакета, содержащего анонимный класс.
Вот демонстрация того, что происходит за кулисами:
public static void main(String[] args) throws Exception {
Portal portal = new Portal();
Object list = portal.getClass().getDeclaredMethod("getActionList", null).invoke(portal, null);
Object action = list.getClass().getDeclaredMethod("get", new Class[] { int.class }).invoke(list, 0);
action.getClass().getDeclaredMethod("action", null).invoke(action, null);
}
Попробуйте выполнить это в том же пакете, что и Portal
класс, а затем еще раз в другом классе вне пакета. В другом пакете последняя строка вызовет точно такое же исключение. Это проблема, с которой борется EL, поскольку она основана на отражении.
Я не вижу других способов решить эту проблему, кроме как просто создать public
(внутренний) класс
. Reflection (а значит и EL) может получить к ним доступ из других пакетов.
public class Portal {
private List<IAction> list = new ArrayList<IAction>();
public Portal() {
list.add(new IActionImpl());
}
public class IActionImpl implements IAction {
public void action() {
System.out.println("called action here");
}
}
public List<IAction> getActionList() {
return list;
}
}