How to handle nullpointerexception in java

Что это за ошибка?

Object ProgressEvent – это ошибка объекта выполнения в Киви. Если говорить буквально, то проблема заключается в сбое при операции загрузки объекта ProgressEvent на сервера. То есть вы даете команду на отправку пакетов, но обработанного ответа назад не последовало.

Ошибка Object ProgressEvent в Киви

Сбой может возникнуть при различных операциях – выполнение платежа, вход в личный кабинет, работа с картами, ввод подтверждения или капчи. Помимо этого, в одно время ошибка может сменяться другими уведомлениями:

  • “Ошибка соединения. Проверьте подключение к сети и попробуйте еще раз”.
  • “Seems like something isn’t going right. Try again later”.

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

Рекомендуем наш материал по исправлению кода ошибки QWPRC-1021 , который возникает при ограничении на исходящие платежи.

Язык программирования «Java»

Java — крепко типизированный объектно-ориентированный язык программирования, созданный фирмой Sun Microsystems (в следующем приобретённой фирмой Oracle). В реальное время план принадлежит OpenSource и распространяется по лицензии GPL. В OpenJDK работаю большие фирмы , такие как — Oracle, RedHat, IBM, Google, JetBrains. Например, же на базе OpenJDK эти фирмы разрабатывают собственные сборки JDK. Как заявляет фирма Oracle — различия между OpenJDK и OracleJDK буквально отсутствуют за исключением лицензии, рисовки шрифтов в Swing и кое-каких библиотек, на которые лицензия GPL не распространяется. Приложения Java, как правило, транслируются в особый байт-код, вследствие этого они имеют права работать с любыми компьютерными фирмами, которые разрабатывают поддержку виртуальной Java-машины. Дата официального выпуска — 23 мая 1995 года. На 2019 год Java — одна из самых известных языков программирования.

Главные особенности языка

Программы на Java транслируются в байт-код Java, производимый виртуальной машиной Java (JVM) — программой , обрабатывающей байтовый код и передающей память оборудованию, как интерпретатор.

Нередко к дефектам концепции виртуальной машины, относят понижение производительности. Ряд усовершенствований прибавил скорость работе программ на Java: использование технологии трансляции байт-кода в машинный код, именно во время работы программы (JIT-технология) с вероятностью хранения версий класса в машинном коде,обширное внедрение native-кода в библиотеки, аппаратные способы , обеспечивающие разогнанную обработку байт-кода (например, разработка Jazelle, поддерживаемая некоторыми микропроцессорами производства ARM).

Обработка исключения

Обработка исключений в Java подразумевает создание блоков кода и производится в программе посредством конструкций try{}finally{}, try{}catch, try{}catch{}finally.

В процессе возбуждения исключения в try обработчик исключения ищется в блоке catch, который следует за try. При этом если в catch присутствует обработчик данного вида исключения, происходит передача управления ему. Если же нет, JVM осуществляет поиск обработчика данного типа исключения, используя для этого цепочку вызова методов. И так происходит до тех пор, пока не находится подходящий catch. После того, как блок catch выполнится, управление переходит в необязательный блок finally. Если подходящий блок catch найден не будет, Java Virtual Machine остановит выполнение программы, выведя стек вызовов методов под названием stack trace. Причём перед этим выполнится код блока finally при наличии такового.

Рассмотрим практический пример обработки исключений:

public class Print {

     void print(String s) {
        if (s == null) {
            throw new NullPointerException("Exception: s is null!");
        }
        System.out.println("Inside method print: " + s);
    }

    public static void main(String[] args) {
        Print print = new Print();
        List list= Arrays.asList("first step", null, "second step");

        for (String slist) {
            try {
                print.print(s);
            }
            catch (NullPointerException e) {
                System.out.println(e.getMessage());
                System.out.println("Exception was processed. Program continues");
            }
            finally {
                System.out.println("Inside bloсk finally");
            }
            System.out.println("Go program....");
            System.out.println("-----------------");
        }

    }
    }

А теперь глянем на результаты работы метода main:

