一.内部类的分类
1.定义在局部位置上(比如方法内)
1)局部内部类(有类名)
2)匿名内部类(没有类名)
2.定义在外部类的成员位置上
1)成员内部类(没有static)
2)静态内部类(有static)
二.内部类的使用
1.局部内部类的使用
2.匿名内部类
1)为什么要使用匿名内部类
在实际开发中,我们常常遇到这样的情况:一个接口/类的方法的某个实现方式在程序中只会执行一次,但为了使用它,我们需要创建它的实现类/子类去实现/重写。此时可以使用匿名内部类的方式,可以无需创建新的类,减少代码冗余。
下面详细说明一下
interface Person {
public void speak();
}
为了使用该接口的show方法,我们需要去创建一个实现类,同时书写show方法的具体实现方式
如果实现类Interface01Impl全程只使用一次,那么为了这一次的使用去创建一个类,未免太过麻烦。我们需要一个方式来帮助我们摆脱这个困境。匿名内部类则可以很好的解决这个问题。
class A implements Person{
@Override
public void speak() {
System.out.println("aa");
}
}
我们使用匿名内部类
public class innerClass01 {
public static void main(String[] args) {
new Person() {
public void say() {// 匿名内部类自定义的方法say
System.out.println("say方法调用");
}
@Override
public void speak() {// 实现接口的的方法speak
System.out.println("speak方法调用");
}
}.say();
}
}
interface Person {
public void speak();
}
2)匿名内部类的细节
关于匿名内部类还有如下两条规则:
(1)匿名内部类不能是抽象类,因为系统在创建匿名内部类的时候,会立即创建内部类的对象。因此不允许将匿名内部类定义成抽象类。
(2)匿名内部类不等定义构造器(构造方法),因为匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以定义实例初始化块,
(3)调用匿名内部类自定义的方法有两种 像上面的代码new Person{}.方法名 或者在接口中定义
总结一下内部类
是一个类,内部类,没有类名(编译器自动分配)(也不能实例对象去调用他的方法)还是一个对象。
3.匿名内部类的使用
1)实现接口
首先,定义一个匿名类要实现的接口,代码如下
public interface Product{
double getPrice();
String getName();
然后,定义一个实体类,实体类定义一个方法,方法的参数为上述的接口对象,到时候会传入一个匿名类对象,这个匿名类实现了上述创建的接口,代码如下
到这里有一丝疑问 : 方法的参数为上述的接口对象(以为是创建了接口对象,还去搜了下,接口不能实例化,不过可以声明一个接口的引用变量,让它指向一个类的实例,当然那个类要实现了那个接口的。到这里可以看出这里方法的参数是接口的引用变量,因为我们传入了一个匿名内部类对象(所以指向了我们的匿名内部类)
public class Anony{
public void test(Product product){
System.out.println("购买了一个"+product.getName()+",花掉了"+product.getPrice());
}
}
最后测试运行:
pubic class Test{
public static void main(String[] args){
Anony anony=new Anony();
// 注意,此处要传入一个匿名类对象
anony.test(new Product(){
@Override
public double getPrice(){
return 578.6;
}
@Override
public String getName(){
return "联想笔记本";
}
}
);
}
}
输出:
购买了一个联想笔记本,花掉了578.6
总结:此处匿名内部类的作用就是实现了一个接口,创建了一个实现了该接口的类的对象,然后重写了这个接口中的方法。
4.成员内部类
1)细节
2)成员内部类的使用
外部类使用成员内部类的方式
class Outre01{//外部类
private int n1 = 10;
public String name = "张三";
public class Inner01{//内部类
private double sal = 99.8;
private int n1 = 66;
System.out.println("n1 = " + n1 + " name = " + name + " 外部类的 n1=" + Outer.this.n1);
} //当内部类和外部类属性名相同时 可以用Outer.this.n1来访问
public void t1() { //使用成员内部类 //创建成员内部类的对象,然后使用相关的方法 I
nner08 inner01 = new Inner01();
inner08.say();
System.out.println(inner08.sal);
}
}
//然后在通过创建Outer的对象来调用t1方法来使用内部类
外部其他类使用成员内部类的方式
public static void main(String[] args) {
Outer01 outer01 = new Outer01();
outer01.t1();//外部类使用内部类
Outer01.Inner01 inner01 = outer01.new Inner01();//外部其他类使用内部类 第一种
Outer08.Inner08 inner08Instance = outer08.getInner08Instance(); //第二种
inner08Instance.say();
}
第二种在外部类写一个方法返回内部类的对象
class Outer01{
public Inner08 getInner08Instance(){
return new Inner08();
}
}
5.静态内部类
外部其他类使用静态内部类
//因为静态内部类,是可以通过类名直接访问(前提是满足访问权限)
第一种
Outer10.Inner10 inner10 = new Outer10.Inner10(); //这里比成员内部类 少了一步 不用先得到Outerde对象
inner10.say();
第二种 也是创建一个方法返回静态内部类的对象
总结:熟练使用各种内部类的使用