質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Null

Nullとは、プログラミング言語やデータベースにおけるデータ表現の一種です。コンテキストによって"空"もしくは"長さ0の文字列"、”未知・不明”を意味します。

NullPointerException

null値の参照型変数を参照しようとした場合に投げられる、Javaにおける例外のひとつです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Q&A

解決済

2回答

4241閲覧

【Android】ヌルポインタの例外が出た時の処理

tadanoosakana

総合スコア30

Null

Nullとは、プログラミング言語やデータベースにおけるデータ表現の一種です。コンテキストによって"空"もしくは"長さ0の文字列"、”未知・不明”を意味します。

NullPointerException

null値の参照型変数を参照しようとした場合に投げられる、Javaにおける例外のひとつです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

0グッド

0クリップ

投稿2015/08/19 14:43

編集2015/08/19 14:49

SurfaceViewを使っていたときに
__java.lang.NullPointerException__が発生し、アプリが強制終了しました。
発生した部分のコードは以下です。

lang

1 @Override public void run() 2 { 3 while (thread != null) 4 { 5 process(getHolder()); 6 } 7 } 8 9 private void process(SurfaceHolder holder) 10 { 11 Canvas canvas = holder.lockCanvas(); 12 canvas.drawColor(Color.BLACK); 13 14 hoge.setHoge(canvas); // この行で例外が起きる 15 16 /* 以下続きますが、省略 */ 17

setHogeメソッドはcanvasの参照を他のクラスへ持って行くために使っています。

原因を考えてみたのですが、
参照型にnullが入っていて、それを引数で渡したからだと思うので
以下のように対策しました。

lang

1 private void process(SurfaceHolder holder) 2 { 3 Canvas canvas = holder.lockCanvas(); 4 5 6 if (canvas == null) return; // nullを参照していたら、このメソッドを抜ける 7 8 9 canvas.drawColor(Color.BLACK); 10 hoge.setHoge(canvas); // この行で例外が起きる 11 /* 以下続きますが、省略 */ 12

例外や、ヌルポに詳しくないのですが、
ヌルポは危ないということだけは分かったので、
一旦、メソッドを抜けてしまうというようにしました。

そこで、この例外が起きる理由と
それに対するより良い対策があれば教えて下さい。

参考にしたコード
ここのサンプルの onDraw() が 私のコードの process() の部分です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

いくつか指摘させていただきます。
・指摘1:なぜヌルポが起きているのか
→引数にnullの参照変数をわたすことはできます。ここでnullなのはhogeの方です。nullの参照変数を使ってメソッド呼び出しを行ったためヌルポが発生してしまうのです。

・指摘2:参照型なのにnullが入っている
よく入門書に下記のように書かれています。
Hoge hoge= new Hoge();
これが少なからず、理解を阻んでいます。
上記は下記の2式を省略したものです。
Hoge hoge;//Hoge型参照変数の宣言
hoge = new Hoge();//Hoge型参照変数にインスタンスを代入する。
つまり、参照変数(参照型)はnullになり得るのです。

・指摘3:ヌルポは危ないのか
ヌルポは危ないかといえば確かにそうです。しかし、ヌルポ発生原因の大部分はコーディング誤りです。例えば下記のようなものが挙げられます。
・参照変数に代入し忘れた。
・使用する参照変数にnullを代入した。
・nullを返す可能性があるメソッドに対して、nullチェックを怠った。

・回答1:良い対策一部
コーディング時に参照変数へ確実に代入されていることを確認する。
nullチェックをする。
nullオブジェクトを導入する。

投稿2015/08/19 15:08

yona

総合スコア18155

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tadanoosakana

2015/08/19 15:33

ご指摘2について すいません、書き間違えてました。 別に参照型にnullは入れてはいけないと思っていたわけではないです。 「参照型にnullが入っていて、どこも参照していないのに、それを渡した先で使わせてしまったから」みたいなことを考えていました。 ご指摘3を受けて 少し原因を考えてみました。 ・参照変数に代入し忘れた。 ・使用する参照変数にnullを代入した。 という例について アプリを起動して、まれにこの例外が出ますが、 毎回出るわけでは無いですし、同じコードで実行しても例外が出ない時のほうが多いです。 となると ・nullを返す可能性があるメソッドに対して、nullチェックを怠った。 というケースかと思ったんですが、 この場合はgetHolderメソッド( public SurfaceHolder getHolder() ) がnullを返す可能性があると思うのですが、 「もしgetHolderの戻り値がnullなら」のような条件を組んだとしたら どうするべきなんでしょうか。 もう一度呼びなおすのか、それともメソッドを抜けるのかがわかりません。
yona

2015/08/19 15:43

指摘1に記載している様に(swordoneさんも同様に回答しています)、対策前と後のコードで同様にヌルポが出ているのであれば、一番疑うべきなのは hoge.setHoge(canvas); です。 ここで、hogeはnullになっていないでしょうか。
swordone

2015/08/19 15:49

例外のログはちゃんと読めているでしょうか. 例外が発生した位置も記載されているはずなので,まずそれを確認して下さい.
tadanoosakana

2015/08/22 06:53 編集

よく見ると、発生した場所は3箇所ありました 元をたどると holder.lockCanvas() がnull になり、 そのまま canvas が null になって それを process() に渡しているからと思います。 そのため、コードを以下のようにしてみました。 @Override public void run() { while (thread != null) { SurfaceHolder holder = getHolder(); if (holder == null) continue; process(holder); } } しかし、これでも例外は出てきます。 null の対処法がおかしいのでしょうか。
swordone

2015/08/22 09:35 編集

例外が3箇所で発生しているなんてありえないので,例外ログを載せてください. というか,上の説明や私の回答を全く見ていないような修正をしているように見えます. 明らかにスタックトレースログの読み方を間違えています.
tadanoosakana

2015/08/22 10:20

解決しました。 本当に3箇所でした。 1つ目はhogeはHogeクラスのインスタンスなのですが、 このインスタンスの生成処理をsurfaceCreated()で書いていたのですが、 runメソッドのほうがsurfaceCreated()よりも先に呼ばれる場合があり、 インスタンスが生成されていないのにメンバを呼びだそうとしたからです。 hogeが関わっているところを見なおした時に気が付きました。 ご指摘のおかげです。ありがとうございました。 2つ目はPaintのインスタンスを生成せずに canvas.draw〇〇系のメソッドの引数に渡していたので 当然でした。hoge()が呼び出しているメソッド内の出来事でした。 3つ目は1つ目と同じように クラスのインスタンスを生成していないに メンバを呼びだそうとしていました。 いままで、surfaceCreated() -> surfaceChanged() -> run() の順に呼び出されると 思い込んでいたので、インスタンスが生成される前に呼び出されることがあることに 気が付きませんでした。 本当にご指摘ありがとうございました。 これからは、もっといろんな視点から見ていくようにしていきたいです。
guest

0

そもそもnullとは,参照型変数に対して代入できる,「何もない」状態を表す特殊な値です.
「何もない」もののフィールドを見ようとしたりメソッドを使おうとしたりしてもできないので
NullPointerException,通称ヌルポが発生するわけです.
これが発生するときは,たいていどこかでコーディングをミスっています.

参照型にnullが入っていて、それを引数で渡したからだと思うので

ここで言う「引数で渡した参照型」に該当するのはgetHolder()とcanvasですが,
getHolder()がnullならprocess内のholder.lockCanvas()で,
canvasがnullならcanvas.drawColor(Color.BLACK)でヌルポが発生するはずなので,
どちらもありえません.
なのでここでnullで問題になっているのはhogeということになります.
肝心のhogeがコード上にないのでどういうものかわからないのですが,
こちらのnullチェックをするのが第一の対策ですね.
ヌルポは危険といえば危険ですが,逆に言えばそのようなコードミスを教えてくれるので,
これを含めた例外を上手く扱えれば効率よくデバッグできると思いますよ.

投稿2015/08/19 15:34

swordone

総合スコア20651

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問