Inside method print first step
Inside bloсk finally
Go program....
-----------------
Exception: s is null!
Exception was processed. Program continues
Inside bloсk finally
Go program....
-----------------
Inside method print second step
Inside bloсk finally
Go program....
-----------------

Блок finally чаще всего используют, чтобы закрыть открытые в try потоки либо освободить ресурсы. Но при написании программы уследить за закрытием всех ресурсов возможно не всегда. Чтобы облегчить жизнь разработчикам Java, была предложена конструкция try-with-resources, автоматически закрывающая ресурсы, открытые в try. Используя try-with-resources, мы можем переписать наш первый пример следующим образом:

public String input() throws MyException {
    String s = null;
    try(BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))){
        s = reader.readLine();
   } catch (IOException e) {
       System.out.println(e.getMessage());
   }
    if (s.equals("")){
        throw new MyException ("String can not be empty!");
    }
    return s;
}

А благодаря появившимся возможностям Java начиная с седьмой версии, мы можем ещё и объединять в одном блоке перехват разнотипных исключений, делая код компактнее и читабельнее:

public String input() {
    String s = null;
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
        s = reader.readLine();
        if (s.equals("")) {
            throw new MyException("String can not be empty!");
        }
    } catch (IOException | MyException e) {
        System.out.println(e.getMessage());
    }
    return s;
}

Common Reasons of NullPointerException in Java as Example

Based upon my experience java.lang.NullPointerException repeats itself in various formats, I have collected the most common cause of java.lang.NullPointerException in java code and explained them here, we will use the following Trade class for example :

publicclass Trade {private String symbol;privateint price;publicstatic String market;public Trade(String symbol, int price){this.symbol = symbol;this.price = price;}publicint getPrice(){return price;}publicvoid setPrice(int price){this.price = price;}public String getSymbol(){return symbol;}publicvoid setSymbol(String symbol){this.symbol = symbol;}}

1. Java  NullPointerException while calling instance method on null object

This is probably the most common cause of this error, you call method on some object and found that the reference is null, always perform null check if you see possibility of null before calling any method on object.

Trade pennyStock = null;pennyStock.getPrice(); //this will throw NullPointerExceptionException in thread «main» java.lang.NullPointerExceptionat test.NullPointerExceptionTest.main(NullPointerExceptionTest.java:23)

2. NullPointerException in Java while accessing field on a null reference.

Trade fxtrade = null;int price = fxtrade.price; //here fxtrade is null, you can’t access field hereException in thread «main» java.lang.NullPointerExceptionat test.NullPointerExceptionTest.main(NullPointerExceptionTest.java:64)

3. java.lang.NullPointerException when throwing null as an exception.

If you throw an Exception object and if that is null you will get a null pointer exception as shown in the below example

RuntimeException nullException = null;throw nullException;Exception in thread «main» java.lang.NullPointerExceptionat test.NullPointerExceptionTest.main(NullPointerExceptionTest.java:74)

4. example of NullPointerException is when getting the length of an array that is null.

Trade[] bluechips = null;int length = bluechips.length;  //array is null hereException in thread «main» java.lang.NullPointerExceptionat test.NullPointerExceptionTest.main(NullPointerExceptionTest.java:85)

5. Example of NPE when accessing an element of a null array.

Trade[] bluechips = null;Trade motorola = bluechips; //array is null hereException in thread «main» java.lang.NullPointerExceptionat test.NullPointerExceptionTest.main(NullPointerExceptionTest.java:94)

6. You will also get NullPointerException in Java if you try to synchronize on a null object or try to use the null object inside the synchronized block in Java.

Trade highbetaTrade = null;synchronized(highbetaTrade){System.out.print(«This statement is synchronized on null»);}

Exception in thread «main» java.lang.NullPointerExceptionat test.NullPointerExceptionTest.main(NullPointerExceptionTest.java:104)

4 ответа 4

Когда вы объявляете переменную ссылочного типа, на самом деле вы создаете ссылку на объект данного типа. Рассмотрим следующий код для объявления переменной типа int:

