内部类
内部类的基本概念
- 当一个类的定义出现在另外一个类的类体中时,那么这个类叫做内部类(Inner),而这个内部类所在的类叫做外部类(Outer)
类中的内容:成员变量 成员方法 构造方法 静态成员 构造块和静态代码块 内部类
实际作用
当一个类存在的价值仅仅是为了某一个类单独服务时,那么就可以将这个类定义为所服务类中的内部类,这样可以隐藏该类的实现细节并且可以方便你的访问外部类的私有成员而不再需要提供公有的get和set方法
内部类的分类
普通内部类-直接将一个类的定义在另外一个类的类体中
- 静态内部类-使用static关键字修饰的内部类,隶属于类层级
- 局部内部类-直接将一个类的定义放在方法体的内部时
-
普通内部类的定义
```java 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) { //声明NormalOuter类型的引用指向该类型的对象 NormalOuter no=new NormalOuter(); //声明NormalOuter类中内部类的引用指向内部类的对象 NormalOuter.NormalInner ni=no.new NormalInner(); ni.show(); } }
<a name="YCD4W"></a>
### 普通内部类的使用方式
- 普通内部类和普通类一样可以定义成员变量 成员方法以及构造方法等
- 普通内部类和普通类一样可以使用final和abstract关键字修饰
- 普通内部类还可以使用private 或protected关键字修饰
- 普通内部类需要使用外部类对象来创建对象
- 如果内部类访问外部类中与本类内部同名的成员变量方法时,需要用this关键字
![](https://cdn.nlark.com/yuque/0/2020/png/776784/1603077119688-526825bd-a1c6-4111-b694-33b156b2219d.png#align=left&display=inline&height=361&margin=%5Bobject%20Object%5D&originHeight=361&originWidth=480&size=0&status=done&style=none&width=480)
<a name="3zGN4"></a>
### 静态内部类的定义
<a name="fJ0pW"></a>
#### ![](https://cdn.nlark.com/yuque/0/2020/png/776784/1603077210355-96f28f04-7b9d-4d7b-8cf6-70f179a7d5e3.png#align=left&display=inline&height=279&margin=%5Bobject%20Object%5D&originHeight=279&originWidth=508&size=0&status=done&style=none&width=508)
```java
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);//3
System.out.println("外部类中的snt="+snt);//2
//System.out.println("外部类的cnt="+cnt);//Errot 静态上下文中不能访问非静态的的成员,因为此时可能还没有创建对象
}
}
}
-------------------------------------
public class StaticOuterTest {
public static void main(String[] args) {
//1.声明StaticInner类型的引用指向该类型的对象
StaticOuter.StaticInner si=new StaticOuter.StaticInner();
si.show();
}
}
静态内部类的使用方式
- 静态内部类不能直接访问外部类的非静态成员
- 静态内部类可以直接创建对象
如果静态内部类访问外部类中与本类内同名的成员变量或方法时,需要使用类名.的方式访问
局部内部类的定义
```java public class AreaOuter { private int cnt=1; public void show(){
//定义局部内部类,只在当前方法体的内部使用
class AreaInner{
private int ia=1;
public AreaInner(){
System.out.println("局部内部类的构造方法");
}
public void test(){
System.out.println("ia="+ia);//2
System.out.println("cnt="+cnt);//1
}
}
AreaInner ai=new AreaInner();
ai.test();
} }
public class AreaOuterTest { public static void main(String[] args) { //声明外部类类型的引用指向外部类的对象 AreaOuter ao=new AreaOuter(); ao.show(); } }
<a name="4Lq3Z"></a>
### 局部内部类的使用方式
- 局部内部类只能在该方法的内部使用<br />
- 局部内部类可以在方法体内部直接创建对象<br />
- 局部内部类不能使用访问控制符和static关键字修饰符<br />
- 局部内部类可以使用外部方法的局部变量,但是必须是final的.由局部内部类和局部变量的声明周期不同所致<br />
<a name="aOce5"></a>
### 回调模式的概念
回调模式是----如果一个方法的参数是接口类型,则在调用该方法时,需要创建并传递一个实现此接口类型的对象,而该方法在运行时会调用到参数对象中所实现的方法(接口定义的)
```java
public interface AnonymousInterface {
public abstract void show();
}
-----------------------------------------
public class AnonymousInterfaceImpl implements AnonymousInterface{
@Override
public void show() {
System.out.println("这里是接口的实现类");
}
}
--------------------------------------
public class AnonymousInterfaceTest {
public static void test(AnonymousInterface ai){
ai.show();
}
public static void main(String[] args) {
//AnonymousInterface ai=new AnonymousInterfaceImpl();
AnonymousInterfaceTest.test(new AnonymousInterfaceImpl());
}
}
匿名内部类的使用
语法格式(重点):
接口/父类类型 引用变量 =new 接口/父类类型() {方法的重写};
AnonymousInterfaceTest.test(new AnonymousInterfaceImpl());
AnonymousInterface ait=new AnonymousInterface() {
@Override
public void show() {
System.out.println("匿名内部类");
}
};
AnonymousInterfaceTest.test(ait);
//从java8开始提出新特性lamda表达式可以简化上述代码
// 格式为:(参数列表 )->(方法体)
AnonymousInterface ait2=()-> System.out.println("lamdabiaodashi");
AnonymousInterfaceTest.test(ait2);
枚举类
枚举的基本概念
- 一年中的所有季节:春夏秋冬
- 所有的性别:男 女
- 键盘上的所有方向按键:上下左右
- 在日常生活中这些事物的取值只有明确的几个固定值,此时描述这些事物的所有制都可以一一列出,而这个列举出来的类型就叫做枚举类型
```java package com.lagou.task10;
/**
- @author lijing
- @date 2020/9/22 10:07
@description / public class Direction { //编程实现所有方向的枚举,所有的方向:上下左右 private final String desc;//用于描述方向字符串的成员变量 //2.声明本类类型的引用指向本类类型的对象 /private/public static final Direction UP=new Direction(“向上”); /private/public static final Direction DOWM=new Direction(“向下”); /private/public static final Direction LEFT=new Direction(“向左”); /private*/public static final Direction RIGHT=new Direction(“向右”);
//通过构造方法实现成员变量的初始化,更加灵活 //1.私有化构造方法 此时该构造方法只能在该类内部使用 private Direction(String desc){
this.desc=desc;
} //通过共有的get方法可以再本类的外部访问该类的成员变量 public String getDesc() {
return desc;
} }
psvm中 Direction D1 = Direction.UP; System.out.println(D1.getDesc());
<a name="47z1E"></a>
## 枚举类型的定义
- 使用public static final表示的常量描述较为繁琐,使用enum关键字来定义枚举类型取代常量,枚举类型是从java5开始增加的一种引用数据类型<br />
- 枚举值就是当前类的类型,也就是指向本类的对象,默认使用public static final关键字共同修饰,因此采用枚举类型.的方式调用<br />
- 枚举类可以自定义构造方法,但是构造方法的修饰符必须是private ,默认也是私有的
```java
public enum DirectionEnum {
//2.声明本类类型的引用指向本类类型的对象
//枚举类型要求所有枚举值必须放在枚举类型的组前面
UP("向上"),DOWM("向下"),LEFT("向左"),RIGHT("向右");
//编程实现所有方向的枚举,所有的方向:上下左右
private final String desc;//用于描述方向字符串的成员变量
//通过构造方法实现成员变量的初始化,更加灵活
//1.私有化构造方法 此时该构造方法只能在该类内部使用
private DirectionEnum(String desc){
this.desc=desc;
}
//通过共有的get方法可以再本类的外部访问该类的成员变量
public String getDesc() {
return desc;
}
}
自定义类和枚举类型在switch结构的使用
Enum类的概念和方法
所有的枚举类都继承自java.lang.Enum类中,常用的方法如下图所示:
package com.lagou.task10;
/**
* @author lijing
* @date 2020/9/22 10:58
* @description 编程实现方向枚举类的测试
*/
public class DirectionEnumTest {
public static void main(String[] args) {
//1.获取DirectionEnum类型中的所有枚举对象
DirectionEnum[] arr = DirectionEnum.values();
//2.打印每个枚举对象在枚举类型的名称和索引位置
for (int i = 0; i < arr.length; i++) {
System.out.println("枚举对象名称是:"+arr[i].toString());
System.out.println("枚举对象的索引位置是:"+arr[i].ordinal());
}
}
}
System.out.println("---------------------");
//3.根据参数指定的字符串得到枚举类型的对象,也就是将字符串转换为对象
//DirectionEnum de = DirectionEnum.valueOf("向下");//java.lang.IllegalArgumentException
DirectionEnum de = DirectionEnum.valueOf("DOWM");
//System.out.println("转换出来额枚举对象名称为:"+de.toString());
System.out.println("转换出来额枚举对象名称为:"+de);//当打印变量时,自动调用toString()方法
System.out.println("---------------------");
//4.使用获取到的枚举对象与枚举类已有的对象比较先后顺序
for (int i = 0; i < arr.length; i++) {
//当调用对象在参数对象之后时,获取到的比较结果为正数
//当调用对象在参数对象相同位置时,获取到的比较结果为0
//当调用对象在参数对象之前时,获取到的比较结果为负数
System.out.println("调用对象与数组中对象比较的先后顺序结果是"+de.compareTo(arr[i]));
}