Java自動取外し空ポインタ異常の解決


会社は引っ越しして、臨時に装飾工になります。二時間前に会社に来て、設備の解体に忙しいです。その結果、お客様の反応を受けました。一部の機能はたまに使えません。消防に参加して、このコードを書いている仲間と一緒に原因を調べます。
最終的には、業務がたまに使えなくなることが判明しました。Longタイプの自動取外しによる空の指針異常が原因です。以下はJavaの基本的なタイプの包装種類を分析します。箱を開ける時と箱を詰める時に何をしましたか?なぜ空の指針が異常になっていますか?また、面接の時に出る面接問題について分析します。
問題の再現
以下は簡単な例を通して、異常が発生したシーンを再現します。

public class BoxTest {

  public static void main(String[] args) {
    Map<String,Object> result = httpRequest();
    long userId = (Long) result.get("userId");
  }

  //     HTTP  
  private static Map<String,Object> httpRequest(){
    Map<String,Object> map = new HashMap<>();
    map.put("userId",null);
    return map;
  }
}

基本的なシーンは一つのインターフェースを要求して、インターフェースの中にある値を取ってください。この値はLongタイプです。Mapから値を取得してから、Longタイプの強回転を行います。インターフェイスが戻ってきたuserIdがnullになった時、これを強く回したら空のポインターが出ます。
Exception in thread「main」java.lang.Null PointerException
 at comp.chone gxia.box.BoxTest.main(BoxTest.java:15)
上のシーンは下のコードと同じ効果があります。

public class BoxTest {

  public static long getValue(long value) {
    return value;
  }

  public static void main(String[] args) {
    Long value = null;
    getValue(value);
  }
}

上記のコードもLongタイプを開封による異常です。コードの中に一つだけあります。一つはパラメータの中にあります。分析をより簡単にするために、私たちは第二の例で説明します。
原因分析
最初は疑問に思っていたかもしれませんが、異常なコードを出しても対象がない方法で呼び出したら、どうやって空の指針が現れますか?
この中で主に関わるのは自動的に箱を開ける操作です。箱を開けたからですか?バイトコードを使ってみます。
javap-cを通じて対応するバイトコードを調べてみます。

public class com.choupangxia.box.BoxTest {
 public com.choupangxia.box.BoxTest();
  Code:
    0: aload_0
    1: invokespecial #1         // Method java/lang/Object."<init>":()V
    4: return

 public static long getValue(long);
  Code:
    0: lload_0
    1: lreturn

 public static void main(java.lang.String[]);
  Code:
    0: aconst_null
    1: astore_1
    2: aload_1
    3: invokevirtual #2         // Method java/lang/Long.longValue:()J
    6: invokestatic #3         // Method getValue:(J)J
    9: pop2
   10: return
}

このうち、getValueメソッド呼び出しに対応するのは、mainメソッドの番号3と6の操作です。番号3はコマンドinvokevirtualをメソッドコマンドとします。対応はvalue.longValueで、valueが対応するのは声明のLongタイプです。
つまり、コンパイラはgetValueを2つのステップに分割し、最初のステップはvalueのlongValue方法によってそれを箱から外し、その後の結果を方法に伝える。相当于:

long primitive = value.longValue();
test(promitive);
最初のコードと照らし合わせて、valueがnullであれば、longValueメソッドを呼び出す時にNull PointerExceptionを投げます。
したがって、本質的には、いわゆる自動箱詰めと箱詰めはJavaが提供する文法飴にすぎない。
再確認
以下ではintタイプの例を使って、自動的に箱を開けると自動的に箱を詰めるという2つの操作文法的な砂糖の下の部分はいったいどうやって運行されているのかを確認します。

public class IntBoxTest {

  public static void main(String[] args) {
    Integer index = 11;
    int primitive = index;
  }
}

上のコードのバイトコードも同じです。

public class com.choupangxia.box.IntBoxTest {
 public com.choupangxia.box.IntBoxTest();
  Code:
    0: aload_0
    1: invokespecial #1         // Method java/lang/Object."<init>":()V
    4: return

 public static void main(java.lang.String[]);
  Code:
    0: bipush    11
    2: invokestatic #2         // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
    5: astore_1
    6: aload_1
    7: invokevirtual #3         // Method java/lang/Integer.intValue:()I
   10: istore_2
   11: return
}

mainメソッドの部分が見られます。番号2は箱詰め操作を行いました。元のタイプintをIntegerに入れました。呼び出す方法はInteger.valueOfです。番号7は、箱を外す操作でIntegerタイプをintタイプに変換し、呼び出す方法はInteger.intValueです。
自動箱詰めの本質
上記の分析から、いわゆる箱詰めと箱詰め作業は文法的な飴の機能にすぎないことが分かります。コンパイラはコンパイル操作時に、本質的には包装類に対応する異なる方法を呼び出して処理します。
箱に詰める時は通常包装類のvalueOf方法を呼び出しますが、箱を開ける時は通常包装類のxxValue()方法を呼び出します。その中のxxxはbolean/long/intなどのようです。
自動で箱を開けてと箱を詰める操作は主に賦課、比較、算数演算、方法の呼び出しなどでよくあります。この時、私たちは主要な空の指針が必要です。
面接問題
面接の問題を見てください。次のfoo 1とfoo 2が呼び出された時はどうやって行いますか?簡単に分析します。

public void foo1() {
  if ((Integer) null == 1) {
  }
}

public void foo2() {
  if ((Integer) null > 1) {
    System.out.println("abc");
  }
}

二つの方法を呼び出した時に空のポインターが異常になることは明らかです。空飛ぶポインタの異常な原因と分析過程については、上記で説明しましたが、バイトコードを分析してみてもいいです。
もう一つ面接問題を見てください。次の文は正常に実行できますか?

Integer value1 = (Integer) null;
Double value2 = (Double) null;
Boolean value3 = (Boolean) null;
正常に実行できます。Javaではnullは特別な値であり、任意の参照タイプに値を割り当てることができ、また任意の参照タイプに変換することができます。
結び目
どんな小さな問題でも、小さな異常でも、深く追跡すれば、より明確に底の原理が分かるだけでなく、実践の過程でもっと自信があり、ミスが少ないです。
この記事ではJava自動取外し針の異常な解決に関する記事を紹介します。Java自動取外し針の異常内容については、以前の文章を検索してください。または下記の関連記事を引き続きご覧ください。これからもよろしくお願いします。