В этом примере переменная x имеет тип int и Java инициализирует её как 0. Когда вы присвоите переменной значение 10 (вторая строка), это значение сохранится в ячейке памяти, на которую ссылается x .

Но когда вы объявляете ссылочный тип, процесс выглядит иначе. Посмотрим на следующий код:

В первой строке объявлена переменная num , ее тип не относится к встроенному, следовательно, значением является ссылка (тип этой переменной, Integer , является ссылочным типом). Поскольку вы еще не указали, на что собираетесь ссылаться, Java присвоит переменной значение Null , подразумевая «Я ни на что не ссылаюсь».

Во второй строке, ключевое слово new используется для создания объекта типа Integer . Этот объект имеет адрес в памяти, который присваивается переменной num . Теперь, с помощью переменной num вы можете обратиться к объекту используя оператора разыменования . .

Исключение, о котором вы говорите в вопросе, возникает, если вы объявили переменную, но не создали объект, то есть если вы попытаетесь разыменовать num до того, как создали объект, вы получите NullPointerException . В самом простом случае, компилятор обнаружит проблему и сообщит, что

Что говорит: «возможно, переменная num не инициализирована».

Иногда исключение вызвано именно тем, что объект действительно не был создан. К примеру, у вас может быть следующая функция:

В этом случае создание объекта (переменная num ) лежит на вызывающем коде, то есть вы предполагаете, что он был создан ранее – до вызова метода doSomething . К сожалению, следующий вызов метода вполне возможен:

В этом случае значение переменной num будет null . Лучшим способом избежать данного исключения будет проверка на равенство нулю. Как результат, функция doSomething должна быть переписана следующим образом:

Как альтернативный вариант предыдущему примеру вы можете сообщить вызывающему коду, что метод был вызван с неверными параметрами, например, с помощью IllegalArgumentException .

Иерархия исключений в Java

Когда возникают ошибки при выполнении программы, исполняющая среда Java Virtual Machine обеспечивает создание объекта нужного типа, используя иерархию исключений Java — речь идёт о множестве возможных исключительных ситуаций, которые унаследованы от класса Throwable — общего предка. При этом исключительные ситуации, которые возникают в программе, делят на 2 группы:
1. Ситуации, при которых восстановление нормальной дальнейшей работы невозможно.
2. Ситуации с возможностью восстановления.

К первой группе можно отнести случаи, при которых возникают исключения, которые унаследованы из класса Error. Это ошибки, возникающие во время выполнения программы при сбое работы Java Virtual Machine, переполнении памяти либо сбое системы. Как правило, такие ошибки говорят о серьёзных проблемах, устранение которых программными средствами невозможно. Данный вид исключений в Java относят к неконтролируемым исключениям на стадии компиляции (unchecked). К этой же группе относятся и исключения-наследники класса Exception, генерируемые Java Virtual Machine в процессе выполнения программы — RuntimeException. Данные исключения тоже считаются unchecked на стадии компиляции, а значит, написание кода по их обработке необязательно.

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

Зачем нам механизм исключений?

Для понимания опять приведём пример из обычного мира. Представьте, что на какой-нибудь автодороге имеется участок с аварийным мостом, на котором ограничена грузоподъёмность. И если по такому мосту проедет грузовик со слишком большой массой, мост разрушится, а в момент этого ЧП ситуация для шофёра станет, мягко говоря, исключительной. И вот, дабы такого не произошло, дорожные службы заранее устанавливают на дороге соответствующие предупреждающие знаки. И тогда водитель, посмотрев на знак, сравнит массу своего авто со значением разрешённой грузоподъёмности и примет соответствующее решение, например, поедет по другой дороге.

То есть мы видим, что из-за правильных действий дорожной службы шоферы крупногабаритных транспортных средств:
1) получили возможность заранее изменить свой путь;
2) были предупреждены об опасности;
3) были предупреждены о невозможности проезжать по мосту при определённых условиях.

Вот как наш жизненный пример соотносится с применением исключения на Java:

Исходя из вышесказанного, мы можем назвать одну из причин применения исключений в Java. Заключается она в возможности предупреждения исключительной ситуации для её последующего разрешения и продолжения работы программы. То есть механизм исключений позволит защитить написанный код от неверного применения пользователем путём валидации входящих данных.

Что же, давайте ещё раз побудем дорожной службой. Чтобы установить знак, мы ведь должны знать места, где водителей ТС могут ждать различные неприятности. Это первое. Далее, нам ведь надо заготовить и установить знаки. Это второе. И, наконец, надо предусмотреть маршруты объезда, позволяющие избежать опасности.

В общем, механизм исключений в Java работает схожим образом. На стадии разработки программы мы выполняем «ограждение» опасных участков кода в отношении наших исключений, используя блок try{}. Чтобы предусмотреть запасные пути, применяем блок catch{}. Код, выполняемый в программе при любом исходе, пишем в блоке finally{}.

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

Что касается программирования на Java, то мы, когда пишем свои классы и методы, далеко не всегда можем предвидеть контекст их применения другими программистами в своих программах, а значит, не можем со стопроцентной вероятностью предвидеть правильный путь для разрешения исключительных ситуаций. Но предупредить коллег о возможной исключительной ситуации мы всё-таки должны, и это не что иное, как правило хорошего тона.

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

Как исправить фатальную ошибку виртуальной машины Java в Windows 10

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

1. Установите новую системную переменную для Java

Ошибка виртуальной машины Java часто возникает, когда Java требуется больший глобальный максимальный размер кучи памяти. Пользователи исправили проблему, увеличив максимальный объем оперативной памяти, выделенной для Java. Пользователи могут сделать это, установив новую системную переменную Java следующим образом.

  • Откройте «Выполнить» с помощью сочетания клавиш Windows + R.
  • Введите «sysdm.cpl» в «Выполнить» и нажмите ОК , чтобы открыть окно на изображении непосредственно ниже.

  • Выберите вкладку Advanced в этом окне.
  • Нажмите кнопку Переменные среды , чтобы открыть окно ниже.

  • Нажмите кнопку Создать под полем Системные переменные.
  • Введите «_JAVA_OPTIONS» в текстовое поле «Имя переменной».

Затем введите «–Xmx512M» в текстовом поле «Значение переменной», что увеличит объем оперативной памяти до 512 мегабайт.

  • Нажмите кнопку ОК , чтобы закрыть окно.
  • Затем нажмите кнопку ОК в окнах среды.

– СВЯЗАННО: Как удалить всплывающее окно «Обновление Java доступно»

2. Выберите опцию Запуск от имени администратора для Java

Ошибка виртуальной машины Java также может быть связана с недостаточными правами администратора. Таким образом, некоторым пользователям может потребоваться назначить права администратора для Java. Пользователи могут назначать права администратора для Java в Windows 10 следующим образом.

  • Откройте Cortana с помощью сочетания клавиш Windows + Q.
  • Введите «Java» в поле поиска.
  • Затем щелкните правой кнопкой мыши Java и выберите Открыть местоположение файла , чтобы открыть папку Java в проводнике.

Теперь пользователи могут щелкнуть правой кнопкой мыши файл java.exe и выбрать Свойства .

Выберите вкладку «Совместимость».

  • Выберите Запустить эту программу от имени администратора .
  • Выберите параметр Применить .
  • Нажмите ОК , чтобы закрыть окно.

3. Переустановите Java

Переустановка Java может также исправить ошибку виртуальной машины Java для некоторых пользователей. Сначала удалите установленную версию Java, введя «appwiz.cpl» в «Выполнить» и нажав ОК .

  • Введите «Java» в поле поиска.
  • Выберите Java и нажмите Удалить .
  • Нажмите Да в любом открывшемся окне подтверждения.
  • После этого перезапустите Windows.
  • Затем откройте страницу загрузки Java в браузере.

  • Пользователям нужна 32-битная Java для 32-битных программ и 64-битная Java для 64-битного программного обеспечения. В случае сомнений лучше всего загрузить и установить обе версии Java, нажав Windows Offline и Windows Offline 64-bit .
  • После этого откройте мастер установки Java.
  • Нажмите кнопку Установить в мастере настройки.

