5年前にブログで三元演算子のヌルポインタの問題について書きましたが、ついにAlibaba開発マニュアルに含まれました。

5年前にブログで三元演算子のヌルポインタの問題について書きましたが、ついにAlibaba開発マニュアルに含まれました。

トピックに含まれる

15のAlibaba開発マニュアルの解釈
△コーディングを独自に追求して
5年前にブログで三元演算子のヌルポインタの問題について書きましたが、ついにAlibaba開発マニュアルに含まれました。
いるHollis これはHollisの267番目のオリジナル共有
著者
ですlHollisソースlHollis(ID:hollischuang)
最近、AlibabaJava開発マニュアルがリリースされました最新版の大山版は名前がかなり良く、山々が一望できます。

新しいバージョンには30以上のプロトコルが追加されたと言われています。注意深く読む時間がありませんでしたが、ファンは私のブログで新しいプロトコルの1つを見たことがあると言っていました。

よく調べてみると、ずっと前にこの問題に遭遇しましたが、実際にブログに記録されていました。
5年前にブログで三元演算子のヌルポインタの問題について書きましたが、ついにAlibaba開発マニュアルに含まれました。

私の
同僚は最初にこの問題に遭遇しました。彼はコードで三元演算子を使用しました。コードがオンラインで実行されているときにNPEが発生しました。調査の結果、三元演算子と自動解凍の間にあることがわかりました。特定の関係があり、結果としてnullポインタになります。
この記事は2015年に最初に公開され、現在は1w以上のビューがあります。
5年前にブログで三元演算子のヌルポインタの問題について書きましたが、ついにAlibaba開発マニュアルに含まれました。

この点は最新の開発マニュアルにも記載されていることを踏まえ、前回の記事の内容を整理して整理し、みんなでこの知識のポイントを復習しました。

1つの3値演算子

条件式b?x:yの場合、最初に条件bを計算してから、判断します。bの値が真の場合、xの値が計算され、操作の結果はxの値になります。それ以外の場合、yの値が計算され、操作の結果はyの値になります。条件式がxとyの両方を評価することはありません。条件付き演算子は右連想です。つまり、計算を右から左にグループ化します。たとえば、a?b:c?d:eはa?b:(c?d:e)として実行されます。

2つ、自動梱包と自動開梱

基本データタイプのオートボックス化とボックス化解除は、J2SE5.0以降で提供されている機能です。
一般に、クラスのオブジェクトインスタンスを作成する場合は、次のようにします。Classa = new Class(parameters);

Integerオブジェクトを作成すると、次のようになります。Integeri = 100;(注:int i = 100;との違いがあります)

実際、上記のコードが実行されると、システムはそれを実行しました。Integeri = Integer.valueOf(100);

この原則がどのように実装されるか(いつ開梱するか、いつ梱包するか)については説明せず、通常のデータタイプとオブジェクトタイプの違いを無視します。

独自のコードがパッキング(アンパック)仕様に準拠している場合、コンパイラーが自動的にボックスのアンパック(アンパック)を支援することを理解できます。

それで、プログラマーによって制御されないこの種の自動分解(組み立て)に問題はありますか?

3、問題のレビュー

まず、既存の経験を通じて次のコードを見てください。

Map<String,Boolean> map =  new HashMap<String, Boolean>();

Boolean b = (map!=null ? map.get("test") : false);

上記のコードは、私たちが注意を払わずに書くことが多いタイプのコードです(多くの場合、三元演算子を使用するのが好きです)。もちろん、このコードには問題があります。コードが実行されると、NPEに報告されます。

スレッド「メイン」の例外java.lang.NullPointerException

まず、nullポインターが報告されるため、nullオブジェクトのいくつかのメソッドをいくつかの場所で呼び出す必要があることは明らかです。

これらの2つの短いコード行では、map.get( "test")を呼び出すメソッドは1つしかないようですが、マップが事前に初期化されており、Nullにならないことは誰もが知っているので、どこにありますか?ヌルポインタ。

次に、コードを逆コンパイルしてみましょう。コンパイラによって処理された後、私たちが書いたコードがどうなるか見てみましょう。

コンパイル解除後のコードは次のとおりです。


HashMap hashmap = new HashMap();

