Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
ピュアJavaだと思った?
残念Androidでした
~いつからAndroidをJavaだと錯覚していた?~
空中清高
空中清高 @soranakk
● 所属:ジャストシステム
○ スマイルゼミ中学生コース
■ ホームアプリ
■ システムアプリ
● Android開発歴:4年半ぐらい
目次
Oracle JavaとAndroid Javaの違い
ArrayListの不思議な現象
ピュアJavaだと思った?残念Androidでした
ArrayListで例外が発生する仕組み
いつからAndroidをJavaだと錯覚していた?
A...
目次
Oracle JavaとAndroid Javaの違い
ArrayListの不思議な現象
ピュアJavaだと思った?残念Androidでした
ArrayListで例外が発生する仕組み
いつからAndroidをJavaだと錯覚していた?
A...
Oracle JavaとAndroid Javaの違い
Android JavaOracle Java
● javaはclassファイルにされ、さらにdexファ
イルにコンパイルされる
● 実行環境はDalvik or ART
● javaはc...
Oracle Javaの世界
JVM
Java実行環境
rt.jar
● Object
● String
● List   … etc
標準ライブラリ
classjava
Android Javaの世界
Dalvik or ART
android.jar
● Object
● String
● List   … etc
標準ライブラリ
dexclass
java
Oracle JavaとAndroid Javaの違い
Android JavaOracle Java
● buildツール
● バイトコード
● 標準ライブラリ
● 実行マシン
● 実行OS
● etc...
Oracle JavaとAndroid Javaの違い
Android JavaOracle Java
● buildツール
● バイトコード
● 標準ライブラリ
● 実行マシン
● 実行OS
● etc...
今日話すのはココ!
標準ライブラ...
Oracle JavaとAndroid Javaの違い
Android JavaOracle Java
rt.jar
● Object
● String
● List   … etc
標準ライブラリ
android.jar
● Object
●...
目次
Oracle JavaとAndroid Javaの違い
ArrayListの不思議な現象
ピュアJavaだと思った?残念Androidでした
ArrayListで例外が発生する仕組み
いつからAndroidをJavaだと錯覚していた?
A...
ArrayListの不思議な現象
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (String str...
ArrayListの不思議な現象
> foo
> bar
> find!
> baz
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.a...
for文中にあることをすると・・・おおっと
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Strin...
for文中にあることをすると・・・おおっと
> foo
> bar
> baz
> ConcurrentModificationException
List<String> list = new ArrayList<>();
list.add(...
ConcurrentModificationException is 何?
● マルチスレッドで同じArrayListを変更したときなどに発生する例外
● シングルスレッドでもループ文などで発生することがある
● 仕組み(概要)
○ Array...
ConcurrentModificationException is 何?
● マルチスレッドで同じArrayListを変更したときなどに発生する例外
● シングルスレッドでもループ文などで発生することがある
● 仕組み(概要)
○ Array...
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (String str : list) {
if ("b...
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (String str : list) {
if ("b...
ArrayListの不思議な現象
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (String str...
ArrayListの不思議な現象
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (String str...
ArrayListの不思議な現象
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (String str...
ArrayListの不思議な現象
● ConcurrentModificationExceptionの発生はbest-effort
● 例外は発生したり、しなかったりする
● たとえばリストの最後から二番目をremoveしたときは発生しない
ArrayListの不思議な現象
● ConcurrentModificationExceptionの発生はbest-effort
● 例外は発生したり、しなかったりする
● たとえばリストの最後から二番目をremoveしたときは発生しない
J...
目次
Oracle JavaとAndroid Javaの違い
ArrayListの不思議な現象
ピュアJavaだと思った?残念Androidでした
ArrayListで例外が発生する仕組み
いつからAndroidをJavaだと錯覚していた?
A...
ピュアJavaだと思った?残念Androidでした
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (S...
ピュアJavaだと思った?残念Androidでした
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (S...
ピュアJavaだと思った?残念Androidでした
> foo
> bar
> baz
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list....
ピュアJavaだと思った?残念Androidでした
> foo
> bar
> baz
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list....
目次
Oracle JavaとAndroid Javaの違い
ArrayListの不思議な現象
ピュアJavaだと思った?残念Androidでした
ArrayListで例外が発生する仕組み
いつからAndroidをJavaだと錯覚していた?
A...
ループ開始
ArrayListで例外が発生する仕組み:概要
ループ開始 変更回数をチェック
ArrayListで例外が発生する仕組み:概要
ループ開始 変更回数をチェック あれ?変更回数が違ってる?
ArrayListで例外が発生する仕組み:概要
ループ開始 変更回数をチェック あれ?変更回数が違ってる?
ArrayListで例外が発生する仕組み:概要
もしかするとあるはずの終端が無いかもしれない?
終わったと思ったのにまだ残ってるかもしれない!?
ループ開始 変更回数をチェック
List警察だ!例外を投げる!
あれ?変更回数が違ってる?
ArrayListで例外が発生する仕組み:概要
もしかするとあるはずの終端が無いかもしれない?
終わったと思ったのにまだ残ってるかもしれない!?
ループ開始 変更回数をチェック
List警察だ!例外を投げる!
あれ?変更回数が違ってる?
ArrayListで例外が発生する仕組み:概要
もしかするとあるはずの終端が無いかもしれない?
終わったと思ったのにまだ残ってるかもしれない!?
概要は...
ループ開始 変更回数をチェック
List警察だ!例外を投げる!
あれ?変更回数が違ってる?
ArrayListで例外が発生する仕組み:概要
もしかするとあるはずの終端が無いかもしれない?
終わったと思ったのにまだ残ってるかもしれない!?
やっぱ...
ArrayListで例外が発生する仕組み
for (String str : list) {
...省略
}
拡張for文は次のように展開されます
https://jcp.org/aboutJava/communityprocess/jsr/t...
ArrayListで例外が発生する仕組み
● ListはmodCountというint値を持っている
● modCountはadd() remove()などでインクリメントされる
● IteratorはmodCountを監視している
Java 9...
ArrayListで例外が発生する仕組み
class Itr implements Iterator<E> {
int expectedModCount = modCount;
public boolean hasNext() {
return...
ArrayListで例外が発生する仕組み
Java 9.0.4 java.util.ArrayList.javaより一部抜粋 (872行あたりから)
final void checkForComodification() {
if (modCo...
例外発生の仕組み Oracle Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (String...
例外発生の仕組み Oracle Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (String...
例外発生の仕組み Oracle Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Iterat...
例外発生の仕組み Oracle Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Iterat...
例外発生の仕組み Oracle Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Iterat...
例外発生の仕組み Oracle Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Iterat...
例外発生の仕組み Oracle Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Iterat...
例外発生の仕組み Oracle Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Iterat...
例外発生の仕組み Oracle Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Iterat...
例外発生の仕組み Oracle Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Iterat...
例外が発生しない仕組み Oracle Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Str...
例外が発生しない仕組み Oracle Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Str...
例外が発生しない仕組み Oracle Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Ite...
例外が発生しない仕組み Oracle Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Ite...
例外が発生しない仕組み Oracle Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Ite...
例外が発生しない仕組み Oracle Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Ite...
例外が発生しない仕組み Oracle Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Ite...
例外が発生しない仕組み Oracle Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Ite...
目次
Oracle JavaとAndroid Javaの違い
ArrayListの不思議な現象
ピュアJavaだと思った?残念Androidでした
ArrayListで例外が発生する仕組み
いつからAndroidをJavaだと錯覚していた?
A...
いつからAndroidをJavaだと錯覚していた?
Java 9.0.4 java.util.ArrayList.javaより一部抜粋 (872行あたりから)
final void checkForComodification() {
if (...
いつからAndroidをJavaだと錯覚していた?
for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) {
String str = iter.next();
…省略
...
class Itr implements Iterator<E> {
protected int limit = ArrayList.this.size;
int expectedModCount = modCount;
public bool...
例外が発生しない仕組み Android Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (St...
例外が発生しない仕組み Android Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (St...
例外が発生しない仕組み Android Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (It...
例外が発生しない仕組み Android Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (It...
例外が発生しない仕組み Android Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (It...
例外が発生しない仕組み Android Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (It...
例外が発生しない仕組み Android Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (It...
例外が発生しない仕組み Android Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (It...
例外発生の仕組み Android Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Strin...
例外発生の仕組み Android Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Strin...
例外発生の仕組み Android Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Itera...
例外発生の仕組み Android Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Itera...
例外発生の仕組み Android Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Itera...
例外発生の仕組み Android Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Itera...
例外発生の仕組み Android Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Itera...
例外発生の仕組み Android Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Itera...
例外発生の仕組み Android Java
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("baz");
for (Itera...
例外発生の仕組み Android Java
List警察だ!例外を投げる!
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("b...
目次
Oracle JavaとAndroid Javaの違い
ArrayListの不思議な現象
ピュアJavaだと思った?残念Androidでした
ArrayListで例外が発生する仕組み
いつからAndroidをJavaだと錯覚していた?
A...
AndroidとJavaはAPIが同じなだけ
Oracle Java
● ConcurrentModificationExceptionの発生はbest-effort
● 例外は発生したり、しなかったりする
● たとえばリストの最後から二番目を...
AndroidとJavaはAPIが同じなだけ
Oracle Java
● ConcurrentModificationExceptionの発生はbest-effort
● 例外は発生したり、しなかったりする
● たとえばリストの最後から二番目を...
目次
Oracle JavaとAndroid Javaの違い
ArrayListの不思議な現象
ピュアJavaだと思った?残念Androidでした
ArrayListで例外が発生する仕組み
いつからAndroidをJavaだと錯覚していた?
A...
その他の事例もあるぞ(先駆者紹介)
● Java と Android の正規表現の動作の違い
   https://qiita.com/KeithYokoma/items/2915a904a18760ee67c4
○ 正規表現ライブラリの違いに...
ご静聴ありがとうございました。
細かい補足
じゃあfor文中にリストから削除したいときはどうしたらいいの?
拡張for文の中でlist#removeは使ってはいけません。
代わりにIteratorでfor文を回して、Iterator#removeを使いましょう。
あるいはKo...
細かい補足
Android N 以降はOpen JDKを使っているって聞いたけど?
はい、その通りです。
でも実はAndroidのJavaはOpen JDKからさらに変更を加えています
そのため、今回紹介したArrayListの操作では
Ope...
細かい補足
Android N より前はHarmonyを使っているって聞いたけど?
はい、その通りです。
でも実はAndroidのJavaはApache Harmonyからさらに変更を加えています
そのため、今回紹介したArrayListの操作...
細かい補足
なんでこんな違いが生まれたの?
コミットコメントやソースコードのコメントを読んでみると
Android側は意図して修正しています。
Open JDKのhasNext()はlistのsizeに依存して
false返したりtrue返した...
ご静聴ありがとうございました。
Upcoming SlideShare
Loading in …5
×

ピュアJavaだと思った?残念androidでした~いつからAndroidをJavaだと錯覚していた?~

3,509 views

Published on

DroidKaigi2018 Room 1 - 2018/02/08 14:00-14:30 の発表資料です。

Published in: Software
  • Be the first to comment

ピュアJavaだと思った?残念androidでした~いつからAndroidをJavaだと錯覚していた?~

  1. 1. ピュアJavaだと思った? 残念Androidでした ~いつからAndroidをJavaだと錯覚していた?~ 空中清高
  2. 2. 空中清高 @soranakk ● 所属:ジャストシステム ○ スマイルゼミ中学生コース ■ ホームアプリ ■ システムアプリ ● Android開発歴:4年半ぐらい
  3. 3. 目次 Oracle JavaとAndroid Javaの違い ArrayListの不思議な現象 ピュアJavaだと思った?残念Androidでした ArrayListで例外が発生する仕組み いつからAndroidをJavaだと錯覚していた? AndroidとJavaはAPIが同じなだけ その他の事例もあるぞ(先駆者紹介)
  4. 4. 目次 Oracle JavaとAndroid Javaの違い ArrayListの不思議な現象 ピュアJavaだと思った?残念Androidでした ArrayListで例外が発生する仕組み いつからAndroidをJavaだと錯覚していた? AndroidとJavaはAPIが同じなだけ その他の事例もあるぞ(先駆者紹介)
  5. 5. Oracle JavaとAndroid Javaの違い Android JavaOracle Java ● javaはclassファイルにされ、さらにdexファ イルにコンパイルされる ● 実行環境はDalvik or ART ● javaはclassファイルにコンパイルされ る ● 実行環境はLinux, Mac OS, WindowsなどのJRE
  6. 6. Oracle Javaの世界 JVM Java実行環境 rt.jar ● Object ● String ● List   … etc 標準ライブラリ classjava
  7. 7. Android Javaの世界 Dalvik or ART android.jar ● Object ● String ● List   … etc 標準ライブラリ dexclass java
  8. 8. Oracle JavaとAndroid Javaの違い Android JavaOracle Java ● buildツール ● バイトコード ● 標準ライブラリ ● 実行マシン ● 実行OS ● etc...
  9. 9. Oracle JavaとAndroid Javaの違い Android JavaOracle Java ● buildツール ● バイトコード ● 標準ライブラリ ● 実行マシン ● 実行OS ● etc... 今日話すのはココ! 標準ライブラリの違い
  10. 10. Oracle JavaとAndroid Javaの違い Android JavaOracle Java rt.jar ● Object ● String ● List   … etc 標準ライブラリ android.jar ● Object ● String ● List   … etc 標準ライブラリ VS
  11. 11. 目次 Oracle JavaとAndroid Javaの違い ArrayListの不思議な現象 ピュアJavaだと思った?残念Androidでした ArrayListで例外が発生する仕組み いつからAndroidをJavaだと錯覚していた? AndroidとJavaはAPIが同じなだけ その他の事例もあるぞ(先駆者紹介)
  12. 12. ArrayListの不思議な現象 List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("baz".equals(str)) { System.out.println("find!"); } System.out.println(str); }
  13. 13. ArrayListの不思議な現象 > foo > bar > find! > baz List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("baz".equals(str)) { System.out.println("find!"); } System.out.println(str); }
  14. 14. for文中にあることをすると・・・おおっと List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("baz".equals(str)) { list.remove(str); } System.out.println(str); }
  15. 15. for文中にあることをすると・・・おおっと > foo > bar > baz > ConcurrentModificationException List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("baz".equals(str)) { list.remove(str); } System.out.println(str); }
  16. 16. ConcurrentModificationException is 何? ● マルチスレッドで同じArrayListを変更したときなどに発生する例外 ● シングルスレッドでもループ文などで発生することがある ● 仕組み(概要) ○ ArrayListは内部的に変更回数を持っている ○ Iteratorで変更回数をチェックしている ○ 変更回数がループ開始時点から変わっていたら例外を投げる 「あるはずの終端が無い!」とか、「終わったと思ったのにまだ残ってる!?」 とかを防ぐための機構。 JavaDocによると、「完全に防げるわけではない、best-effort」 https://docs.oracle.com/javase/9/docs/api/java/util/ConcurrentModificationExc eption.html
  17. 17. ConcurrentModificationException is 何? ● マルチスレッドで同じArrayListを変更したときなどに発生する例外 ● シングルスレッドでもループ文などで発生することがある ● 仕組み(概要) ○ ArrayListは内部的に変更回数を持っている ○ Iteratorで変更回数をチェックしている ○ 変更回数がループ開始時点から変わっていたら例外を投げる 「あるはずの終端が無い!」とか、「終わったと思ったのにまだ残ってる!?」 とかを防ぐための機構。 JavaDocによると、「完全に防げるわけではない、best-effort」 https://docs.oracle.com/javase/9/docs/api/java/util/ConcurrentModificationExc eption.html best-effort?
  18. 18. List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } ArrayListの不思議な現象 > foo > bar > baz > ConcurrentModificationException
  19. 19. List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } ArrayListの不思議な現象 List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } > foo > bar > baz > ConcurrentModificationException
  20. 20. ArrayListの不思議な現象 List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } > foo > bar > baz > ConcurrentModificationException ココが違う
  21. 21. ArrayListの不思議な現象 List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } > foo > bar > baz > ConcurrentModificationException ココが違う > foo > bar
  22. 22. ArrayListの不思議な現象 List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } > foo > bar > baz > ConcurrentModificationException ココが違う 例外が発生しない!? > foo > bar
  23. 23. ArrayListの不思議な現象 ● ConcurrentModificationExceptionの発生はbest-effort ● 例外は発生したり、しなかったりする ● たとえばリストの最後から二番目をremoveしたときは発生しない
  24. 24. ArrayListの不思議な現象 ● ConcurrentModificationExceptionの発生はbest-effort ● 例外は発生したり、しなかったりする ● たとえばリストの最後から二番目をremoveしたときは発生しない Javaは不思議だなぁ Androidでも同じかなぁ?
  25. 25. 目次 Oracle JavaとAndroid Javaの違い ArrayListの不思議な現象 ピュアJavaだと思った?残念Androidでした ArrayListで例外が発生する仕組み いつからAndroidをJavaだと錯覚していた? AndroidとJavaはAPIが同じなだけ その他の事例もあるぞ(先駆者紹介)
  26. 26. ピュアJavaだと思った?残念Androidでした List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } ココが違う
  27. 27. ピュアJavaだと思った?残念Androidでした List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } ココが違う > foo > bar > baz > 例外発生 Oracle Java > foo > bar Oracle Java
  28. 28. ピュアJavaだと思った?残念Androidでした > foo > bar > baz List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } ココが違う > foo > bar > baz > 例外発生 Android JavaOracle Java > foo > bar > 例外発生 > foo > bar Android JavaOracle Java
  29. 29. ピュアJavaだと思った?残念Androidでした > foo > bar > baz List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } ココが違う > foo > bar > baz > 例外発生 Android JavaOracle Java > foo > bar > 例外発生 > foo > bar Android JavaOracle Java JavaとAndroidで結果が違う
  30. 30. 目次 Oracle JavaとAndroid Javaの違い ArrayListの不思議な現象 ピュアJavaだと思った?残念Androidでした ArrayListで例外が発生する仕組み いつからAndroidをJavaだと錯覚していた? AndroidとJavaはAPIが同じなだけ その他の事例もあるぞ(先駆者紹介)
  31. 31. ループ開始 ArrayListで例外が発生する仕組み:概要
  32. 32. ループ開始 変更回数をチェック ArrayListで例外が発生する仕組み:概要
  33. 33. ループ開始 変更回数をチェック あれ?変更回数が違ってる? ArrayListで例外が発生する仕組み:概要
  34. 34. ループ開始 変更回数をチェック あれ?変更回数が違ってる? ArrayListで例外が発生する仕組み:概要 もしかするとあるはずの終端が無いかもしれない? 終わったと思ったのにまだ残ってるかもしれない!?
  35. 35. ループ開始 変更回数をチェック List警察だ!例外を投げる! あれ?変更回数が違ってる? ArrayListで例外が発生する仕組み:概要 もしかするとあるはずの終端が無いかもしれない? 終わったと思ったのにまだ残ってるかもしれない!?
  36. 36. ループ開始 変更回数をチェック List警察だ!例外を投げる! あれ?変更回数が違ってる? ArrayListで例外が発生する仕組み:概要 もしかするとあるはずの終端が無いかもしれない? 終わったと思ったのにまだ残ってるかもしれない!? 概要はわかったけど、 まだよくわかんないなぁ
  37. 37. ループ開始 変更回数をチェック List警察だ!例外を投げる! あれ?変更回数が違ってる? ArrayListで例外が発生する仕組み:概要 もしかするとあるはずの終端が無いかもしれない? 終わったと思ったのにまだ残ってるかもしれない!? やっぱエンジニアだしコード で理解したい
  38. 38. ArrayListで例外が発生する仕組み for (String str : list) { ...省略 } 拡張for文は次のように展開されます https://jcp.org/aboutJava/communityprocess/jsr/tiger/enhanced-for.html for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); ...省略 }
  39. 39. ArrayListで例外が発生する仕組み ● ListはmodCountというint値を持っている ● modCountはadd() remove()などでインクリメントされる ● IteratorはmodCountを監視している Java 9.0.4 java.util.ArrayList.javaより一部抜粋 (872行あたりから) for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); …省略 } public Iterator<E> iterator() { return new Itr(); } class Itr implements Iterator<E> { int expectedModCount = modCount; …省略 }
  40. 40. ArrayListで例外が発生する仕組み class Itr implements Iterator<E> { int expectedModCount = modCount; public boolean hasNext() { return cursor != size; } public E next() { checkForComodification(); int i = cursor; ...省略 cursor = i + 1; return (E) elementData[lastRet = i]; } …省略 Java 9.0.4 java.util.ArrayList.javaより一部抜粋 (872行あたりから) for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); …省略 }
  41. 41. ArrayListで例外が発生する仕組み Java 9.0.4 java.util.ArrayList.javaより一部抜粋 (872行あたりから) final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); …省略 } class Itr implements Iterator<E> { int expectedModCount = modCount; public boolean hasNext() { return cursor != size; } public E next() { checkForComodification(); int i = cursor; ...省略 cursor = i + 1; return (E) elementData[lastRet = i]; } …省略
  42. 42. 例外発生の仕組み Oracle Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("baz".equals(str)) { list.remove(str); } System.out.println(str); }
  43. 43. 例外発生の仕組み Oracle Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される
  44. 44. 例外発生の仕組み Oracle Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される
  45. 45. 例外発生の仕組み Oracle Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "baz"のときcursor = 3
  46. 46. 例外発生の仕組み Oracle Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "baz"のときcursor = 3 remove(str)でmodCount++, size = 2
  47. 47. 例外発生の仕組み Oracle Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "baz"のときcursor = 3 remove(str)でmodCount++, size = 2 次のhasNext()はcursor != size == true で継続
  48. 48. 例外発生の仕組み Oracle Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "baz"のときcursor = 3 remove(str)でmodCount++, size = 2 次のhasNext()はcursor != size == true で継続 next()のcheckForComodification()で modCount != expectedModCount == true
  49. 49. 例外発生の仕組み Oracle Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "baz"のときcursor = 3 remove(str)でmodCount++, size = 2 次のhasNext()はcursor != size == true で継続 next()のcheckForComodification()で modCount != expectedModCount == true ん~・・・
  50. 50. 例外発生の仕組み Oracle Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "baz"のときcursor = 3 remove(str)でmodCount++, size = 2 次のhasNext()はcursor != size == true で継続 next()のcheckForComodification()で modCount != expectedModCount == true 変わってる
  51. 51. 例外発生の仕組み Oracle Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "baz"のときcursor = 3 remove(str)でmodCount++, size = 2 次のhasNext()はcursor != size == true で継続 next()のcheckForComodification()で modCount != expectedModCount == true List警察だ!例外を投げる! 変わってる
  52. 52. 例外が発生しない仕組み Oracle Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("bar".equals(str)) { list.remove(str); } System.out.println(str); }
  53. 53. 例外が発生しない仕組み Oracle Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される
  54. 54. 例外が発生しない仕組み Oracle Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される
  55. 55. 例外が発生しない仕組み Oracle Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "bar"のときcursor = 2
  56. 56. 例外が発生しない仕組み Oracle Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "bar"のときcursor = 2 remove(str)でmodCount++, size = 2
  57. 57. 例外が発生しない仕組み Oracle Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "bar"のときcursor = 2 remove(str)でmodCount++, size = 2 次のhasNext()はcursor != size == false でループ終了
  58. 58. 例外が発生しない仕組み Oracle Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "bar"のときcursor = 2 remove(str)でmodCount++, size = 2 次のhasNext()はcursor != size == false でループ終了 next()は呼ばれないので checkForComodification()は呼ばれない
  59. 59. 例外が発生しない仕組み Oracle Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } ・・・ 拡張for文が展開される str == "bar"のときcursor = 2 remove(str)でmodCount++, size = 2 次のhasNext()はcursor != size == false でループ終了 next()は呼ばれないので checkForComodification()は呼ばれない
  60. 60. 目次 Oracle JavaとAndroid Javaの違い ArrayListの不思議な現象 ピュアJavaだと思った?残念Androidでした ArrayListで例外が発生する仕組み いつからAndroidをJavaだと錯覚していた? AndroidとJavaはAPIが同じなだけ その他の事例もあるぞ(先駆者紹介)
  61. 61. いつからAndroidをJavaだと錯覚していた? Java 9.0.4 java.util.ArrayList.javaより一部抜粋 (872行あたりから) final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); …省略 } class Itr implements Iterator<E> { int expectedModCount = modCount; public boolean hasNext() { return cursor != size; } public E next() { checkForComodification(); int i = cursor; ...省略 cursor = i + 1; return (E) elementData[lastRet = i]; } …省略
  62. 62. いつからAndroidをJavaだと錯覚していた? for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); …省略 } class Itr implements Iterator<E> { protected int limit = ArrayList.this.size; int expectedModCount = modCount; public boolean hasNext() { return cursor < limit; } public E next() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); int i = cursor; ...省略 cursor = i + 1; return (E) elementData[lastRet = i]; } ...省略 Android 26 java.util.ArrayList.javaより一部抜粋 (833行あたりから)
  63. 63. class Itr implements Iterator<E> { protected int limit = ArrayList.this.size; int expectedModCount = modCount; public boolean hasNext() { return cursor < limit; } public E next() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); int i = cursor; ...省略 cursor = i + 1; return (E) elementData[lastRet = i]; } ...省略 いつからAndroidをJavaだと錯覚していた? limitが追加され、 hasNext()の条件が変わっている listのsizeが変わっても、limitは固 定されているので hasNext()の動作が変わった! for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); …省略 } Android 26 java.util.ArrayList.javaより一部抜粋 (833行あたりから)
  64. 64. 例外が発生しない仕組み Android Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("baz".equals(str)) { list.remove(str); } System.out.println(str); }
  65. 65. 例外が発生しない仕組み Android Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される
  66. 66. 例外が発生しない仕組み Android Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される
  67. 67. 例外が発生しない仕組み Android Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "baz"のときcursor = 3
  68. 68. 例外が発生しない仕組み Android Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "baz"のときcursor = 3 remove(str)でmodCount++, size = 2だけどlimit = 3のまま
  69. 69. 例外が発生しない仕組み Android Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "baz"のときcursor = 3 remove(str)でmodCount++, size = 2だけどlimit = 3のまま 次のhasNext()はcursor < limit == false でループ終了
  70. 70. 例外が発生しない仕組み Android Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "baz"のときcursor = 3 remove(str)でmodCount++, size = 2だけどlimit = 3のまま 次のhasNext()はcursor < limit == false でループ終了 next()は呼ばれないので modCount != expectedModCount はチェックされない
  71. 71. 例外が発生しない仕組み Android Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("baz".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "baz"のときcursor = 3 remove(str)でmodCount++, size = 2だけどlimit = 3のまま 次のhasNext()はcursor < limit == false でループ終了 next()は呼ばれないので modCount != expectedModCount はチェックされない ・・・
  72. 72. 例外発生の仕組み Android Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("bar".equals(str)) { list.remove(str); } System.out.println(str); }
  73. 73. 例外発生の仕組み Android Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (String str : list) { if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される
  74. 74. 例外発生の仕組み Android Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される
  75. 75. 例外発生の仕組み Android Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "bar"のときcursor = 2
  76. 76. 例外発生の仕組み Android Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "bar"のときcursor = 2 remove(str)でmodCount++, size = 2だけどlimit = 3のまま
  77. 77. 例外発生の仕組み Android Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "bar"のときcursor = 2 remove(str)でmodCount++, size = 2だけどlimit = 3のまま 次のhasNext()はcursor < limit == true で継続
  78. 78. 例外発生の仕組み Android Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "bar"のときcursor = 2 remove(str)でmodCount++, size = 2だけどlimit = 3のまま 次のhasNext()はcursor < limit == true で継続 next()で modCount != expectedModCount == true
  79. 79. 例外発生の仕組み Android Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } ん~・・・ 拡張for文が展開される str == "bar"のときcursor = 2 remove(str)でmodCount++, size = 2だけどlimit = 3のまま 次のhasNext()はcursor < limit == true で継続 next()で modCount != expectedModCount == true
  80. 80. 例外発生の仕組み Android Java List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "bar"のときcursor = 2 remove(str)でmodCount++, size = 2だけどlimit = 3のまま 次のhasNext()はcursor < limit == true で継続 next()で modCount != expectedModCount == true 変わってる
  81. 81. 例外発生の仕組み Android Java List警察だ!例外を投げる! List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("bar".equals(str)) { list.remove(str); } System.out.println(str); } 拡張for文が展開される str == "bar"のときcursor = 2 remove(str)でmodCount++, size = 2だけどlimit = 3のまま 次のhasNext()はcursor < limit == true で継続 next()で modCount != expectedModCount == true 変わってる
  82. 82. 目次 Oracle JavaとAndroid Javaの違い ArrayListの不思議な現象 ピュアJavaだと思った?残念Androidでした ArrayListで例外が発生する仕組み いつからAndroidをJavaだと錯覚していた? AndroidとJavaはAPIが同じなだけ その他の事例もあるぞ(先駆者紹介)
  83. 83. AndroidとJavaはAPIが同じなだけ Oracle Java ● ConcurrentModificationExceptionの発生はbest-effort ● 例外は発生したり、しなかったりする ● たとえばリストの最後から二番目をremoveしたときは発生しない Android Java ● ConcurrentModificationExceptionの発生はbest-effort ● 例外は発生したり、しなかったりする ● たとえばリストの最後をremoveしたときは発生しない
  84. 84. AndroidとJavaはAPIが同じなだけ Oracle Java ● ConcurrentModificationExceptionの発生はbest-effort ● 例外は発生したり、しなかったりする ● たとえばリストの最後から二番目をremoveしたときは発生しない Android Java ● ConcurrentModificationExceptionの発生はbest-effort ● 例外は発生したり、しなかったりする ● たとえばリストの最後をremoveしたときは発生しない 標準ライブラリが違う!
  85. 85. 目次 Oracle JavaとAndroid Javaの違い ArrayListの不思議な現象 ピュアJavaだと思った?残念Androidでした ArrayListで例外が発生する仕組み いつからAndroidをJavaだと錯覚していた? AndroidとJavaはAPIが同じなだけ その他の事例もあるぞ(先駆者紹介)
  86. 86. その他の事例もあるぞ(先駆者紹介) ● Java と Android の正規表現の動作の違い    https://qiita.com/KeithYokoma/items/2915a904a18760ee67c4 ○ 正規表現ライブラリの違いに解説されています ● Android Javaの正規表現の落とし穴    https://www.ecoop.net/memo/archives/regular-expression-problem-o-android-java.html ○ こちらも正規表現ですが、Stringクラスの違いについて解説されています
  87. 87. ご静聴ありがとうございました。
  88. 88. 細かい補足 じゃあfor文中にリストから削除したいときはどうしたらいいの? 拡張for文の中でlist#removeは使ってはいけません。 代わりにIteratorでfor文を回して、Iterator#removeを使いましょう。 あるいはKotlinのfilterを使うと良いです。 List<String> list = new ArrayList<>(); list.add("foo"); list.add("bar"); list.add("baz"); for (Iterator<String> iter = list.iterator(); iter.hasNext(); ) { String str = iter.next(); if ("baz".equals(str)) { iter.remove(); } System.out.println(str); }
  89. 89. 細かい補足 Android N 以降はOpen JDKを使っているって聞いたけど? はい、その通りです。 でも実はAndroidのJavaはOpen JDKからさらに変更を加えています そのため、今回紹介したArrayListの操作では Open JDK != Android Java となります。 Open JDKだと思った? 残念Androidでした コミットログ https://android.googlesource.com/platform/libcore/+/b10b2a3ab693cfd6156d06ffe4e00ce69b9c9194
  90. 90. 細かい補足 Android N より前はHarmonyを使っているって聞いたけど? はい、その通りです。 でも実はAndroidのJavaはApache Harmonyからさらに変更を加えています そのため、今回紹介したArrayListの操作では Apache Harmony != Android Java となります。 Apache Harmonyだと思った? 残念Androidでした コミットログ https://android.googlesource.com/platform/libcore/+/7de2d41b95fc968b0ccc530c28d66f003ff9ab2a
  91. 91. 細かい補足 なんでこんな違いが生まれたの? コミットコメントやソースコードのコメントを読んでみると Android側は意図して修正しています。 Open JDKのhasNext()はlistのsizeに依存して false返したりtrue返したりするので、固定させるために修正したみたいです。 コミットログ https://android.googlesource.com/platform/libcore/+/b10b2a3ab693cfd6156d06ffe4e00ce69b9c9194 ソースコードのコメント https://android.googlesource.com/platform/libcore/+/master/ojluni/src/main/java/java/util/ArrayList.jav a#841
  92. 92. ご静聴ありがとうございました。

×