描述
一个类的内部又完整的嵌套了另外一个类结构,被嵌套的类称为内部类(inner class),内部类属于类的五大成员(属性、方法、构造器、代码块、内部类) 之一,内部类最大的特点是可以直接访问私有属性,并且可以体现类与类之间的包含关系。
局部内部类
如果类定义在方法或者代码块中,称为局部内部类,无类名的称为匿名内部类。
①可以直接访问外部类的所有成员,包含私有成员
②不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量是不能使用修饰符的。但是可以使用final修饰,因为局部变量也可以使用final
③作用域和局部变量一样
④外部类访问局部内部类的成员,需要先创建对象,再访问(必须在作用域之内)
⑤如果外部类和局部内的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员名)去访问
普通局部内部类
样例代码:
package com.liuranli;
public class test {
public static void main(String[] args) {
new Outer().m1();
}
}
class Outer {
private int n1 = 100;
private void m2() {
System.out.println("Outer m2()");
}
public void m1() {
final class Inner {
private int n1 = 200;
public void f1() {
System.out.println("n1 = " + n1 + "外部类的n1 = " + Outer.this.n1);
System.out.println("Outer.this.hashcode = " + Outer.this);
m2(); //调用外部类的m2方法
}
}
Inner inner = new Inner(); //创建内部类对象
inner.f1(); //执行内部类的f1方法
}
}
样例输出:
n1 = 200外部类的n1 = 100
Outer.this.hashcode = com.liuranli.Outer@614c5515
Outer m2()
局部内部类定义在方法或代码块中,有类名,作用域在方法体或者代码块中,其本质任是一个类。
匿名内部类
样例代码:
package com.liuranli;
public class test {
public static void main(String[] args) {
new Outer02().method();
}
}
class Outer02 {
private int n1 = 10;
public void method() {
//基于接口的匿名内部类
IA tiger = new IA() {
@Override
public void cry() {
System.out.println("老虎在叫唤~");
}
}; //加分号结束
System.out.println("tiger的运行类型=" + tiger.getClass());
tiger.cry();
//基于外部其它类的匿名内部类
Father father = new Father("张三") {
@Override
public void test() {
System.out.println("匿名内部类重写了father类的test方法");
}
};
System.out.println("father的运行类型=" + father.getClass());
father.test();
//基于抽象类的匿名内部类
Animal animal = new Animal() {
@Override
void eat() {
System.out.println("小狗吃骨头");
}
};
System.out.println("animal的运行类型=" + animal.getClass());
animal.eat();
}
}
//接口
interface IA {
public void cry();
}
class Father {
public Father(String name) {
System.out.println("接收到name = " + name);
}
public void test() {
}
}
//抽象类
abstract class Animal {
abstract void eat();
}
样例输出:
tiger的运行类型=class com.liuranli.Outer02$1
老虎在叫唤~
接收到name = 张三
father的运行类型=class com.liuranli.Outer02$2
匿名内部类重写了father类的test方法
animal的运行类型=class com.liuranli.Outer02$3
小狗吃骨头
样例代码2(做实参传递):
package com.liuranli;
/*
* 有一个铃声接口Bell,里面有一个ring方法。
* 有一个手机类Cellphone,具有闹钟功能alarmclock,参数是Bell类型。
* 测试手机类的闹钟功能,通过匿名内部类作为实参。
* */
public class test {
public static void main(String[] args) {
new Cellphone().alarmClock(new Bell() {
@Override
public void ring() {
System.out.println("起床了");
}
});
new Cellphone().alarmClock(new Bell() {
@Override
public void ring() {
System.out.println("上课了");
}
});
}
}
//铃声接口
interface Bell {
public void ring();
}
//手机类
class Cellphone {
public void alarmClock(Bell bell) {
bell.ring();
}
}
样例输出2(做实参传递):
起床了
上课了
匿名内部类使用一次就不能在使用了, jdk 底层在创建匿名内部类时会自动分配一个类名,类名为:外部类名称$序号 组成。
成员内部类
如果类定义在成员位置上,称为成员内部类,使用static修饰过的叫做静态内部类。
①可以直接访问外部类的所有成员,包含私有的
②可以添加任意访问修饰符(public、protected、private),因为它的地位就是一个成员。
③作用域和外部类的其他成员一样。
④外部类访问成员内部类,先创建对象,在访问。
⑤如果外部类和局部内的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员名)去访问。
成员内部类
样例代码:
package com.liuranli;
public class test {
public static void main(String[] args) {
new Outer03().t1();
System.out.println("--------------------");
new Outer03().getInner03Instance().say();
}
}
class Outer03{
private int n1 = 10;
public String name = "张三";
private void hi(){
System.out.println("hi()方法...");
}
//成员内部类
public class Inner03{
private double sal = 99.7;
private int n1 = 55;
public void say(){
System.out.println("n1 = " + n1 + " name = " + name + " 外部类的n1 = " + Outer03.this.n1);
hi();
}
}
//公有的用于返回成员内部类对象的方法
public Inner03 getInner03Instance(){
return new Inner03();
}
public void t1(){
Inner03 inner03 = new Inner03();
inner03.say();
System.out.println(inner03.sal);
}
}
样例输出:
n1 = 55 name = 张三 外部类的n1 = 10
hi()方法...
99.7
--------------------
n1 = 55 name = 张三 外部类的n1 = 10
hi()方法...
静态内部类
样例代码:
package com.liuranli;
public class test {
public static void main(String[] args) {
Outer04.Inner04 inner04 = new Outer04.Inner04();
inner04.say();
System.out.println("--------------------");
Outer04 outer04 = new Outer04();
Outer04.Inner04 inner041 = outer04.getInner04();
inner041.say();
System.out.println("--------------------");
Outer04._getInner04().say();
}
}
class Outer04{
private int n1 = 10;
private static String name = "张三";
private static void cry(){
}
static class Inner04{
private static String name = "zhangsan";
public void say(){
System.out.println("内部类name = " + name + " 外部类name = " + Outer04.name);
cry();
}
}
public Inner04 getInner04(){
return new Inner04();
}
public static Inner04 _getInner04(){
return new Inner04();
}
}
样例输出:
内部类name = zhangsan 外部类name = 张三
--------------------
内部类name = zhangsan 外部类name = 张三
--------------------
内部类name = zhangsan 外部类name = 张三