java第十一章:枚举和注解
java第十一章:枚举和注解
枚举
自定义类实现枚举
package com.lcz.enumerate.customize;
/**
* 自定义类实现枚举
* 1.将构造器私有化,防止外部new
* 2.只存在get方法,不存在set方法,防止外部修改
* 3.内部创建对象,用public static final修饰
* 枚举对象名通常全部大写
* 枚举对象可根据需要具有多个属性
*/
class Test{
public static void main(String[] args) {
System.out.println(Season1.AUTUMN);
System.out.println(Season1.SPRING);
System.out.println(Season1.WINTER);
System.out.println(Season1.SUMMER);
}
}
public class Season1 {
private String name;
private String desc;//描述
//内部创建对象
public static final Season1 SPRING = new Season1("春天","温暖");
public static final Season1 SUMMER = new Season1("夏天","炎热");
public static final Season1 AUTUMN = new Season1("秋天","凉爽");
public static final Season1 WINTER = new Season1("冬天","寒冷");
private Season1(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
@Override
public String toString() {
return "Season{" +
"name='" + name + '\'' +
", desc='" + desc + '\'' +
'}';
}
}
enum关键字实现枚举
package com.lcz.enumerate.enum_;
import com.lcz.enumerate.customize.Season1;
/**
* @author lcz
* @version 1.0
*
* 使用enum关键字实现枚举
* 1.enum关键字代替class
* 2.public static final Season2 SPRING = new Season2("春天","温暖")用
* SPRING("春天","温暖")代替
* 注:多个枚举对象用","间隔
* 如果使用enum实现枚举,要求将定义常量对象,写在最前面
*/
class Test{
public static void main(String[] args) {
System.out.println(Season1.AUTUMN);
System.out.println(Season1.SPRING);
System.out.println(Season1.WINTER);
System.out.println(Season1.SUMMER);
}
}
public enum Season2 {
//内部创建对象
SPRING("春天","温暖"),
SUMMER("夏天","炎热"),
AUTUMN("秋天","凉爽"),
WINTER("冬天","寒冷");
private String name;
private String desc;//描述
private Season2(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
@Override
public String toString() {
return "Season{" +
"name='" + name + '\'' +
", desc='" + desc + '\'' +
'}';
}
}
enum关键字实现枚举细节
1.enum关键字实现一个枚举类时,默认会继承Enum类,而且实现的枚举类是final类
javap反编译工具可看到
2.如果使用无参构造器创建枚举对象,则实参列表和小括号都可以省略
3.枚举对象必须放在枚举类的行首
反编译枚举类细节
1.枚举类默认继承Enum类,是final类
2.默认带有静态方法values和valueOf,一个返回包含枚举对象的数组,一个将字符串转换为枚举对象
3.有一个静态代码块
enum常用方法
1.toString:Enum类是返回当前枚举对象名,枚举类可重写用于返回对象的属性信息
2.name:返回当前对象名,子类不能重写
3.ordinal:返回当前对象的位置号,默认从0开始
4.values:返回当前枚举类中所有的常量,以数组返回
5.valueOf:将字符串转换成枚举对象,要求字符串为已有常量名,否则报异常
6.compareTo:比较两个枚举常量,比较的是编号,返回self.ordinal-other.ordinal
enum实现接口
1.使用enum关键字后,就不能再继承其他类了,隐式继承Enum类,而java又是单继承机制
2.枚举类和普通类一样,可以实现接口
如:enum 类名 implements 接口1,接口2{ }
enum枚举类练习
1.父类toString方法返回该枚举对象的名称
package com.lcz.enumerate.enum_;
/**
* @author lcz
* @version 1.0
*/
class Test1{
public static void main(String[] args) {
Week[] weeks = Week.values();
System.out.println("===所有星期的信息如下(使用增强for)===");
for (Week week:weeks) {
System.out.println(week);
}
System.out.println(Week.FIRDAY.ordinal());
System.out.println(Week.FIRDAY.name());
System.out.println(Week.FIRDAY.compareTo(Week.SATURDAY));
System.out.println(Week.valueOf("MONDAY"));
Week monday = Week.MONDAY;
monday.say();
}
}
interface IA{
public void say();
}
public enum Week implements IA{
MONDAY("星期一"),
TUESDAY("星期二"),
WEDNESDAY("星期三"),
THURSDAY("星期四"),
FIRDAY("星期五"),
SATURDAY("星期六"),
SUNDAY("星期日");
private String name;
private Week(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
@Override
public void say() {
System.out.println("我是: "+ name);
}
}
注解
注解介绍
1.注解(Annotation)也被称为元数据(Metadata),用于修饰解释 包、类、方法、属性、构造器、局部变量等数据信息
2.和注释一样,不影响程序逻辑,但注解可以被编译或运行,相当于补充信息
3.三个基本的Annotation:
1):@Override
2):@Deprecated
3):@SuppressWarnings
@Override
限定某个方法,是重写父类方法,该注解只能用于方法
1.如果没有写@Override,仍构成重写
只是写@Override,编译器会进行语法检查
2.源码:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override{
}
@interface 表示一个 注解类
@Deprecated
用于表示某个程序元素(类,方法等)已过时,不推荐使用,但仍可以使用
1.可以修饰类、方法、字段、包、参数、构造器、局部变量
2.源码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Targe(value={CONSTRUCTOR,FIELD,LOCAL_VARIABLE,METHOD,PACKAGE,PARAMETER,TYPE})
public @interface Deprecated{
}
@SuppressWarnings
抑制编译器警告
1.在{""}中,可以写入希望抑制的警告信息
1):unchecked:忽略没有检查的警告
2):rawtypes:忽略没有指定泛型的警告
3):unused:忽略没有使用某个变量的警告
4):all:忽略所有警告
2.源码:
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();//接受抑制的警告信息
}
四种元注解(了解即可)
@Retention
只能用于修饰一个Annotation定义,用于指定该Annotation可以保留多长时间
1.使用时必须为RetentionPolicy类型的成员变量指定值:
1):RetentionPolicy.SOURCE:源码级别,编译器使用后,直接丢弃这种策略的注解
2):RetentionPolicy.CLASS:编译器将把注解记录在class文件中,当运行java程序时,JVM不会保留注解。这是默认值
3):RetentionPolicy.RUNTIME:编译器将把注解记录在class文件中,当运行java程序时,JVM会保留注解。程序可通过反射获取该注解
@Target
指定注解类可修饰哪些程序元素,包含一个value的成员变量
如:@Target(value={CONSTRUCTOR,FIELD,LOCAL_VARIABLE})
@Documented
指定注解类被javadoc工具提取成文档,即在生成文档时,可以看到该注解
说明:定义为Documented的注解必须设置Retention值为RUNTIME
@Inherited
指定注解类的子类将自动具有该注解
本章作业
关于类变量和类方法
类变量是静态变量,被所有对象共享,一个对象对其改变会影响另一个对象调用的结果
package com.lcz.oopAdvanced.homework;
/**
* @author lcz
* @version 1.0
* 需求:
* 1.在Frock类中声明私有的静态属性currentNum[int类型],初始值为100000,作为衣服出厂的序列号起始值
* 2.声明共有的静态方法getNextNum,作为生成上衣唯一序列号的方法,每调用一次,将currentNum增加100,并作为返回值
* 3.在TestFrock类的main方法中,分两次调用getNextNum方法,获取序列号并打印输出
* 4.在Frock类中声明serialNumber(序列号)属性,并提供对应的get方法
* 5.在Frock类的构造器中,通过调用getNextNum方法为Frock对象获取唯一序列号,赋给serialNumber属性
* 6.在TestFrock类的main方法中,分别创建三个Frock对象,并打印三个对象的序列号,验证是否为按100递增
*
*/
class Frock{
//衣服出厂的序列号起始值
private static int currentNum = 100000;
private int serialNumber;
public int getSerialNumber() {
return serialNumber;
}
public Frock() {
this.serialNumber = getNextNum();
}
public static int getNextNum(){
currentNum += 100;
return currentNum;
}
}
public class TestFrock {
public static void main(String[] args) {
System.out.println(Frock.getNextNum());
System.out.println(Frock.getNextNum());
Frock frock1 = new Frock();
Frock frock2 = new Frock();
Frock frock3 = new Frock();
System.out.println(frock1.getSerialNumber());
System.out.println(frock2.getSerialNumber());
System.out.println(frock3.getSerialNumber());
}
}
关于抽象类
package com.lcz.oopAdvanced.homework;
/**
* @author lcz
* @version 1.0
* 需求:
* 1.动物类Animal包含了抽象方法 shout();
* 2.Cat类继承了Animal,并实现方法shout,打印“猫会喵喵叫”
* 3.Dog类继承了Animal,并实现方法shout,打印“狗会汪汪叫”
* 4.在测试类中分别实例化对象调用Cat和Dog的shout方法;
*/
abstract class Animal{
public abstract void shout();
}
class Cat extends Animal{
@Override
public void shout() {
System.out.println("猫会喵喵叫...");
}
}
class Dog extends Animal{
@Override
public void shout() {
System.out.println("狗会汪汪叫...");
}
}
public class Homework02 {
public static void main(String[] args) {
Dog dog = new Dog();
Cat cat = new Cat();
dog.shout();
cat.shout();
}
}
关于接口
package com.lcz.oopAdvanced.homework;
/**
* @author lcz
* @version 1.0
* 需求:
* 关于接口
* 1.有一个交通工具接口类Vehicles,有work接口
* 2.有Horse类和Boat类分别实现Vehicles
* 3.创建交通工具工厂类,有两个方法分别获得交通工具Horse和Boat
* 4.有Person类,有name和Vehicles属性,在构造器中为两个属性赋值
* 5.实例化Person对象“唐僧”,要求一般情况下用Horse作为交通工具,遇到大河用Boat作为交通工具
*
*/
interface Vehicles{
public void work();
}
class Horse implements Vehicles{
@Override
public void work() {
System.out.println("骑马...");
}
}
class Boat implements Vehicles{
@Override
public void work() {
System.out.println("坐船...");
}
}
class Fly implements Vehicles{
@Override
public void work() {
System.out.println("坐飞机...");
}
}
class Factory{
private Factory() {//私有化构造器
}
private static Horse horse = new Horse();//马儿只有一只,白龙马嘛!
public static Horse getHorse(){
return horse;
}
public static Boat getBoat(){
return new Boat();
}
public static Fly getFly(){
return new Fly();
}
}
class Person{
private String name;
private Vehicles vehicles;
public Person(String name, Vehicles vehicles) {
this.name = name;
this.vehicles = vehicles;
}
public void f1(){
if(!(vehicles instanceof Boat)){
vehicles = Factory.getBoat();
}
System.out.println("遇到大河,乘船过河...");
}
public void f2(){
if(!(vehicles instanceof Horse)){
vehicles = Factory.getHorse();
}
System.out.println("一般情况,骑马奔波...");
}
public void f3(){
if(!(vehicles instanceof Fly)){
vehicles = Factory.getFly();
}
System.out.println("遇火焰山,飞机带翅膀...");
}
}
public class Homework03 {
public static void main(String[] args) {
Person person = new Person("唐僧",new Horse());
person.f1();
person.f2();
person.f3();
}
}
关于匿名内部类和接口
package com.lcz.oopAdvanced.homework;
/**
* @author lcz
* @version 1.0
* 需求:
* 关于匿名内部类和接口
* 1.计算器接口具有work方法,功能是运算,有一个手机类CellPhone,定义方法testWork,
* 测试计算功能,调用计算接口的work方法
* 2.要求调用CellPhone对象的testWork方法,使用上 匿名内部类
*/
interface calculator{
public void work(int n1,int n2);
}
class CellPhone{
public void testWork(calculator cal,int n1,int n2){
try {
cal.work(n1,n2);
} catch (NumberFormatException e) {
System.out.println(e.getMessage());
}
}
}
public class Homework04 {
public static void main(String[] args) {
CellPhone cellPhone = new CellPhone();
cellPhone.testWork(new calculator() {
@Override
public void work(int n1, int n2) {
System.out.println("n1 / n2 : " + n1/n2);
}
},10,0);
}
}
关于成员内部类
package com.lcz.oopAdvanced.homework;
/**
* @author lcz
* @version 1.0
* 需求:
* 关于成员内部类
* 1.有一个Car类,有属性temperature(温度),车内有Air(空调)类,有吹风的功能flow,
* 2.Air会监视车内的温度,如果温度超过40度则吹冷气,低于0度则吹暖气,在这之间关闭空调
* 3.实例化具有不同温度的Car对象,调用空调的flow方法,测试空调吹的风是否正确
*/
class Car{
private double temperature;
public Car(double temperature) {
this.temperature = temperature;
}
public Air getAir(){
return new Air();
}
class Air{
public void flow(){
if(temperature > 40){
System.out.println("吹冷气...");
}else if(temperature < 0){
System.out.println("吹暖气...");
}else{
System.out.println("空调关闭");
}
}
}
}
public class Homework05 {
public static void main(String[] args) {
Car[] cars = new Car[3];
cars[0] = new Car(41);
cars[1] = new Car(-5);
cars[2] = new Car(22);
for (int i = 0; i < cars.length; i++) {
cars[i].getAir().flow();
}
}
}
关于局部内部类
package com.lcz.oopAdvanced.homework;
/**
* @author lcz
* @version 1.0
* 需求:
* 关于局部内部类
* 1.编一个类A,在类中定义局部内部类B,B中有一个私有常量name,有一个方法show()打印常量name,进行测试
* 2.进阶:A中也定义一个私有的变量name,在show方法中打印测试
*/
class A{
private String name;
public A(String name) {
this.name = name;
}
public void f1(){
class B{
private String name;
public B(String name) {
this.name = name;
}
public void show(){
System.out.println(name);
System.out.println(A.this.name);
}
}
B b = new B("lhc");
b.show();
}
}
public class Homework06 {
public static void main(String[] args) {
A a = new A("lcz");
a.f1();
}
}
关于枚举类
package com.lcz.enumerate.homework;
/**
* @author lcz
* @version 1.0
*
* 需求:
* 1.创建一个Color枚举类
* 2.有 RED,BLUE,BLACK,YELLOW,GREEN这五个枚举对象
* 3.Color有三个属性redValue,greenValue,blueValue
* 4.创建构造方法,参数包括这三个属性
* 5.每个枚举对象都要给这三个属性赋值,三个属性对应的值分别是:
* red:255,0,0 blue:0,0,255 black:0,0,0, yellow:255,255,0 green:0,255,0
* 6.定义接口,里面有show方法,要求Color实现该接口
* 7.show方法中显示三属性的值
* 8.将枚举对象在switch语句中匹配使用
*/
interface IA{
public void show();
}
enum Color implements IA{
RED(255,0,0),
BLUE(0,0,255),
BLACK(0,0,0),
YELLOW(255,255,0),
GREEN(0,255,0);
private int redValue;
private int greenValue;
private int blueValue;
Color(int redValue, int greenValue, int blueValue) {
this.redValue = redValue;
this.greenValue = greenValue;
this.blueValue = blueValue;
}
@Override
public void show() {
System.out.println("红: " + redValue + "绿: " + greenValue + "蓝: " + blueValue);
}
}
public class Homework01 {
public static void main(String[] args) {
Color blue = Color.BLUE;
blue.show();
//switch 中 放入枚举对象
switch (blue){
case RED:
System.out.println("匹配到红色...");
break;
case GREEN:
System.out.println("匹配到绿色...");
break;
case BLACK:
System.out.println("匹配到黑色...");
break;
case BLUE:
System.out.println("匹配到蓝色...");
break;
case YELLOW:
System.out.println("匹配到黄色...");
break;
default:
System.out.println("没有匹配到...");
}
}
}
tic void main(String[] args) {
Color blue = Color.BLUE;
blue.show();
//switch 中 放入枚举对象
switch (blue){
case RED:
System.out.println(“匹配到红色…”);
break;
case GREEN:
System.out.println(“匹配到绿色…”);
break;
case BLACK:
System.out.println(“匹配到黑色…”);
break;
case BLUE:
System.out.println(“匹配到蓝色…”);
break;
case YELLOW:
System.out.println(“匹配到黄色…”);
break;
default:
System.out.println(“没有匹配到…”);
}
}
}