Boolean boolean1 = Boolean.valueOf(hashmap == null ? false : ((Boolean)hashmap.get("test")).booleanValue());

この逆コンパイルされたコードを読んだ後、分析した後、おそらく問題がどこにあるかを知ることができます。

((Boolean)hashmap.get( "test"))。booleanValue()の実行プロセスと結果は次のとおりです。


hashmap.get("test")->null;
(Boolean)null->null;
null.booleanValue()->报错

さて、問題は最終的に特定されました。それでは、この問題を解決する方法と、この問題が発生する理由を見てみましょう。

4、原理分析

逆コンパイルされたコードを確認することで、問題を正確に特定しました。分析の結果、NPEの原因は、3値演算子と自動ボックス解除によって引き起こされたヌルポインタ例外であると結論付けることができます。

規則によれば、三元演算子の結果を変数に割り当てることができるように、三元演算子の第2および第3オペランドの戻り値タイプは同じである必要があります。

例:Person i = a> b?i1:i2; i1とi2のタイプはPersonである必要があります。

Javaには特別な状況があるため、つまり、基本データタイプとパッケージデータタイプは、自動ボックス解除によって相互に変換できます。つまり、int i = new Integer(10)を定義できます。また、Integer i = 10を定義することもできます。

三元演算子の第2および第3オペランドタイプがそれぞれ基本データタイプおよびパッケージングタイプオブジェクトである場合、一方の当事者が自動的にボックスを解除する必要があります。

三元演算子の文法仕様に従って、それを行う方法。jls-15.25を参照してください。要約は次のとおりです。


If the second and third operands have the same type (which may be the null type), then that is the type of the conditional expression.
If one of the second and third operands is of primitive type T, and the type of the other is the result of applying boxing conversion (§5.1.7) to T, then the type of the conditional expression is T.
If one of the second and third operands is of the null type and the type of the other is a reference type, then the type of the conditional expression is that reference type.

簡単に言うと、2番目と3番目のオペランドがそれぞれ基本型とオブジェクトの場合、その中のオブジェクトは操作の基本型としてボックス化されません。

したがって、結果は次のようになります。3値演算子が使用され、2番目と3番目のオペランドがそれぞれ基本タイプとオブジェクトであるためです。したがって、オブジェクトはボックス化されていません。オブジェクトはnullであるため、ボックス化解除プロセス中にnull.booleanValue()が呼び出されると、NPEが報告されます。

5、問題解決

コードが次のように記述されている場合、エラーは報告されません。


Map<String,Boolean> map =  new HashMap<String, Boolean>();

Boolean b = (map!=null ? map.get("test") : Boolean.FALSE);

三元演算子の2番目と3番目のオペランドがすべてオブジェクトタイプであることを確認するためです。

これは、3値演算子に関連しています。

著者について:ホリスは、コーディングの人々、現在のアリババの技術専門家、パーソナルテクノロジーブロガー、技術記事、数千万のネットワーク全体を読む量、「3クラスプログラマー」の共同著者のためのユニークな探求を持っています。
ダイナミックブラックノート

Javaエンジニアの神になるための道に関する一連の記事
は、GitHubアップデートにあります。フォローを歓迎し、スターへようこそ。
5年前にブログで三元演算子のヌルポインタの問題について書きましたが、ついにAlibaba開発マニュアルに含まれました。
Javaの問題313に直面しています:JDKのさまざまなバージョンでランタイム定数プールはどのように実装されていますか?
詳細な同時実行問題013:同期ロック最適化の拡張

  • 詳細|よりエキサイティングな記事
    -「Javaエンジニアへの道」の高精細マインドマップがここにあります!
    ランダムトーク:コンピューターでレアな文字を入力できない、または入力後に表示できないのはなぜですか?
    とても才能のある、ネチズンによって要約された羅志翔事件はメロンのコピーライティングを食べます!誰もが笑顔
    スワイプでき、すぐ差し引かれます。支払いコードの原理を知りたくありませんか?

この記事が気に入ったら
QRコードを長押し
5年前にブログで三元演算子のヌルポインタの問題について書きましたが、ついにAlibaba開発マニュアルに含まれました。
してホリスをフォローしください。友達の輪に転送してください。これが私の最大のサポートです。
良い記事、私は❤️を読んでいます

おすすめ

転載: blog.51cto.com/13626762/2544167