インナークラスの概念
クラスは別のクラスやメソッドの中に定義することができ、前者を内部クラス、後者を外部クラスと呼びます。内部クラスもカプセル化の現れです。内部クラスと外部クラスは同じ Java ソース ファイルを共有しますが、コンパイル後、内部クラスは別のバイトコード ファイルを形成します。
public class OutClass {
//外部类
class InnerClass{
//内部类
}
}
上記のコードでは、OutClass が外部クラス、InnerClass が内部クラスです。通常の外部クラスとの最大の違いは、そのインスタンス オブジェクトは単独で存在できず、外部クラスのインスタンス オブジェクトにアタッチする必要があることです。
ローカル内部クラス
ローカル内部クラスは、外部クラスのローカルな場所 (通常はメソッド内) で定義されます。外部クラスのすべての要素にアクセスできます。ローカル変数と同等であるため、アクセス修飾子を追加することはできませんが、最終的な変更は使用できます。スコープは、それが定義されているメソッドまたはコード ブロック内のみです。
class Outer{
//外部类
private int a = 1;//私有属性
private void fun2(){
//私有方法
System.out.println("Outer fun2()");
}
public void fun1(){
System.out.println("Outer fun1()");
final class Inner{
//局部内部类
private int a = 2;
public void funInner(){
System.out.println(a); // 1 外部变量名重名 就近原则
//Outer.this本质上就是外部类的对象,即哪个对象调用了fun1,Outer.this就指向哪个对象
System.out.println(Outer.this.a); // 2
fun2();
}
}
Inner inner = new Inner();
inner.funInner();
}
}
public class InnerClass {
public static void main(String[] args) {
Outer outer = new Outer();
outer.fun1();
}
}
外部クラスとローカル内部クラスのメンバーが同じ名前を持っている場合、デフォルトで近接原則に従います。外部クラスのメンバーにアクセスする場合は、外部クラス名.this. メンバー名 を使用できます。
匿名の内部クラス (強調を強調!!!)
匿名内部クラスはクラス名のない内部クラスを参照し、作成時に new ステートメントを使用して宣言する必要があります。通常、メソッドのパラメータがインターフェイス型で、そのインターフェイスを一度だけ実装する必要がある場合は、それを匿名内部クラスの形式で定義できます。
インターフェイスベースの匿名内部クラス インスタンス:
class Outer1 {
private int a = 10;
public void method() {
//基于接口的匿名内部类
IA person = new IA() {
@Override
public void eat() {
System.out.println("正在吃大餐");
}
};
//查看person的运行类型
System.out.println("person的运行类型:" + person.getClass()); // Outer1$1
person.eat();
}
}
//接口
interface IA {
void eat();
}
class Person implements IA {
@Override
public void eat() {
System.out.println("吃");
}
}
public class AnonInter {
public static void main(String[] args) {
Outer1 outer1 = new Outer1();
outer1.method();
}
}
IA person = new IA() {
@Override
public void eat() {
System.out.println("正在吃大餐");
}
};
//上面这段代码其实就相当于
class Outer1$1 implements IA {
@Override
public void eat() {
System.out.println("正在吃大餐");
}
}
基礎となる jdk が匿名内部クラス アウター 1$1 を作成すると、すぐにアウター 1$1 のインスタンスが作成され、そのアドレスがユーザーに返されます。匿名内部クラスは 1 回のみ使用でき、その後は使用できません。
クラスベースの匿名内部クラスと抽象内部クラスインスタンス:
class Outer2 {
public void method() {
//编译类型:Animal
//运行类型:Outer2$1
Animal animal = new Animal("小白"){
//基于类的匿名内部类
@Override
public void eat() {
System.out.println("匿名内部类重写了eat()");;
}
};
animal.eat();
System.out.println(animal.getClass()); //animal的运行类型 Outer2$1
//编译类型:Robot
//运行类型:Outer2$2
Robot robot = new Robot(){
//基于抽象类的匿名内部类
@Override
void run() {
System.out.println("正在奔跑");
}
};
robot.run();
System.out.println(robot.getClass());// robot的运行类型 Outer2$2
}
}
class Animal implements IC {
String name;
public Animal(String name) {
this.name = name;
}
public void eat(){
System.out.println("Animal 在吃东西");
}
@Override
public void run() {
System.out.println("重写的run()");
}
}
abstract class Robot {
//抽象类
abstract void run();
}
interface IC {
//接口
void run();
}
//测试
public class InterClass {
public static void main(String[] args) {
Outer2 outer2 = new Outer2();
outer2.method();
}
}
匿名内部クラスの詳細 匿名
内部クラスは、クラス定義であると同時にオブジェクトでもあり、構文的にはクラスを定義し、オブジェクトを作成するという特徴があります。
public class AnonClassDatil {
public static void main(String[] args) {
Outer3 outer3 = new Outer3();
outer3.fun();
}
}
class Outer3 {
public void fun(){
Car car = new Car(){
// 运行类型 Outer3$1
@Override
public void speed() {
System.out.println("重写了speed()");;
}
};
car.speed(); //动态绑定
//也可以直接调用
new Car(){
@Override
public void speed() {
System.out.println("直接调用speed()");
}
}.speed();
}
}
class Car {
public void speed() {
System.out.println("Car speed()");
}
}
以下のコードを参照してください
public class InnerExcise {
public static void main(String[] args) {
fun(new IQ() {
//当做实参直接传递 简洁高效
@Override
public void show() {
System.out.println("正在学习Java内部类");
}
});
}
public static void fun(IQ iq) {
//静态方法 形参是接口类型
iq.show();
}
}
interface IQ {
void show();
}
演習:
着信音インターフェイス Bell があり、これには Ring メソッドがあります。携帯電話クラス CellPhone があり、目覚まし時計の機能があります。遅刻」を指定し、別の匿名内部クラスを渡して「すでに遅刻しています」を出力します。
public class InnerExcise1 {
public static void main(String[] args) {
CallPhone callPhone = new CallPhone();
callPhone.alarmClock(new Bell() {
//传递的是实现了Bell接口的匿名内部类
@Override
public void ring() {
System.out.println("起床了要迟到了");
}
});
callPhone.alarmClock(new Bell() {
@Override
public void ring() {
System.out.println("已经迟到了");
}
});
}
}
interface Bell {
void ring();
}
class CallPhone {
public void alarmClock(Bell bell) {
bell.ring(); // 动态绑定
}
}
メンバーの内部クラス
メンバー内部クラスは、外部クラスのメンバー位置で定義され、静的な変更はなく、プライベート メンバーを含む外部クラスのすべてのメンバーにアクセスできます。基本的にはメンバーであるため、任意のアクセス修飾子を追加できます。つまり、メンバ内部クラスとは、静的によって変更されない内部クラスを指し、非静的内部クラスとも呼ばれます。
public class InnerExcise2 {
public static void main(String[] args) {
Outer5 outer5 = new Outer5();
outer5.fun();
}
}
class Outer5 {
private int a = 10;
private class Inner {
// 可以添加任意访问修饰符
public void say() {
System.out.println(a); //可以访问外部类的所有成员,包括私有成员
}
}
public void fun() {
Inner inner = new Inner();
inner.say();
}
}
public class InnerExcise2 {
public static void main(String[] args) {
Outer5 outer5 = new Outer5();
outer5.fun();
//外部其他类 使用成员内部类的几种方式
// 第一种 outer5.new Inner() 相当于是把new Inner()当成一个成员
Outer5.Inner outer51 = outer5.new Inner();
outer51.say();
Outer5.Inner outer52 = outer5.shawOuter5();
outer52.say();
}
}
class Outer5 {
private int a = 10;
public class Inner {
// 可以添加任意访问修饰符
public void say() {
System.out.println(a); //可以访问外部类的所有成员,包括私有成员
}
}
//第二种 定义一个方法 返回一个Inner对象
public Inner shawOuter5() {
return new Inner();
}
public void fun() {
Inner inner = new Inner();
inner.say();
}
}
同名のメンバが存在する場合は近接原則に従い、外部クラスのメンバにアクセスする場合は上記と同様に、外部クラス名.this.メンバ名というアクセス方法となります。
静的内部クラス
静的内部クラスとメンバー内部クラスの定義は似ていますが、 static で変更する必要があるため、静的内部クラスと呼ばれます。静的内部クラスは、Outer のインスタンスに付加されなくなり、完全に独立したクラスとなるため、Outer.this を参照して呼び出すことはできません。ただし、外部クラスのプライベート静的フィールドと静的メソッドにはアクセスできますが、静的内部クラスを外部クラスの外に移動すると、プライベートにアクセスする権限が失われます。
public class StaticInnerClass {
public static void main(String[] args) {
Outer6 outer6 = new Outer6();
outer6.fun1();
//外部其他类访问静态内部类
//静态内部类可以直接通过类名访问
Outer6.Fun fun1 = new Outer6.Fun();
fun1.show();
//通过定义一个方法返回静态内部类
Outer6.Fun fun2 = outer6.getFun();
fun2.show();
}
}
class Outer6 {
private static int a = 99;
private static String str = "java";
static class Fun {
public static int a = 999;
public void show() {
System.out.println(str);
System.out.println(a); //同名成员遵循就近原则
System.out.println(Outer6.a); //通过 外部类名.成员名访问
}
}
public void fun1() {
Fun fun = new Fun();
fun.show();
}
public Fun getFun() {
return new Fun();
}
}
静的内部クラスでは、静的外部クラスの静的プロパティとメソッドのみにアクセスできます。