内部类,从名字上就可以看出,是定义在外部类里的类,可以更加详细地说明某个事物的特征,举个例子,就像一个人(把他定义为一个类[外部类]),这个人有大脑、肝脏、心脏等器官,这些器官都有自己特有的属性,但又必须待在身体里面,而不能单独列出来(单创一个类),这时就要创建内部类了。内部类按是否有名称可分为:有名内部类和匿名内部类,
class Body{ //外部类
double bloodFlow = 13.5;//外部类成员变量
class Heart{ //有名内部类
double heartRate = 70;
void beat(){
System.out.println("每分钟跳动70次");
}
}
public static void main(String[] args) {
Body body = new Body();
Heart heart = body.new Heart(); //调用内部类
// Body.Heart heart = new Body().new Heart(); 也可以这样调用(因为该内部类是非静态的,不能直接调用,需要通过创建对象来调用)
System.out.println(heart.heartRate); //输出结果:70
heart.beat(); //输出结果:每分钟跳动70次
}
}
该程序编译后会生成两个文件:Body.class 和 Body$Heart.class
其实上面的内部类也是非静态内部类,所以也就有静态内部类:
class Body{ //外部类
static class Brain{ //静态内部类
void happen(){
System.out.println("大脑每秒发生10万次化学反应");
}
}
public static void main(String[] args) {
// Body body = new Body();(在一个外部类中调用时不需要这行代码)
Brain brain = new Brain(); //调用静态内部类
// Body.Heart heart = new Body.Heart(); 也可以这样调用(因为该内部类是静态的,所以可以直接调用)
brain.happen(); //输出结果:大脑每秒发生10万次化学反应
}
}
匿名内部类,顾名思义就是没有名字的内部类,想一下一个没有名字的类该怎么调用它?怎么创建对象?肯定都不能实现了,所以匿名内部类一定要和创建对象一起存在,此时的匿名内部类也就是上转型对象(所以无法调用匿名内部类中新增的属性和方法),且跟在new后面的若是“类”,则该匿名内部类是其子类,若跟在new后面的是“接口”,则该匿名内部类是其实现类。
我们再想一下在多态中,子类要重写父类的方法,但首要前提就是创建一个子类,然后重写,再调用。这样会很麻烦,而且如果就几个或一个抽象方法时,再单独创建一个子类很浪费,所以此种情况下就可以考虑用匿名内部类了(也就是说匿名内部类通常用作实现或重写接口或父类中的抽象方法)
public interface IBlood{
void cycle();
}
class Body{
static IBlood blood = new IBlood(){ //从这个大括号到对应的大括号之间就是匿名内部类,它可以直接作为一个整体去使用
@Override
public void cycle(){
System.out.println("血液循环");
}
}; //注意:要加英文分号
public static void main(String[] args) {
blood.cycle(); //输出结果:血液循环
}
}
该程序编译时创建三个文件:IBlood.class文件、Body.class文件、Body$1.class文件。
总之匿名内部类要和创建对象一起使用,多用于继承其他类或实现接口,对继承方法进行重写或实现,因为不用另创建一个单独的子类,所以就简化了代码
最后补充一点内部类的访问权限,外部类或接口的访问权限只能是public或默认的,而内部类四种访问权限都可以,但局部内部类跟局部变量一样 不允许添加任何访问权限:
class Out{//只能是public或默认的
protected Class In{//四种都可以
}
public static void main(String[] args) {
Class PartIn{//不可添加任何访问权限
}
}
}