dart

Non-nullable instance field ‘変数’ must be initializedエラーについて

結論から

何パターンかあります。

■修正前


class _MyHomePageState extends State {
   String _test; //←ここでエラー

  @override
  void initState() {
    _test= "";
    super.initState();
  }
(省略)
}

■修正パターン1(lateを宣言する)


class _MyHomePageState extends State {
   late String _test; //←lateを追加

  @override
  void initState() {
    _test= "";
    super.initState();
  }
(省略)
}

■修正パターン2(初期値にnull以外をセットする)


class _MyHomePageState extends State {
   String _test = ""; //←初期値にnull以外をセット

  @override
  void initState() {
    _test= "";
    super.initState();
  }
(省略)
}

■修正パターン3(修飾子『?』をつける)


class _MyHomePageState extends State {
   String? _test; //←修飾子『?』をつける

  @override
  void initState() {
    _test= "";
    super.initState();
  }
(省略)
}

原因(ザックリ解説)

Flutter2のバージョンが上がり、Null safetyという文法が有効になったためです。

詳しい解説は他の記事に譲りますが、

ざっくりいうと

Nullを変数にセットするのは原則禁止にして以下のような
Nullを考慮した実装をしなければならなくなりました。

  • 特別な修飾子(?・!・late・required)
  • IF文でのNullチェック
  • 演算子 ??でのNullチェック
  • 定義時にNull以外の値をセットしておく

などなど・・・

今回の例は

  • 修飾子「?」「late」をつける。
  • 定義時にNull以外の値をセットしておく

などの方法で回避できます。

修飾子「?」 の意味は?

修飾子『?』の意味は

Nullを許可する

という意味です。

上記の説明の通り「Null Safety」により、

Nullを変数に入れるのは原則禁止になりました。

しかし、修飾子『?』をつけることによってその変数に関してはNullをセットすることを許可しています。

修正パターン3の例をもう一度みてます。

修正パターン3


class _MyHomePageState extends State {
   String? _test; //←修飾子『?』をつける

  @override
  void initState() {
    _test= "";
    super.initState();
  }
(省略)
}

この例では3行目、宣言時に変数に何も設定されていませんね。

何も入っていないということは、言い換えるとNullが入っている状態ということです。

つまり『Null Safety』の原則に反しているわけです。

なので、今回のエラーが発生します。

修飾子『?』をつけるとNullを許可するようになるので、エラーが解消されるわけです。

修飾子『late』の意味は

修飾子『late』の意味はザックリいうと

Null以外の値を後で設定すること

を宣言しています。

修正パターン1の例をもう一度みてます。


class _MyHomePageState extends State {
   late String _test; //←lateを追加

  @override
  void initState() {
    _test= "";
    super.initState();
  }
(省略)
}

『Null Safety』の導入により、変数を宣言した場合、初期値はNullなのでエラーとなりますがlateを宣言することで、一旦回避できます。

宣言時には初期値はセットしておく必要はなく、必ず後で初期値以外の値を設定する場合に使います。

上記の例も『_MyHomePageState』が呼び出されるたびに必ずinitState()が呼ばれるようになっていて、そこに『_test= “”;』しています、

つまり、必ずnull以外がセットされるソースコードになっていますよね。

ご存じの通り「late」は日本語で「後で」という意味です。

Null safetyという文法に対して、

Nullは『後で』設定するからエラーを表示しなくて良いですよ

と伝えているのが修飾子「late」だと思えば覚えやすいかもしれません。

Flutterあるある

公式サイトやブログのサンプルコピペしただけなのにエラーが出た!

っていう事象は大体この「Null safety」が悪さをしていることが多いです。

2021年5月20日以降から 「Dart 2.13」になり、「Null safety」が必ず効くようになったので、

それ以降のサンプルプログラムは動かない可能性があると思った方が良いです。

書籍購入の際も注意

そもそもFlutterは文法が変わってくと思われるので書籍を購入することはお勧めしません。

もし、購入するのであれば、新しいものを購入した方が良いです。

巻末の版数をみて2021年6月以降のものを対象に購入を検討することをお勧めします。

ちなみに以下の書籍は初版が2021年8月24日でNull Safetyに関する説明がありました。
(2ページ程度だけですが、スッキリまとまっていると思います。)