内部类的定义:
将一个类A定义在另一个类B里面,里面的那个类A就称为内部类(InnerClass),类B则称为外部类(OuterClass)。
内部类的使用场景:
类A只在类B中使用,便可以使用内部类的方法。
内部类的分类:
①成员内部类:直接声明在外部类的里面。
>使用static修饰的:静态的成员内部类。
>不使用static修饰的:非静态的成员内部类。
②局部内部类:声明在方法内,构造器内,代码块的内部类。
>匿名的局部内部类。
>非匿名的局部内部类。
成员内部类的理解:
>从类的角度看:
内部可以声明 属性、方法、构造器、代码块、内部类。
可以声明父类,可以实现接口。
可以使用abstract、final修饰。
>从外部类的成员的角度看:
在内部可以调用外部的结构。比如属性、方法等。
作为外部类的成员,可以用四种权限修饰符来修饰。
可以用static来修饰。
创建成员内部类的实例:
以下面的代码为例。
class Person//外部类
{
//静态的成员内部类
static class Dog
{
public void eat()
{
System.out.println("狗吃骨头");
}
}
//非静态的成员内部类
class Bird
{
public void eat()
{
System.out.println("鸟吃虫子");
}
}
}
1.
创建
Person
的静态的成员内部类
Person.Dog dd = new Person.Dog();//Person用来说明Dog属于哪个外部类
dd.eat();
2.创建Person的非静态的成员内部类
Person pp = new Person();
Person.Bird bb = pp.new Bird();//Person用来说明Bird属于哪个外部类,想创建内部类Bird的对象,要拿外部类的对象pp的调用创建对象。
bb.eat();
在成员内部类中调用外部类中的结构:
以下面的代码为例。
class Person//外部类
{
String name;
double weight = 2.0;
int age = 1;
//非静态的成员内部类
class Bird
{
String name = "鸽子";
double weight = 1.0;
public void eat()
{
System.out.println("鸟吃虫子");
}
public void show(double weight)
{
System.out.println("年龄是" + age);//调用的是外部类中的age,值为1。
System.out.println("名字是" + name);//调用的是内部类的name,为 鸽子
System.out.println("体重是" + weight);//调用的是参数的weight,为参数的值
System.out.println("体重是" + this.weight);//调用的是内部类Bird中的weight,值为1.0。
System.out.println("体重是" + Person.this.weight);//调用的是Person中的weight,值为2.0
}
public void show2()
{
eat();//相当于省略了this.
this.eat();//调用的是内部类的eat,输出 鸟吃虫子
Person.this.eat();//调用的是外部类中的eat方法,输出 人吃饭
}
}
public void eat()
{
System.out.println("人吃饭");
}
}
根据内部类中的show方法可知,要调用外部类的属性(或方法),要使用 外部类名.this.外部类的属性(或方法) 的格式。
局部内部类的使用:
public class OutClassTest1
{
//局部内部类的使用
public void method1()
{
//局部内部类
class A
{
}
}
//使用局部内部类的场景
//方式1:
public Comparable getInstance() //Comparable是一个接口,以接口名Comparable为返回类型,即要返回一个Comparable的实现类的对象
{
//内部类用于提供Comparable接口的实现类,用以创建接口实现类的对象
class MyComparable implements Comparable
{
@Override
public int compareTo(Object o)
{
return 0;
}
}
//返回接口的实现类的对象
MyComparable mm = new MyComparable();
return mm;
}
//方式2:
public Comparable getInstance1() //Comparable是一个接口,以接口名Comparable为返回类型,即要返回一个Comparable的实现类的对象
{
//内部类用于提供Comparable接口的实现类,用以创建接口实现类的对象
class MyComparable implements Comparable
{
@Override
public int compareTo(Object o)
{
return 0;
}
}
//返回接口的实现类的对象(匿名)
return new MyComparable();
}
//方式3:(匿名内部类的匿名对象)
public Comparable getInstance2() //Comparable是一个接口,以接口名Comparable为返回类型,即要返回一个Comparable的实现类的对象
{
//返回接口的实现类(匿名)的对象(匿名)
return new Comparable() //接口名为类型名,实际上指的是一个接口的实现类(匿名)的类型
{
@Override
public int compareTo(Object o)
{
return 0;
}
};
}
}
匿名接口的实现类使用了接口的多态性。当然,匿名继承于父类的子类,也是利用子类的多态性。
比如:要编写一个匿名内部类,它继承于Object类,并在匿名内部类中,声明一个方法test打印出“我要玩原神!!!”。
public class ObjectTest
{
public static void main(String[] args)
{
new Object()
{
public void test()
{
System.out.println("我要玩原神!!!");
}
}.test();
}
}
匿名的对象以父类为引用类型,但是后面有写了新的方法,再根据多态性,可知创建的其实是一个匿名的Object类的子类的匿名对象,接着直接在后面加入{},编写此匿名子类的语句写入了test方法,最后直接在编写好后的匿名子类的匿名对象后面直接调用test方法。
匿名的接口的实现类的匿名对象也是一样:
public class OutClassTest2
{
public static void main(String[] args)
{
SubA ss = new SubA();
ss.method();
new A()
{
public void method()
{
System.out.println("匿名实现类的匿名对象实现的method方法");
}
}.method();
}
}
interface A
{
void method();
}
class SubA implements A{
@Override
public void method()
{
System.out.println("SubA中实现的method方法");
}
}