内部クラスとは、外部クラス内でクラスを定義することを指します。クラス名はフォルダーと同じである必要はありません。
内部クラスは、メンバー内部クラス、ローカル内部クラス、静的入れ子クラス、匿名内部クラスに分類されます。
1. メンバー内部クラス
メンバー内部クラスは最も一般的な内部クラスで、次の形式で別のクラス内に配置されるように定義されます:
class Outter { private int age = 12; class Inner { private int age = 13; public void print() { int age = 14; System.out.println("局部变量:" + age); System.out.println("内部类变量:" + this.age); System.out.println("外部类变量:" + Outter.this.age); } } } public class test1 { public static void main(String[] args) { Outter out = new Outter(); Outter.Inner in = out.new Inner(); in.print(); } }
実行結果:
局部变量:14 内部类变量:13 外部类变量:12
この例から、メンバーの内部クラスは外部クラスのメンバーであり、たとえプライベートであっても、外部クラスのすべてのメンバーとメソッドを直接使用できることがわかります。メンバー内部クラスは外部クラスのメンバーに無条件にアクセスできますが、外部クラスはメンバー内部クラスのメンバーにそれほど自由にアクセスできません。外部クラス内のメンバーの内部クラスのメンバーにアクセスしたい場合は、まずメンバーの内部クラスのオブジェクトを作成し、次にこのオブジェクトへの参照を通じてアクセスする必要があります:
class Outter { private int age = 12; public Outter(int age) { this.age = age; getInInstance().print(); //必须先创建成员内部类的对象,再进行访问! } private Inner getInInstance() { return new Inner(); } class Inner { public void print() { System.out.println("内部类没同名,所以直接调用外部类成员变量:" + age); } } } public class test1 { public static void main(String[] args) { Outter out = new Outter(10); } }
実行結果:
内部类没同名,所以直接调用外部类成员变量:10
Innerクラスには、プライベート アクセス権、保護されたアクセス権、パブリック アクセス権、およびパッケージ アクセス権を設定できます。
たとえば、上記の例では、メンバーの内部クラス Inner が private で変更されている場合は、外部クラス内でのみアクセスできます。また、protected で変更されている場合は、どこからでもアクセスできます。 、同じパッケージ内でのみアクセスできます。同じパッケージ内でアクセスするか、外部クラスを継承することによってアクセスできます。デフォルトのアクセス許可の場合は、同じパッケージ内でのみアクセスできます。
これは外部クラスとは少し異なります。外部クラスはパブリックおよびパッケージのアクセス許可によってのみ変更できます。
これは私の個人的な理解です。メンバーの内部クラスは外部クラスのメンバーのように見えるため、クラスのメンバーと同様に複数の権限変更を行うことができます。メンバーの内部クラスには静的変数とメソッドを含めることはできないことに注意してください。なぜなら、メンバー内部クラスは、独自のクラスを作成する前に、まず外部クラスを作成する必要があるからです
2. ローカル内部クラス
ローカル内部クラスは、メソッドまたはスコープで定義されたクラスです。メンバー内部クラスとの違いです。クラスはローカルであるということです。内部クラスへのアクセスはメソッドまたはスコープに限定されます。
メソッド内で定義されている内部クラス:
class Outter { private int age = 12; public void Print(final int x) { //这里局部变量x必须设置为final类型! class Inner { public void inPrint() { System.out.println(x); System.out.println(age); } } new Inner().inPrint(); } } public class test1 { public static void main(String[] args) { Outter out = new Outter(); out.Print(10); } }
実行結果:
10 12
この例では、内部クラスを外部クラスのメソッドに移動し、外部クラスのメソッド内に内部クラスのオブジェクトを生成しています。内部クラスのクラスメソッドを呼び出します。この時点で外部クラスのメソッドにパラメータを渡す必要がある場合は、外部クラスのメソッド パラメータをfinalとして定義する必要があります。
つまり、メソッド内で定義された内部クラスは、メソッド内で最終型のローカル変数にしかアクセスできません。これは、メソッド内で定義されたローカル変数が定数に相当し、そのライフサイクルが のライフサイクルを超えるためです。ローカル変数がfinalに設定されているため、内部クラスでローカル変数の値を変更することはできません。 (ここでインターネットでさまざまな説明を見ましたが、まだ完全に理解できていません==)
スコープ内で定義された内部クラス:
class Outter { private int age = 12; public void Print(final boolean x) { //这里局部变量x必须设置为final类型! if(x){ class Inner { public void inPrint() { System.out.println(age); } } new Inner().inPrint(); } } } public class test1 { public static void main(String[] args) { Outter out = new Outter(); out.Print(true); } }
3. 静的ネストされたクラス
静的部分クラス、ネストされた内部クラスとも呼ばれます。 , 静的に変更された内部クラスです。 static として宣言された内部クラスは、内部クラス オブジェクトと外部クラス オブジェクト間の接続を必要としません。つまり、outer.inner を直接参照できます。つまり、外部クラスや内部クラスを作成する必要はありません。
class Outter { private static int age = 12; static class Inner { public void print() { System.out.println(age); } } } public class test1 { public static void main(String[] args) { Outter.Inner in = new Outter.Inner(); in.print(); } }
static を使用して内部を静的にすると、内部クラスは外部クラスの静的メンバー変数にのみアクセスできるようになり、制限があることがわかります。
第二に、内部クラスは静的であるため、Oututter.Inner は全体として見ることができ、内部クラスのオブジェクトを直接新しいものにすることができます (クラス名を介して static にアクセスします。外部クラスのオブジェクトが静的であるかどうかは関係ありません)。生成されるかどうか)
4. 匿名内部クラス
コードを書くときに匿名内部クラスを使用すると、便利なだけでなく、コードの保守も容易になります。次のコードは Android イベント リスニング コードです:
scan_bt.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub } }); history_bt.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub } });
这段代码为两个按钮设置监听器,这里面就使用了匿名内部类。具体位置是这段:
new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub } }
代码中需要给按钮设置监听器对象,使用匿名内部类能够在实现父类或者接口中的方法情况下同时产生一个相应的对象,但是前提是这个父类或者接口必须先存在才能这样使用。当然像下面这种写法也是可以的,跟上面使用匿名内部类达到效果相同:
private void setListener() { scan_bt.setOnClickListener(new Listener1()); history_bt.setOnClickListener(new Listener2()); } class Listener1 implements View.OnClickListener{ @Override public void onClick(View v) { // TODO Auto-generated method stub } } class Listener2 implements View.OnClickListener{ @Override public void onClick(View v) { // TODO Auto-generated method stub } }
这种写法虽然能达到一样的效果,但是既冗长又难以维护,所以一般使用匿名内部类的方法来编写事件监听代码。同样的,匿名内部类也是不能有访问修饰符和static修饰符的。
匿名内部类是唯一一种没有构造器的类。正因为其没有构造器,所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调。匿名内部类在编译的时候由系统自动起名为Outter$1.class。一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。