内部クラスはJavaで一般的に使用されていますか?これらはネストされたクラスと同じですか?または、これらはJavaでより良いものに置き換えられましたか?バージョン5の本があり、内部クラスを使用した例がありますが、内部クラスが「悪い」と読んだことがあると思いました。
わからないので、考えてみたかったです。
ありがとうございました。
内部クラスはJavaで一般的に使用されていますか?これらはネストされたクラスと同じですか?または、これらはJavaでより良いものに置き換えられましたか?バージョン5の本があり、内部クラスを使用した例がありますが、内部クラスが「悪い」と読んだことがあると思いました。
わからないので、考えてみたかったです。
ありがとうございました。
内部クラスは頻繁に使用され、Javaがクロージャに最も近いものであるため、非常に類似したもの(匿名クラス)が実際に不可欠です。したがって、内部クラスが悪いと聞いた場所を思い出せない場合は、それを忘れてみてください。
それらはそれ自体「悪い」ものではありません。
それらは悪用される可能性があります(たとえば、内部クラスの内部クラス)。私の内部クラスが数行を超えるとすぐに、それを独自のクラスに抽出することを好みます。読みやすさ、場合によってはテストに役立ちます。
すぐにはわからない、覚えておく価値のある落とし穴が1つあります。非static
内部クラスには、周囲の外部クラスへの暗黙の参照(暗黙の'this'参照)があります。これは通常は問題ではありませんが、内部クラスをシリアル化する場合(たとえば、XStreamを使用する場合)、予期しない悲しみを引き起こす可能性があることがわかります。
私は彼らが悪か悪いとは思わない。広く使用されていないかもしれませんが、多くの用途があり、コールバックもその1つです。特別な利点は、それらが外部クラスとは異なるクラスから拡張できるため、多重継承を持つことができることです。
内部クラスの問題の1つは、それらの構文がやや「醜い」ということです。それは何人かの人々を落胆させるものです。ここで仕事をしていると、それらの多くがあります。
内部クラスの良い例は、特定のコレクションタイプのイテレータ実装です。パブリックインターフェイスを実装するクラスですが、別のクラスに関連付けられている場合を除いて、ビジネスは存在しません。これにより、C++ではフレンド演算子を使用せざるを得ないことをモデル化できます。
非静的内部クラスは、パフォーマンスの問題を隠すことができます。それらは、囲んでいるクラスのメンバーフィールドにアクセスできますが、直接ではなく、自動的に作成されるゲッターを介してアクセスできます。これは、囲んでいるクラスのメンバーを内部クラスにコピーするよりも遅くなります。
非静的内部クラスに関するその他の問題については、ここで説明します。
それらは便利で、非常に一般的に使用できます。機能の悪用には注意する必要がありますが、他の言語機能よりも悪用される可能性はそれほど高くありません。
覚えておくべき重要なことは、2つのクラスをより緊密に結合することにより、柔軟性と単純さとまとまりを交換することです。クラスを緊密にバインドしたい場合もありますが、含まれているクラスの外部のインターフェイスからクラスを定義しないことで、他のクラスを現在の埋め込みクラスの場所に透過的にスワップする機能を放棄しています。
次の例を検討してください。
public class OuterClass {
private AnonymousInnerClass anonymousInnerClass = new AnonymousInnerClass() {
@Override
protected void printAboutme() {
System.out.println("AnonymousInnerClass.printAboutMe.........");
Class clazz = this.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected");
message = message + " " + field.getType().getSimpleName();
message = message + " " + field.getName();
System.out.println(message);
}
}
};
public void displayAnonymousInnerClass() {
anonymousInnerClass.printAboutme();
}
public void displayStaticInnerClass() {
NestedStaticClass staticInnerClass = new NestedStaticClass();
staticInnerClass.printAboutMe();
}
public void displayInnerClass() {
InnerClass innerClass = new InnerClass();
innerClass.printAboutMe();
}
public void displayMethodInnerClass(){
class MethodInnerClass {
private String sampleField = "Method Inner Class";
public void printAboutMe() {
System.out.println("MethodInnerClass.printAboutMe.........");
Class clazz = this.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected");
message = message + " " + field.getType().getSimpleName();
message = message + " " + field.getName();
System.out.println(message);
}
}
}
MethodInnerClass methodInnerClass = new MethodInnerClass();
methodInnerClass.printAboutMe();
}
class InnerClass {
private String sampleField = "Inner Class";
public void printAboutMe() {
System.out.println("InnerClass.printAboutMe.........");
Class clazz = this.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected");
message = message + " " + field.getType().getSimpleName();
message = message + " " + field.getName();
System.out.println(message);
}
}
}
abstract class AnonymousInnerClass {
protected String sampleField = "Anonymous Inner Class";
protected abstract void printAboutme();
}
static class NestedStaticClass {
private String sampleField = "NestedStaticClass";
public void printAboutMe() {
System.out.println("NestedStaticClass.printAboutMe.........");
Class clazz = this.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected");
message = message + " " + field.getType().getSimpleName();
message = message + " " + field.getName();
System.out.println(message);
}
}
}
}
この例では、すべてのタイプの非静的ネストクラスと静的ネストクラスの比較があります。ネストされたクラスごとにOuterクラスのdisplayメソッドを実行すると、いくつかのリフレクションコードを持つ各ネストされたクラスのprintAboutMe()メソッドの出力が表示されます。ネストされたクラスのすべてのメンバー変数を出力します。
ネストされていないクラスの場合、コードで宣言された変数文字列以外に1つの追加のメンバー変数があり、実行時にのみ存在します。
たとえば、InnerClassに対して次のコードを実行する場合です。:-
public class NestedClassesDemo {
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
outerClass.displayInnerClass();
}
}
出力は次のようになります:-
InnerClass.printAboutMe.........
private String sampleField
protected OuterClass this$0
クラス(外部クラス)を囲むタイプのミステリーメンバー変数this$0があることに注意してください。
これで、内部クラスが外部クラスへの参照を保持していることがわかります。したがって、内部クラスの参照を他の外部クラスに渡し、参照が解放されないというイメージシナリオでは、OuterClassも参照されるため、リークが発生します。
したがって、これは、適切に使用されない場合、内部クラスの使用を悪くします。
静的内部クラスではそのようなケースはありません。すべてのdisplayメソッドを実行してください。また、コードに問題がある場合は指摘してください。