♥Java枚举实例---交通灯,一文带你深入理解枚举,了解融会贯通JAVA SE所该具备的能力Java养成
Posted 码农C风
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了♥Java枚举实例---交通灯,一文带你深入理解枚举,了解融会贯通JAVA SE所该具备的能力Java养成相关的知识,希望对你有一定的参考价值。
Java学习打卡:第十八天
内容导航
Java养成计划(打卡第18天)
JAVA SE(夯实基础系列----Java初步)
内容管理
今天分享一下chapter four的容易忽略的类和对象容易忽略的知识。以问答的方式来复习巩固
基础问题(一定不要忘记)
- static静态代码块的特点,作用?
一个类中可以定义多个静态代码块,静态初始化块在类装入并初始化时执行一次,作用是初始化类变量(也是属于类的)
- 构造方法如何调用另外一个构造方法?
Public Mytime();
Public Mytime(int h);
Public Mytime(int h, int m, int s);
- 那如果现在构造第三个构造方法想调用第二个构造方法如何做?
this就是指代对象的,所以同一类中一个构造方法调用另外一个构造方法必须使用关键字this,但是只能调用一次,并且只能是第一行代码, 并且一个构造方法不能直接或间接调用自己
Public Mytime(int h, int m, int s){
this(h);
………
}
- 类方法有什么需要注意点?
类方法代码块是静态的,和静态代码块一样不能使用this关键字,因为this就是指代实例对象的,实例方法必须实例调用
- 标号有什么需要注意点?
标号只需要注意一个细节,那就是它是用于标记循环,如果标记在循环内部的普通语句,且下面执行break 标记 ,那么会编译错误
- 什么是has-a的关系
has-a是一种包含关系,是在另外一个类中将该类对象作为属性,在之前博客UML中提到
Java对象清除机制(垃圾处理机制)
对C语言有点了解就知道指针的存在,C语言里面的指针传递和JAVA里面的引用传递类似,JAVA里面的变量是在栈里面,我们创建new出来的对象在堆里面,变量存储的是堆中对象内存的首地址,这些知识在JVM里会深入讲到,,讲到指针就会提到动态内存,我们为指针分配内存之后在使用完指针之后若不进行free释放操作就会出现一些问题,但是在多线程,共享对象的情况下,Programmer不知道什么时机释放指针内存,但是在JAVA里面就不需要显释放内存了
在JAVA里面,对象清除由运行系统自动完成,称为垃圾收集,运行系统自动识别出哪些对象不再使用,之后由一个叫做垃圾处理器的线程来完成, (如果不了解线程就看看之前的博客)
什么样的对象是垃圾呢?
JAVA系统认为,一个程序的所有活的线程都不存在有变量去引用一个对象时,该对象就是垃圾,那失去价值了就不要让它占用堆内存了
那一个对象成为垃圾有哪几种情况?
- 一个对象引用的某个对象变成引用另外一个对象
Point2D pointone = new Point2D(2,3);
……
pointone = new Ponint2D(3,4);
- 一个引用某个对象的变量被设置为null,,这和上面其实是一样的
Point2D pointone = new Point2D(2,3);
……
pointone = null;
- 一个引用某对象的变量生存期结束,就释放了
方法体里的局部变量的生存期要短一些,当生存期过了,其引用对象就可能成为垃圾对象
一个良好习惯
那JAVA的垃圾处理线程这么🐂,那Programmer岂不是随意而为了?这不可能,JAVA中还会有这种情况出现:虽然有一个或多个变量引用某个对象,但实际上这个对象不需要,但是JAVA系统不会处理这个对象,那我们就要使用第二种方式将其设置为null,------所以Programmer要养成一个发现对象型变量不使用时,就将其设置为null的好习惯
这里我来举一个栗子
Public Class Point{
……
}
Public Class Test{
private Point pointone = new Point();
private static final Point pointtwo = new Point(); //这是一个(静态的)类变量
Public static void main(Stting[] args){
Test t1 = new Test();
Test t2 = new Test();
pointone = null;
fun(t1);
//gc
……
}
……
public static void fun(Test u)
Point pointthree = new Point();
u = null;
}
- 现在的问题是这里哪些变量引用过的对象可能被gc处收集?
这里我们分析一下就以知道我们一共创建了3个Point对象,其中pointone被置空了,因此满足回收条件,还有就是fun方法里的局部变量pointthree的生存期过了,所以这里也会回收,但是系统还不会回收Test类对象t1,因为系统不能判断是否放弃
在Java中垃圾回收线程的执行不是固定的,它可能就算满足条件也不回收,而等到占内存过大才回收,有的收集器比较积极,过一段时间就会回收一次,但是有的比较消极,很久才执行一次。我们可以使用System类的gc()方法来启动回收线程,但是这里和多线程中所讲的一样,仅仅是让该线程处于可执行状态,但是否执行由系统决定,可能一直都不执行。
枚举类型
(这里之前分享基础的时候漏掉了,现在将其补上)枚举类型是一种特殊的类型,用于表示一组不变的常量,关键字是enum,和C是相似的
enum TrafficLight{//枚举类型和普通的类是不一样的,普通类使用class,但是枚举类型使用enum
RED,GREEN,YELLOW //枚举常量,末尾不需要加分号,枚举常量代表枚举类型的实例,这些类型在初创时就装入
}//除了枚举常量,枚举类型不会有其他实例
枚举常量定义时需要大写,枚举变量除了枚举常量值之外还可能是null,我们调用枚举常量,因为是静态的,使用类名.常量名
枚举类型编译后也是产生一个.class文件,我们调用枚举类型时: < 枚举类型名> < 变量名>;和普通的对象引用没有太大的区别,但是不同的就是这里不能使用new来创建对象,因为除了枚举常量没有其他实例
比较两个枚举常量是否相等,常使用的是 “==” ,虽然也可以使用equals();
嵌套
枚举量的比较除了直接使用if来比较之外也可以使用switch语句switch括号后的值应该是该枚举类型变量的简单名字,不需要再用类型名,在前面声明
所谓嵌套枚举类型就是在类体中定义枚举类型,就是将其作为一个普通的块,放在类里面,但需要注意一点:
- 嵌入的枚举类型都是静态的,关键字static是默认的,就是我们直接可以通过类型名调用量
- 访问权限上,与非枚举类型相比,嵌入的可以是默认或者public,也可以是private或protected,定义成private就只是类内可见
- 所有的枚举类型都不能使用abstract与final修饰,所有的枚举类型都是最终的具体类型不能被扩展
这里我们可以举一个简单的例子来说明枚举类型
枚举类型实例----交通信号灯
package ThirdChapter;
public class EnumTraffic {
private enum TrafficLight{
RED,GREEN,YELLOW
}
public static void dirveRule(TrafficLight lightcolor) {
switch(lightcolor) {
case RED:
System.out.println("Stop now,it's red");
break;
case GREEN:
System.out.println("GO,it's green");
break;//不加break就可能多执行下面的default
default:
System.out.println("Ready to go,it's yellow");
break;
}
}
public static void main(String[] args) {
TrafficLight lightcolor = TrafficLight.GREEN;//这里就是之前的静态变量的引用
dirveRule(lightcolor);
}
}
这里我们就将枚举类型和switch一起使用了,这里是代码比较简单,如果复杂一些就不能无脑if-else或者switch,应该使用Strategy模式,上次介绍的比较简单,之后会再详细讲解一下
枚举类型的方法
枚举类型不能继承,因为都隐式继承了java.lang.Enum抽象类,因为java没有多继承,所以就不能扩展(继承)其他类
Enum类中有几种行为方法
- final String name() :返回枚举常量的名称
- final int ordinal() : 返回枚举类型常量的序号,比如上面RED就是0
- String toString() :返回枚举常量的字符串表示,默认就是名称
- static E[] values() : 返回包含该枚举类型所有枚举常量的数组//一般使用一个枚举类型的数组接收
- static E valueOf(String name) : 返回指定名称的枚举常量
举个例子,遍历输出所有枚举常量
private enum Week{
MON,TUS,WES,THR,FRI,SAT,SUN
}
public static void main(String[] args) {
Week[] w = Week.values();
for(Week s:w)
{
System.out.println(s.ordinal() +":"+ s.name());
}
}
这里既然是一个数组,那么就可以使用for-each循环
带参数的枚举类型的枚举常量
在枚举类型中,除了枚举常量列表,还可以定义构造方法,成员变量和方法等成分,枚举常量列表应该以分号结尾,其他语法成分在其后面, 当创建枚举类型的对象时,运行系统会调用相应的构造方法,如果没有显式的构造方法,系统会默认一个无参的构造方法
枚举常量可以包含一个实参列表,如RED(2),在枚举类型中,如果定义有带实参的枚举常量,那么就应该有相应的带形参的构造方法,否则将引发编译错,当创建带实参的枚举常量对象时,运行系统会将各自的实参传递给相应的形参。
⚠
在枚举类型中,自定义成员变量不能和枚举常量重名,自定义方法不能和继承的方法相冲
接下来举一个例子就是输出一周七天
private enum Week{
MON("星期一"),TUS("星期二"),WES("星期三"),THR("星期四"),FRI("星期五"),SAT("星期六"),SUN("星期日");//必须要有相应的带形参的构造方法
private String description;
private Week(String description) {//枚举类型的构造方法只能时private的,否则会报错
this.description = description;
}
@Override
public String toString() {
return description;
}
}
public static void main(String[] args) {
Week[] w = Week.values();
for(Week s:w)
{//.ordinal()为返回枚举常量的序号,name是返回其常量名称,重写toString方法可以返回其参数列表中的字符串
System.out.println(s.toString() +":"+ s.name());
}
}
运行结果
星期一:MON
星期二:TUS
星期三:WES
星期四:THR
星期五:FRI
星期六:SAT
星期日:SUN
博主的话
🙆,今天的分享就到这里,这是Second round review,所以进度就非常快,枚举和回收进程说的要多一些,我们学完之后一定要能够综合利用MVC,singleton ,strategy,decorator,factory模式,利用容器,综合利用继承与多态,封装不同的类,运用界面编程和反射机制(异常处理使用软件就可以自动进行,但是还是要自己会处理),同时运用IO完成一个复杂的功能强大的小程序。要能够实现对user隐藏代码,只在界面上操作,还要掌握debug的能力,,,,这是学完java SE的初级人员所应该具备的能力~~
以上是关于♥Java枚举实例---交通灯,一文带你深入理解枚举,了解融会贯通JAVA SE所该具备的能力Java养成的主要内容,如果未能解决你的问题,请参考以下文章
闭包原来并没有那么难!一文带你深入理解JavaScript的闭包