成员内部类:
说明:
- 成员内部类是定义在外部类的成员位置,并且没有static修饰。
- 可以直接访问外部类的所有成员,包括私有的
-
可以添加任意访问修饰符(public、protected、默认、private),因为它的地位就是一个成员
-
作用域 和外部类的其他成员一样,为整个类体、
比如前面的案例,在外部类的成员方法中创建成员内部类对象,再调用方法
-
成员内部类–访问—>外部类成员(比如:属性) [访问方式:直接访问]
-
外部类–访问—>成员内部类 [访问方式:创建对象,再访问]
-
外部其他类–访问—>成员内部类
-
法一:Outer08.Innter08 innter08 = outer08.new Innter08();
-
法二:在外部类中,编写一个方法,可以返回Inner08对象
- 如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员) 去访问
public class MemberInnerClass01{
public static void main(String[] args) {
Outer08 outer08 = new Innter08();
outer08.t1();
//外部其他类,使用成员内部类的两种方式:
//其它外部类访问内部类,方式一:
//outer08.new Innter08(); 相当于把new Innter08()当作是outer08成员
Outer08.Innter08 innter08 = outer08.new Innter08();
//方式二,在外部类中,编写一个方法,可以返回Inner08对象
Outer08.Innter08 inner08Instance = outer08.getInnter08Instance();
inner08Instance.say();
}
}
class Outer08{ //外部类
private double sal = 99.8;
private int n1 = 10;
public String name = "张三";
private void hi(){
System.out.print("hi()方法~~");
}
public class Innter08{ //成员内部类
public void say(){
//可以直接访问外部类的所有成员,包含私有的
System.out.print("n1 = " + n1 + "name = " + name);
hi();
}
}
//方法,返回一个Inner08实例
public Innter08 getInnter08Instance(){
return new Innter08();
}
}
public void t1(){
//使用了成员内部类
//创建成员内部类的对象,然后使用相关的方法
Innter08 innter08 = new Innter08();
innter08.say();
System.out.print(innter08.sal);
}
静态内部类:
说明:
静态内部类是定义在外部类的成员位置,并且有static修饰
- 可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员
-
可以添加任意访问修饰符(public、protected、默认、private),因为它的地位就是一个成员
-
作用域:同其他的成员,为整个类体
-
静态内部类–访问—>外部类(比如:静态属性) [访问方式:直接访问所有静态成员]
-
外部类–访问—>静态内部类 访问方式:创建对象,再访问
-
外部其他类–访问—>静态内部类
-
法一:Outer08.Innter08 innter08 = outer08.new Innter08();
-
法二:在外部类中,编写一个方法,可以返回Inner08对象
-
如果外部类和静态内部类的成员重名时,静态内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.成员) 去访问
public class StaticInnerClass01{ public static void main(String[] args) { Outer10 outer10 = new Outer10(); outer10.m1(); } }
class Outer02{ //外部类 private int n1 = 10; private static String name = "张三"; //inner10就是静态内部类 /* 1、放在外部类成员位置 2、使用static修饰 3、可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员 4、可以添加任意访问修饰符(public、protected、默认、private),因为它的地位就是一个成员 5、 */ pravite static class Inner10{ public void say(){ System.out.print(name); } } public void m1(){ Inner10 inner10 = new Inner10(); inner10.say(); } }
枚举类:
引出:
要求创造季节(Season)对象,请设计并完成
public class Enumeration01{
public static void main(String[] args) {
Season spring = new Season("春天","温暖");
Season winter = new Season("冬天","寒冷");
Season summer = new Season("夏天","炎热");
Season autumn = new Season("秋天","凉爽");
//因为对于季节而言,他的对象(具体值)是固定的四个,不会有更多
//如果这样设计,不能提现季节是固定的,还可以创建其他对象
//因此,这样的设计不好===>枚举类:把具体的对象一个一个列举出来的类
//如:
Season other = new Season("其他","其他");
}
}
class Season{
private String name;
private String desc; //描述
//构造器
//.getXX
//.setXX
}
分析:
创建Season对象有如下特点:
- 季节的值是有限的几个值(spring、summer、autumn、winter)
- 只读,不需要修改
解决方案——枚举:
- 枚举对应英文(enumeration,简写enum)
- 枚举是一组常量的集合
- 可以这样理解:枚举属于一种特殊的类,里面只包含一组有限的特定的对象
枚举的两种实现方式:
- 自定义类实现枚举
- 使用enum关键字实现枚举
自定义枚举类:
- 不需要提供setXX方法,因为枚举对象值通常为只读;
- 枚举对象/属性使用 final + static 共同修饰,实现底层优化;
- 枚举对象名通常使用全部大写,常量的命名规范
- 枚举对象根据需要,也可以有多个属性
演示自定义枚举
class Season{
private String name;
private String desc; //描述
//3、在Season内部,直接创建固定的对象
//使用static属性会导致Season类加载,可以加final修饰符
public final static Season SPRING = new Season("春天","温暖");
public final static Season WINTER = new Season("冬天","寒冷");
public final static Season SUMMER = new Season("夏天","炎热");
public final static Season AUTUMN = new Season("秋天","凉爽");
//1、将构造器私有化,防止直接new
private Season(……){
……
}
//.getXX
//2、去掉setXX方法,防止属性被修改
}
小结:
- 构造器私有化
- 本类内部创建一组对象(四个 春夏秋冬)
- 对外暴露对象(通过为对象添加 public final static修饰符)
- 可以提供get方法,但是不要提供set方法
enum枚举类:
演示使用enum关键字来实现枚举类
//1、使用 enum 关键字来替代 class
enum Season2{
/* //在Season内部,直接创建固定的对象
//使用static属性会导致Season类加载,可以加final修饰符
public final static Season SPRING = new Season("春天","温暖");
public final static Season WINTER = new Season("冬天","寒冷");
public final static Season SUMMER = new Season("夏天","炎热");
public final static Season AUTUMN = new Season("秋天","凉爽");*/
//2、public final static Season SPRING = new Season("春天","温暖");
// 直接使用 SPRING("春天","温暖");
//即:常量名(实参列表)
//3、如果有多个常量(对象),使用逗号间隔即可
SPRING("春天","温暖"),WINTER("冬天","寒冷"),SUMMER("夏天","炎热"),AUTUMN("秋天","凉爽");
//4、如果使用enum 来实现枚举,要求将定义常量对象写在最前面
private String name;
private String desc; //描述
//将构造器私有化,防止直接new
private Season(……){
……
}
//.getXX
//去掉setXX方法,防止属性被修改
- 使用 enum 关键字来替代 class
-
“public final static Season SPRING = new Season(“春天”,”温暖”);” 直接使用 “SPRING(“春天”,”温暖”);”
即:常量名(实参列表)
-
如果有多个常量(对象),使用逗号间隔即可
-
如果使用enum 来实现枚举,要求将定义常量对象写在最前面
注意事项:
-
当我们使用enum关键字开发一个枚举类时,默认会继承Enum类
-
传统的”public final static Season SPRING = new Season(“春天”,”温暖”);”
-
简化成 “SPRING(“春天”,”温暖”);” ,这里必须知道,它调用的是哪个构造器
-
从传入的实参可以看出来,比如上面调用的就是两个参数的构造器
-
如果使用无参构造器 创建 枚举对象,则实参列表和小括号都可以省略
-
当有多个枚举对象时,使用”,”间隔,最后有一个分号收尾
-
枚举对象必须放在枚举类的首行
enum常用方法说明:
说明:
使用关键字enum时,会隐式继承Enum类,这样我们就可以使用Enum类相关的方法
- toString:Enum类已经重写过了,返回的时是当前对象名,子类可以重写该方法,用于返回对象的属性信息
- name:返回当前对象名(常量名),子类中不能重写
- ordinal:返回当前对象的位置号,默认从0开始
- values:返回当前枚举类中的所有常量
- valueOf:将字符串转换成枚举对象,要求字符串必须为已有的常量名,否则报异常!
- compareTo:比较两个枚举常量,比较的就是位置号!
演示Enum类的各种方法的使用,以Season2枚举类来演示各种方法
public static void main(String[] args) {
Season2 autumn = Season2.AUTUMN;
System.out.print(autumn.name());
/*
输出枚举对象的名字
*/
System.out.print(autumn.ordinal());
/*
输出结果:
3
输出的是该枚举对象的次序(编号),是从0开始的,枚举对象是第4个,所以输出3
*/
Season2[] values = Season2.values();
/*
含有定义的所有枚举对象
*/
for (Season2 season :values ) { //增强for循环
//从values一次取一个放到season
}
//1、根据输入的"AUTUMN" 到 Season2的枚举对象去查找
//2、如果找到了,就返回,如果没找到,就报错
Season2 autumn1 = Season2.valuesOf("AUTUMN");
System.out.print("autumn1=" + autumn1);
/*
输出:
ture
*/
//把 Season2.AUTUMN 枚举对象的编号 和 Season2.SUMMER枚举对象的编号比较
//Season2.AUTUMN的编号(3) - Season2.SUMMER的编号(0)
System.out.print(Season2.AUTUMN.compareTo(Season2.SUMMER));
/*
输出结果:
3
*/
}
使用细节:
- 使用enum关键字后,就不能继承其他类了,因为enum会隐式继承Enum,而java是单继承机制;
-
枚举类和普通类一样,可以实现接口,如下形式:
enum 类名 implements 接口1,接口2{} interface Iplaying{ public void playing(); } enum Music implements Iplaying{ @Override public void playing(){ System.out.print("播放音乐~~"); } }