2016-02-24 3 views
7

Следующий фрагмент воспроизводит предупреждение в Android Studio.Dereference может генерировать «java.lang.NullPointerException»

Bundle extras = getIntent().getExtras(); 
    if (extras != null && extras.getString(REDIRECT_KEY) != null) { 
     switch (extras.getString(REDIRECT_KEY)) { ... 

extras.getString(REDIRECT_KEY) производит предупред

enter image description here

разыменование 'extras.getString (REDIRECT_KEY)' может производить 'java.lang.NullPointerException'

Но я не Нет никакого сценария, где это может произойти. Это ошибка в проверках lint, что она просто не распознает мои нулевые проверки в if, если раньше? Или мне что-то не хватает?

EDIT: изменения кода на следующий, сделал удалить предупреждение

if(getIntent() != null && getIntent().getStringExtra(REDIRECT_KEY) != null){ 
     switch (getIntent().getStringExtra(REDIRECT_KEY)){ 
      ... 
     } 
    } 

НО это ушло только потому, кстати, эта проверка ворса работает (по крайней мере, я думаю). Если я покажу более подробную информацию для этой проверки, он говорит в одной точке

Переменных, параметры метода и возвращаемые значения, помеченные как @Nullable или @NotNull рассматриваются как обнуляемые (или не нулевые, соответственно) и используемые в ходе анализ, чтобы проверить допустимость пустых контрактов

Глядя на исходный код Bundle и Намерения показывает:

/** 
* Retrieve extended data from the intent. 
* 
* @param name The name of the desired item. 
* 
* @return the value of an item that previously added with putExtra() 
* or null if no String value was found. 
* 
* @see #putExtra(String, String) 
*/ 
public String getStringExtra(String name) { 
    return mExtras == null ? null : mExtras.getString(name); 
} 

и BaseBundle

/** 
* Returns the value associated with the given key, or null if 
* no mapping of the desired type exists for the given key or a null 
* value is explicitly associated with the key. 
* 
* @param key a String, or null 
* @return a String value, or null 
*/ 
@Nullable 
public String getString(@Nullable String key) { 
    unparcel(); 
    final Object o = mMap.get(key); 
    try { 
     return (String) o; 
    } catch (ClassCastException e) { 
     typeWarning(key, o, "String", e); 
     return null; 
    } 
} 

Как вы можете видеть, BaseBundle устанавливает свои возвращаемые значения в @Nullable, а Intent - нет. Поэтому использование getStringExtra устраняет симпозиумы, а не причину. Я догадываюсь, что это вызвано недостаточной проверкой на линт, вместо неправильного кодирования на моей стороне. Или кто-нибудь все еще видит сценарий, где может быть выброшен указатель Null?

+0

В какой строке это предупреждение? второй или третий? – Ferrybig

+2

Я думаю, что вместо того, чтобы получать String каждый раз из дополнительных функций, вы должны назначить его переменной. Потому что ваши дополнительные параметры могут стать нулевыми в определенных ситуациях. – Pragnani

+0

третья строка в фрагменте или строка 80 на изображении. Я проверяю extras == null и результат getString() == null. См. Раздел «Ввод» во второй строке. – AlbAtNf

ответ

4

Взгляните на этот пример взят из here

class Argument { 

    public final static int TOMAYTO = 0; 
    public final static int TOMAHTO = 1; 

    static void argue() { 

     int say = TOMAYTO; 

     while (true) { 

      switch (say) { 

      case TOMAYTO: 

       say = TOMAHTO; 
       break; 

      case TOMAHTO: 

       say = TOMAYTO; 
       break; 
      } 
     } 
    } 
} 

байткоды порожденную JAVAC для метода утверждают() приведены ниже:

0 iconst_0 // Push constant 0 (TOMAYTO) 
    1 istore_0 // Pop into local var 0: int say = TOMAYTO; 
    2 iload_0 // Push key for switch from local var 0 
          // Perform switch statement: switch (say) {... 
          // Low case value is 0, high case value is 1 
          // Default branch offset will goto 2 
    3 tableswitch 0 to 1: default=2 
      0: 24 // case 0 (TOMAYTO): goto 24 
      1: 29 // case 1 (TOMAHTO): goto 29 

          // Note that the next instruction starts at address 24, 
          // which means that the tableswitch took up 21 bytes 
    24 iconst_1 // Push constant 1 (TOMAHTO) 
    25 istore_0 // Pop into local var 0: say = TOMAHTO 
    26 goto 2 // Branch unconditionally to 2, top of while loop 
    29 iconst_0 // Push constant 1 (TOMAYTO) 
    30 istore_0 // Pop into local var 0: say = TOMAYTO 
    31 goto 2 // Branch unconditionally to 2, top of while loop 

Как вы можете видеть для переключателя заявление с Строковый тип данных выполняется с помощью tablewitch, и для каждого случая значение, переданное коммутатору, сравнивается с значением case, поэтому это означает, что в вашем случае extras.getString можно вызывать несколько раз без вашего предыдущего if, и как таковой, поскольку дополнительные функции являются пакетом, есть вероятность, что он может быть разыменован и вызвать исключение nullpointer.

Всегда полезно создавать локальную переменную вместо выполнения нескольких вызовов метода, вы можете взглянуть на this presentation by Jake Wharton, чтобы понять, почему.

+1

Спасибо, так как это единственный ответ, который действительно отвечает на мой первоначальный вопрос: «Пропустил ли я что-нибудь». – AlbAtNf

Смежные вопросы