当一个类的定义出现在另外一个类的类体中,这个类叫做内部类,这个类所在的类叫做外部类
普通内部类:直接将一个类的定义放在另外一个类的类体中
静态内部类:使用static关键字修饰的内部类,隶属于类层级
局部内部类:直接将一个类的定义放在方法体的内部时。
匿名内部类:没有名字的内部类
普通内部类(成员内部类)
/**
* 编程实现普通内部类的定义和使用 --文档注释
*/
public class NormalOuter {
private int cnt = 1;
//定义普通内部类 内部类也属于成员,和成员变量是平级的 并且是对象层级
public class NormalInner {
private int ia = 2;
public NormalInner(){
System.out.println("普通内部类的构造方法体执行到了");
}
public void show() {
System.out.println("外部类中变量cnt的数值为:" + cnt);
System.out.println("内部类的成员变量ia的数值为:" + ia);
}
}
}
public class NormalOuterTest {
public static void main(String[] args) {
//1.声明NormalOuter类型的引用指向该类型的对象
NormalOuter nt1 = new NormalOuter();
//声明NormalOuter类中内部类的引用指向内部类的对象
NormalOuter.NormalInner ni = nt1.new NormalInner();
//调用内部类中的show方法
ni.show();
}
}
普通内部类的构造方法体执行到了
外部类中变量cnt的数值为:1
内部类的成员变量ia的数值为:2
普通内部类需要使用外部类对象来创建对象
如果内部类访问外部类中与本类内部同名的成员变量或方法时,需要使用this关键字
例:
public class NormalOuter {
private int cnt = 1;
//定义普通内部类 内部类也属于成员,和成员变量是平级的 并且是对象层级
public class NormalInner {
private int ia = 2;
private int cnt = 3;
public NormalInner(){
System.out.println("普通内部类的构造方法体执行到了");
}
public void show() {
System.out.println("外部类中变量cnt的数值为:" + cnt); //局部优先原则
System.out.println("内部类的成员变量ia的数值为:" + ia);
}
public void show2(int cnt) {
System.out.println("形参变量cnt = " + cnt); //局部优先原则
System.out.println("内部类中cnt = " + this.cnt);
System.out.println("外部类中cnt = " + NormalOuter.this.cnt);
}
}
}
public class NormalOuterTest {
public static void main(String[] args) {
//1.声明NormalOuter类型的引用指向该类型的对象
NormalOuter nt1 = new NormalOuter();
//声明NormalOuter类中内部类的引用指向内部类的对象
NormalOuter.NormalInner ni = nt1.new NormalInner();
//调用内部类中的show方法
ni.show();
System.out.println("=====================================");
ni.show2(4);
}
}
普通内部类的构造方法体执行到了
外部类中变量cnt的数值为:3
内部类的成员变量ia的数值为:2
=====================================
形参变量cnt = 4
内部类中cnt = 3
外部类中cnt = 1
静态内部类
public class StaticOuter {
private int cnt = 1; //隶属于对象层级
private static int snt = 2; //隶属于类层级
/**
* 定义静态内部类
*/
public static class StaticInner{
private int ia = 3;
public StaticInner() {
System.out.println("静态内部类的构造方法哦");
}
public void show() {
System.out.println("ia = " + ia);
System.out.println("外部类中的snt = " + snt);
//System.out.println("外部类中的cnt = " + cnt); //静态上下文中不能访问非静态的成员
}
}
}
public class StaticOuterTest {
public static void main(String [] args) {
//1.声明StaticInner类型的引用指向该类型对象
StaticOuter.StaticInner st = new StaticOuter.StaticInner(); //静态类属于类层级
//2.调用show方法进行测试
st.show();
}
}
静态内部类的构造方法哦
ia = 3
外部类中的snt = 2
静态内部类的使用:
public class StaticOuter {
private int cnt = 1; //隶属于对象层级
private static int snt = 2; //隶属于类层级
public void show() {
System.out.println("调用外部的show方法");
}
/**
* 定义静态内部类
*/
public static class StaticInner{
private int ia = 3;
private static int snt = 4;
public StaticInner() {
System.out.println("静态内部类的构造方法哦");
}
public void show() {
System.out.println("ia = " + ia);
System.out.println("外部类中的snt = " + snt);
}
public void show2(int snt) {
System.out.println("snt = " + snt);
System.out.println("内部类中的snt = " + StaticInner.snt);
System.out.println("外部类中的snt = " + StaticOuter.snt);
new StaticOuter().show(); //创建一个类变量,提升到类层级就可以访问外部类中的非静态方法
}
}
}
public class StaticOuterTest {
public static void main(String [] args) {
//1.声明StaticInner类型的引用指向该类型对象
StaticOuter.StaticInner st = new StaticOuter.StaticInner(); //静态类属于类层级
//2.调用show方法进行测试
st.show();
System.out.println("=====================================");
st.show2(5);
}
}
=====================================
snt = 5
内部类中的snt = 4
外部类中的snt = 2
调用外部的show方法
静态内部类不能访问外部类的非静态成员
静态内部类可以直接创建对象
没有static就是对象层级,有static就是类层级
局部(方法)内部类的格式
/**
* 编程实现局部内部类的定义和使用
*/
public class AreaOuter {
private int cnt = 1;
public void show(){
//定义一个局部变量进行测试, 从java8开始默认final关键字修饰
final int ic = 4;
//定义局部内部类,只在当前方法体的内部好用
class AreaInner {
private int ia = 2;
public AreaInner(){
System.out.println("局部内部类的构造方法");
}
public void test() {
System.out.println("ia = " + ia);
System.out.println("cnt = " + cnt);
//ic = 5; Error需在定义时添加final,且不能改变
System.out.println("ic= " + ic);
}
}
//声明局部内部类的引用指向局部内部类的对象
AreaInner ai = new AreaInner();
ai.test();
}
}
public class AreaOuterTest {
public static void main(String[] args) {
//1.声明外部类类型的引用指向外部类的对象
AreaOuter ao = new AreaOuter();
//2.通过show方法的调用实现局部内部内容类的定义和使用
ao.show();
}
}
局部内部类的构造方法
ia = 2
cnt = 1
ic= 4
局部内部类特点:
该方法的内部使用
局部内部类可以在方法体内部直接创建对象
局部内部类不能使用访问控制符(public private)和static关键字,方法内部的变量为局部变量,局部变量不能使用访问控制符,成员变量可以
局部内部类可以使用外部方法的局部变量,但是必须是final的。由局部内部类和局部变量的声明周期不同所致。
回调模式
如果一个方法的参数是接口类型,则在调用该方法时,需要创建并传递一个实现此接口类型的对象;而该方法在运行时会调用到参数对象中所实现的方法(接口中定义的)。
public interface AnonymousInterface {
//1.自定义抽象方法
public abstract void show();
}
public class AnonymousInterfaceImpl implements AnonymousInterface {
@Override
public void show() {
System.out.println("这里是接口的实现类!");
}
}
public class AnonymousInterfaceTest {
//假设已有下面的方法
//AnonymousInterface ai = new AnoymousInterfaceImpl();
//接口类型的引用指向实现类型的对象,形成了多态
public static void test(AnonymousInterface ai){
ai.show();
}
public static void main(String[] args){
//形参是一个接口类型的引用,不能直接new接口类型
AnonymousInterfaceTest.test(new AnonymousInterfaceImpl());
}
}
这里是接口的实现类!
经验:
当接口/类类型的引用作为方法的形参时,实参的传递方式有两种:
- 自定义类实现接口/继承类并重写方法,然后创建该类对象作为实参传递;
- 使用上述匿名内部类的语法格式得到接口/类类型的引用即可
匿名内部类的语法格式
pulss AnonymousInterfaceTest{
//假设已有下面的方法
//AnonymousInterface ai = new AnoymousInterfaceImpl();
//接口类型的引用指向实现类型的对象,形成了多态
public static void test(AnonymousInterface ai){
ai.show();
}
public static void main(String[] args) {
//形参是一个接口类型的引用,不能直接new接口类型
//AnonymousInterfaceTest.test(new AnonymousInterfaceImpl());
System.out.println("==============================");
//使用匿名内部类的语法格式来得到接口类型的引用
AnonymousInterface ait = new AnonymousInterface() {
@Override
public void show() {
System.out.println("匿名内部类就是这么玩儿的,虽然你很抽象");
}
};
//从java8开始提出新特性:lambda表达式:(参数列表) -> {方法体}
//AnonymousInterface ait2 = () -> System.out.println("lambda表达式原来如此简单");;
AnonymousInterfaceTest.test(ait);
}
}
匿名内部类就是这么玩儿的,虽然你很抽象