Deencapsulationのコードをgithubで読んだ。finalを書き換える特殊なコードは書かれていないようだった。実際に、自宅の環境では書き換えに失敗している。自分は、こういうことを予想していた。modifiersの書き換えをしているんじゃないだろうか。finalを外して書き込むとか。ところがそういうのをやっていないようだった。finalフィールドへの書き込み例はネットでも見受けられる。final修飾子を除去するコードを書いて試している。この方法は完璧ではないと感じたことがあるので書いてみる。1そもそも正攻法ではない。Fieldオブジェクトのmodifiersのフィールド名称は実装に依存するから、正式な方法とはいえない。誰でもそう感じるだろう。2書き換えた内容が残らない(Fieldオブジェクトのmodifiersの話)Fieldオブジェクトのmodifiersを変更したとしても、ClassオブジェクトからgetDeclaredFieldし直すと、そのmodifiersは本来の値に戻っている。これはFieldオブジェクトが別物なんだから多少納得がいくだろう。ちなみにFieldクラスのequalsメソッドはmodifiersを評価していないようだ。3modifiersの一貫性が損なわれる(FieldオブジェクトのoverrideFieldAccessorの話)次の例ではまた別のことを考える必要がある。getDeclaredFieldを叩いたのちに、setAcessible(true)して、setに失敗しているコードがまず存在していて、その後、取り直した別のFieldオブジェクトに対してmodifiers書き換え版のコードでsetを試みるとしよう。この場合、書き換えは失敗する。内部のaccessorが持つmodifiers関連変数の一貫性がなくなることだ。逆にmodifierを書き換えるコードを先に成功させてしまえば、accessorは書き換え可能な状態で残る。accessorについては、2度目のgetDeclareFieldでも同じインスタンスが設定されているようだ。ここで言っているaccessorというのはsun.reflect.UnsafeFieldAccessorImpl系の話をしている。内部で型に応じたUnsafeFieldAccessorImplのサブクラスが作られている。setするときは、overrideFieldAccessorフィールドに置かれるっぽい。final付きのFieldの場合とそうではない場合で、setされるaccessorは異なる。isFinal変数を持つクラスと、isReadOnlyを持つクラスがいて、isReadOnlyをfalseに書き換えるとfinal修飾子が付いたまま書き換えることができるようになる。sun.reflect.UnsafeQualifiedStaticFieldAccessorImplちなみに、先にmodifiersを書き換えてfinalがついてない場合は、isReadOnlyを持つクラスは使われていないようだ。(Qualifiedが付かないクラスが使われている)うーん、Javaの実装に依存するなら、成功したのは非OracleのJavaだったからかな。OpenJDK7の実装もOracleと同じっぽい。自宅の環境はOracleのJavaのjdk1.8.0_121(最新)にあげて試した。IBMのJavaでも試したいのでWASDを用意した。fixpack11から標準でJava8っぽいな。Java8およびJava7で試したがやっぱりできないよ。過去の経験はまやかしか?ここからgradleでテストするように変更を加えた。(build.gradleを用意した)すると、どうだろう、テストが成功し始めるではないか。はぁぁぁぁぁぁあ!?落ち着けオレ。凡ミス、modifierの書き換えが一番初めに動いたせいだ。finalのインスタンスをDeencapsulationでgetして、それをMockUp(インスタンス)して期待する動作を書くとかだ。インスタンスを引数に渡すとmockitoのspy相当になる。jmockitのMockUpの場合、インスタンスを書き換えてるからクラスも同じ、setし直しは不要。finalにsetできず困る。finalを書き換える方法については、他にsun.misc.Unsafeを使う方法がネットで調べられる。確かに一番強力な方法であるが、これも正攻法ではない。finalを書き換える方法はない。まやかしがまだ信じられないので追加調査。まやかしではなかったぞ。jmockitの古いバージョンではmodifiersを書き換えとるやないか。GitHubえっと、どのバージョンまで書き換え可能なんだ・・・。1.24まで書き換え可能、1.25から書き換えできない。1.25は2016年6月26日リリース。issues#281でdropしている。jmockitのバージョンをあげるときの悲鳴は不可避や。staticメソッドはあま...2009-11-22コンパイル警告と@SuppressWarningsの対応関係虱潰し!どんなコードでコンパイル警告となるかは、以下のサイトが良く...2009-09-23寝ぼけてたんだろうか、気が付いたらまたコンテナ作ってたorzどういうこった。BlogNoticesArchive参加グループプログラミングはてなブログをはじめよう!kidotakaさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。