Используйте аннотации @NotNull и @Nullable

В описании ваших методов вы можете определить соглашение

null

-безопасности методов, используя аннотации

@NotNull

и @Nullable чтобы показать может метод возвращать

null

или нет. Современные компиляторы и IDE могут использовать эти аннотации для анализы вашего кода и выдавать соответствующие советы, например, о пропущенной проверке на

null

, или наоборот, о возможности убрать лишнюю проверку, засоряющую код. Такие аннотации, например, поддерживают IntelliJ IDE и FindBugs, кроме этого они входят в JSR 305. Но даже если ваша IDE и не поддерживает такие аннотации, они сами по себе будут хорошей документацией. Глядя на

@NotNull

и

@Nullable

программисту будет проще понять где нужно добавлять проверку на

null

, а где — нет. Это, кстати, довольно новая среди Java программистов практика, и должно пройти время, чтобы она распространилась.

Conclusion

Remember that any NullPointerException comes about when you use a method on a variable which has not been initialized. Therefore, you can avoid the error by always setting a default value for every variable.

Other ways to avoid exception in thread main java.lang.nullpointerexception include using String.valueOf () method as opposed to toString () method. For instance, if an application code needs a string representation, use the static method instead of the toString method which throws an NPE.

Consider using the ternary operator which is in the form of Boolean expression seven value1: value2. Alternatively, you can avoid the error by creating methods which return to an empty collection, rather than those which return to null. Lastly, use Apache`s StringUtils class. Apache is a library which provides utilities for APU; for example, string manipulation methods.

Now that we have discussed what the error is, how it comes about, remedies to fix, and how to avoid it, you are in a better position to enjoy coding using Java.

Ошибка java.lang.nullpointerexception, как исправить?

Ряд пользователей (да и разработчиков) программных продуктов на языке Java могут столкнуться с ошибкой java.lang.nullpointerexception (сокращённо NPE), при возникновении которой запущенная программа прекращает свою работу. Обычно это связано с некорректно написанным телом какой-либо программы на Java, требуя от разработчиков соответствующих действий для исправления проблемы. В этом материале я расскажу, что это за ошибка, какова её специфика, а также поясню, как исправить ошибку java.lang.nullpointerexception.

Что это за ошибка java.lang.nullpointerexception

Появление данной ошибки знаменует собой ситуацию, при которой разработчик программы пытается вызвать метод по нулевой ссылке на объект. В тексте сообщения об ошибке система обычно указывает stack trace и номер строки, в которой возникла ошибка, по которым проблему будет легко отследить.

Как исправить ошибку java.lang.nullpointerexception

Как избавиться от ошибки java.lang.nullpointerexception? Способы борьбы с проблемой можно разделить на две основные группы – для пользователей и для разработчиков.

Для пользователей

Если вы встретились с данной ошибкой во время запуска (или работы) какой-либо программы (особенно это касается minecraft), то рекомендую выполнить следующее:

  1. Переустановите пакет Java на своём компьютере. Скачать пакет можно, к примеру, вот отсюда;
  2. Переустановите саму проблемную программу (или удалите проблемное обновление, если ошибка начала появляться после такового);
  3. Напишите письмо в техническую поддержку программы (или ресурса) с подробным описанием проблемы и ждите ответа, возможно, разработчики скоро пофиксят баг.
  4. Также, в случае проблем в работе игры Майнкрафт, некоторым пользователям помогло создание новой учётной записи с административными правами, и запуск игры от её имени.

Для разработчиков

Разработчикам стоит обратить внимание на следующее:

  1. Вызывайте методы equals(), а также equalsIgnoreCase() в известной строке литерала, и избегайте вызова данных методов у неизвестного объекта;
  2. Вместо toString() используйте valueOf() в ситуации, когда результат равнозначен;
  3. Применяйте null-безопасные библиотеки и методы;
  4. Старайтесь избегать возвращения null из метода, лучше возвращайте пустую коллекцию;
  5. Применяйте аннотации @Nullable и @NotNull;
  6. Не нужно лишней автоупаковки и автораспаковки в создаваемом вами коде, что приводит к созданию ненужных временных объектов;
  7. Регламентируйте границы на уровне СУБД;
  8. Правильно объявляйте соглашения о кодировании и выполняйте их.

Зачем нам нужно значение null?

Как уже упоминалось, null — это специальное значение, используемое в Java. Это чрезвычайно полезно при кодировании некоторых шаблонов проектирования, таких как Null Object pattern и шаблон Singleton pattern.

Шаблон Singleton обеспечивает создание только одного экземпляра класса, а также направлен на предоставление глобального доступа к объекту.

Например, простой способ создания не более одного экземпляра класса — объявить все его конструкторы как частные, а затем создать открытый метод, который возвращает уникальный экземпляр класса:

import java.util.UUID;class Singleton { private static Singleton single = null; private String ID = null; private Singleton() { /* Make it private, in order to prevent the creation of new instances of * the Singleton class. */ ID = UUID.randomUUID().toString(); // Create a random ID. } public static Singleton getInstance() { if (single == null) single = new Singleton(); return single; } public String getID() { return this.ID; }}public class TestSingleton { public static void main(String[] args) { Singleton s = Singleton.getInstance(); System.out.println(s.getID()); }}

В этом примере мы объявляем статический экземпляр класса Singleton. Этот экземпляр инициализируется не более одного раза внутри метода getInstance.

вопрос: Как я могу прочитать NPE stacktrace?

предположим, что я компилирую и запускаю программу выше:

$ javac Test.java $ java TestException in thread “main” java.lang.NullPointerException at Test.main(Test.java:4)$

первое наблюдение: компиляция удалась! Проблема в программе не является ошибкой компиляции. Это время работы ошибка. (Некоторые IDEs могут предупредить, что ваша программа всегда будет выдавать исключение … но стандарт javac компилятор не.)

второе наблюдение: когда я запускаю программу, она выводит две строки “абракадаброй”. неправильно!! это не чушь собачья. Это stacktrace … и это обеспечивает важная информация это поможет вам отследить ошибка в коде, если вы потратите время, чтобы внимательно прочитать его.

Итак, давайте посмотрим, что он говорит:

Exception in thread “main” java.lang.NullPointerException

первая строка трассировки стека говорит вам о нескольких вещах:

  • он сообщает вам имя потока Java, в котором было вызвано исключение. Для простой программы с одним потоком (как этот) он будет “основным”. Давайте двигаться дальше …
  • он сообщает вам полное имя исключения, которое было брошено; т. е. java.lang.NullPointerException.
  • если исключение имеет связанное сообщение об ошибке, оно будет выведено после имени исключения. NullPointerException необычен в этом отношении, потому что он редко имеет сообщение об ошибке.

вторая строка является наиболее важной в диагностике NPE. at Test.main(Test.java:4)

at Test.main(Test.java:4)

это говорит нам о многом:

  • “на тест.главный” говорит, что мы были в main метод Test класс.
  • “тест.java: 4” дает исходное имя файла класса, и это говорит нам, что оператор, где это произошло, находится в строке 4 файла.

если вы считаете строки в файле выше, строка 4-это та, которую я обозначил комментарием “Здесь”.

обратите внимание, что в более сложном примере в трассировке стека NPE будет много строк. Но вы можете быть уверены, что вторая строка (первая строка “at”) скажет вам, где был NPE бросили1

короче говоря трассировка стека скажет нам однозначно, какой оператор программы бросил NPE.

1 – не совсем верно. Есть вещи, называемые вложенными исключениями…

Рейтинг
( Пока оценок нет )
Editor
Editor/ автор статьи

Давно интересуюсь темой. Мне нравится писать о том, в чём разбираюсь.

Понравилась статья? Поделиться с друзьями:
Клипофком
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: