Javaでカプセル化を再発見した方法。

Javaは、簡潔で美しい(概念的に)言語であり、この構造をあらゆる種類のフレームワークに拡張できる明確な構造を備えているため、最終的なプログラマーのコードに秩序をもたらすことができると常に考えていました。 そして、何よりもまず、javaは100%OO言語だと思いました! しかし最近、私はコードに出くわし、その後、私は夜に激怒して出かけました。 Javaを知らない人でも理解できるように、コードは完全に単純です。
あるパッケージにクラスAがあるとしましょう:

 package test; public class A { private int x = 33; public void test(){ System.out.println(x); } } 

ご覧のとおり、フィールドxは保護されており、 sunドックによると、このフィールドはサブクラスA、テストパッケージ、または他のパッケージでも表示されません。 したがって、test()メソッドは常に数値33を返すと信じるあらゆる理由があります。さらに、コードでこの仮定を使用し、それに何らかのロジックを結び付けることができます。
次に、他のパッケージにクラスがあります(ただし、同じJVM内にあります)。

 package access; public class X { public void getAccess() throws Exception{ A a = new A(); Field x = a.getClass().getDeclaredField("x"); x.setAccessible(true); x.setInt(a, x.getInt(a)+1); System.out.print("protected field: "); a.test(); } } 

以上です。 A.xフィールドのカプセル化と不変性に関するすべての仮定は払拭されます。 A. test()メソッドは数値34を返すようになりました(そして、何らかのロジックをそれに結び付けた場合、コードは現在正しく動作しそうにありません)。 そして、PLOの3つの戒めの1つであるカプセル化に違反しているように見えることさえあります。 プログラマパッケージjava.lang.reflectは 、すべての有罪です。 このパッケージは、プログラム実行段階でオブジェクトを操作する機会を提供します。 なぜなら このオブジェクトのほとんどすべてのクラスは動的構造で動作するため、動作はかなり遅く、例外的な場合にのみ使用する必要があります。 ただし、その使用の可能性は残り、カプセル化違反は明らかです。

その後、このパッケージを詳しく調べてみると、特別なSecurityManagerクラスがセキュリティとアクセスを維持する役割を担っており、それを実行するとすべてが適切に配置されることがわかりました。 クラスAに静的初期化子を追加する場合:

 public class A { static{ if(System.getSecurityManager()==null) System.setSecurityManager(new SecurityManager()); } 

前の例で判明したそのかすかな耳は通りません。 T.ch. すべてが順調で、JavaはまだOO言語です:)この投稿を書いた唯一のことは、すべてのジャビストに警告することです (これはアクションのシグナルではありません。

開発者、BDI!
実行時にSecurityManagerがない場合、誰でもクラスにクロールして、何でも変更できます!

Source: https://habr.com/ru/post/J43859/


All Articles