内部类分类:
1.成员内部类
2.局部内部类(包含匿名内部类)
3.静态内部类
成员内部类:
以身体和心脏的关系为例:
/*
* 成员内部类定义格式:
* 修饰符 class 外部类名称{
* 修饰符 class 内部类名称{
* //...
* }
* //...
* }
*
* 注意:内用外,随意访问;外用内,一定需要借助内部类对象。
*
* =======================================
* 如何使用成员内部类:
* 1.间接方式:在外部类的方法中,使用内部类,然后main只是调用外部类的方法。
* 2.直接方式:公式:
* 【外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();】
* */
class Body {//外部类
public class Heart {//成员内部类
//内部类方法
public void beat() {
System.out.println("心脏跳动!");
System.out.println("我叫:" + name);//正确写法!
}
}
//外部类的成员变量
private String name;
//外部类方法
public void methodBody() {
System.out.println("外部类的方法!");
new Heart().beat();//匿名对象使用
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//如果出现了重名现象,格式:
// 外部类名称.this.外部成员变量名
class Outer {
int num = 10;//外部类成员变量
public class Inner {
int num = 20;//内部类成员变量
public void methodInner() {
int num = 30;//内部类方法的局部变量
System.out.println(num);//30局部变量,就近原则
System.out.println(this.num);//20内部类的成员变量
System.out.println(Outer.this.num);//10外部类的成员变量
}
}
}
public class InnerClass {
public static void main(String[] args) {
Body body = new Body();//外部类的对象
//通过外部类的对象,调用外部类的方法,里面间接再使用内部类
body.methodBody();
System.out.println("===================");
Body.Heart heart = new Body().new Heart();
heart.beat();
}
}
运行结果:
局部内部类:
/*
* 局部内部类:一个类定义在一个方法内部
* “局部”:只在当前所属方法内使用。
*
* 格式:
* 修饰符 class 外部类名称{
* 修饰符 返回值类型 外部类方法名称(参数列表){
* class 局部内部类名称{
* //...
* }
* }
* }
*
* 定义一个类时,权限使用规则:
* 1.外部类:public/(default)
* 2.成员内部类:public/protected/(default)/private
* 3.局部内部类:什么都不能写
* */
class Outer {
public void methodOuter() {
class Inner {//局部内部类
int num = 10;
public void methodInner() {
System.out.println(num);
}
}
Inner inner = new Inner();
inner.methodInner();
}
}
/*
* 局部内部类,如果希望访问所在方法的局部变量,那么这个局部变量必须是【有效final】的。
*
*原因:
* 1.new出来的对象在堆内存当中。
* 2.局部变量跟着方法走,在栈当中。
* 3.方法运行结束后,立刻出栈,局部变量跟着消失。
* 4.但是new出来的对象一直存在,直到垃圾回收消失。
* */
class MyOuter {
public void methodOuter() {
final int num = 10;//所在方法的局部变量;从Java8开始,final关键字可以省略。
class MyInner {
public void methodInner() {
System.out.println(num);
}
}
}
}
public class Work {
public static void main(String[] args) {
Outer outer = new Outer();
outer.methodOuter();
}
}
运行结果:
匿名内部类:
/*
* 如果接口的【实现类】(或者是父类的子类),只需要使用唯一的一次,
* 那么这种情况下就可以略掉该类的定义,而改为使用【匿名内部类】。
*
* 匿名内部类的定义格式:
* 接口名称 对象名 = new 接口名称(){
* //覆盖重写所有抽象方法
* };
*
* 解析格式:“new 接口名称(){...}”
* 1.new代表创建对象的动作
* 2.接口名称就是匿名内部类需要实现的哪个接口
* 3.{...}匿名内部类的类容
*
* 注意:
* 1.匿名内部类在创建对现实只能使用唯一一次;如果希望多次创建对象,而且类的内容一样,
* 那么就必须使用单独定义的实现类了。
* 2.匿名对象,在【调用方法】的时候,只能调用唯一一次,如果希望同意对象调用多次方法,
* 那么必须给对象起个名字。
* 3.匿名内部类省略了【实现类/子类名称】,但是匿名对象是省略了【对象名称】。
* 匿名对象和匿名内部类不是一回事!!!
* */
interface MyInterface {
void method1();//抽象方法
void method2();
}
class MyInterfaceImpl implements MyInterface {
@Override
public void method1() {
System.out.println("实现类覆盖重写了方法!");
}
@Override
public void method2() {
}
}
public class Work {
public static void main(String[] args) {
// MyInterfaceImpl iml = new MyInterfaceImpl();
// iml.method();
// MyInterface some = new MyInterface(); 错误写法!
//使用匿名内部类
MyInterface objA = new MyInterface() {//这就是一个匿名内部类:{}之内,没名称
@Override
public void method1() {
System.out.println("匿名内部类实现了方法!111-A");
}
@Override
public void method2() {
System.out.println("匿名内部类实现了方法!111-A");
}
};
objA.method1();
objA.method2();
System.out.println("=================================");
//使用了匿名内部类,而且省略了对象名称,也是匿名对象
new MyInterface() {
@Override
public void method1() {
System.out.println("匿名内部类实现了方法!222-B");
}
@Override
public void method2() {
System.out.println("匿名内部类实现了方法!222-B");
}
}.method1();
//因为匿名对象无法调用第二次方法,所以需要在创建一个匿名内部类的匿名对象
new MyInterface() {
@Override
public void method1() {
System.out.println("匿名内部类实现了方法!222-B");
}
@Override
public void method2() {
System.out.println("匿名内部类实现了方法!222-B");
}
}.method2();
}
}
运行结果:
静态内部类:
定义在类中,加static修饰符
能拥有普通域,但不能访问外部普通域