• 0029 Java学习笔记-面向对象-枚举类


    可以创建几个对象?

    • n多个:大部分的类,都可以随意创建对象,只要内存不爆掉
    • 1个:比如单例类
    • 有限的几个:采用单例类的设计思路,可以只允许创建少数的几个特定的对象;还有就是枚举类。

    创建少数几个对象,不用枚举类实现

    package testpack;
    public class Test1{  
        public static void main(String[] args) { 
        	Season s=Season.getSeason("秋天");
        	System.out.println(s.getName()+s.getDesc());
        }
    }
    class Season{
    	public final static Season SPRING=new Season("春天","花开"); //所有实例用public final static 修饰
    	public final static Season SUMMER=new Season("夏天","蝉鸣");
    	public final static Season AUTOMN=new Season("秋天","落叶");
    	public final static Season WINTER=new Season("冬天","大雪");
    	private final String desc;
    	private final String name;
    	public static Season getSeason(String sea){                  //提供一个静态方法获取实例
    		switch(sea){
    			case "春天":
    				return SPRING;
    			case "夏天":
    				return SUMMER;
    			case "秋天":
    				return AUTOMN;
    			case "冬天":
    				return WINTER;
    			default :
    				return null;
    		}
    	};
    	private Season(String name,String desc){                     //用private隐藏构造器
    		this.name=name;
    		this.desc=desc;
    	}
    	public String getName(){
    		return this.name;
    	};
    	public String getDesc(){
    		return this.desc;
    	}
    	
    }
    

    创建少数几个对象,用枚举类改写

    package testpack;
    public class Test1{  
        public static void main(String[] args) { 
        	Season s1=Season.SPRING;            //像访问类变量一样获得一个枚举类的对象
        	Season s2=Season.valueOf("AUTOMN"); //通过valueOf(参数)也可以。这里的参数得跟枚举类第一行列出的枚举对象名一致
        	Season.showStaticDesc();            //调用枚举类的类方法
        	System.out.println("调用实例方法:"+s1.toString());             //调用枚举对象的实例方法
        	System.out.println("s1的索引号: "+s1.ordinal()); //ordinal()方法返回这个对象在枚举类第一行的顺序号,0-based
        	System.out.println("s2的索引号: "+s2.ordinal());
        	System.out.println("s1在s2的前面返回int负数:"+s1.compareTo(s2)); //枚举对象的compareTo()方法,其实就是s1.ordinal()-s2.ordinal()
        	System.out.println(s1.name());      //枚举对象的name()方法返回枚举类第一行的枚举名称
        	for (Season s:Season.values()) {    //values()方法遍历Season枚举类
        		System.out.println(s)
        	}
        }
        
    }
    enum Season{                     //在枚举类的第一行列出所有的枚举对象,个数多的话,可以分行
    	SPRING("春天","花开"),        //圆括号表示在调用构造方法,不写圆括号则调用默认的无参构造
    	SUMMER("夏天","蝉鸣"),        //所有的枚举对象默认被public static final修饰。是不是有点像不可变类?
    	AUTOMN("秋天","落叶"),        //AUTOMN相当于是Season类型的变量名,同时调用构造方法创建对象
    	WINTER("冬天","大雪");        //相当于:public static final Season WINTER=new Season("冬天","大雪");
    	private final String name;    //枚举类可以包含实例变量,一般都用private final修饰,是不是又像不可变类
    	private final String desc;
    	private static final String staticDesc="枚举类可以包含类变量"; //枚举类可以包含类变量
    	private Season(String name,String desc){  //枚举类可以包含构造方法,只能是private或者默认private修饰
    		this.name=name;                       //在构造方法中给实例变量初始化,
    		this.desc=desc;
    	}
    	public static void showStaticDesc(){      //枚举类可以包含类方法
    		System.out.println(staticDesc);
    	}
    	public String toString(){                 //枚举类可以包含实例方法
    		return "实例方法toString():季节名+描述:"+this.name+"+"+this.desc;
    	}
    	public String getName(){
    		return this.name;
    	}
    	public String getDesc(){
    		return this.desc;
    	}
    }
    

    枚举类

    • 枚举类的关键字是enum,跟class、interface地位相同
    • 枚举类都默认继承java.lang.Enum,而不是java.lang.Object,因而不能显式的继承其他父类,否则就继承了两个类
    • java.lang.Object是java.lang.Enum的直接父类,枚举类对象可以赋值给Object类型的变量
    • java.lang.Enum实现了java.lang.Serializable和java.lang.Comparable接口
    • 非抽象的枚举类默认有final修饰,因而不能被继承
    • 枚举类的构造器只能用private修饰符,因为不能让外部随意创建对象嘛
    • 枚举类的所有实例必须在第一行列出,并默认添加public static final修饰
    • 枚举类名.values()方法可以遍历所有枚举类对象
    • 通过枚举类名.枚举对象名可以返回枚举类对象;Enum.valueOf(枚举类.class,枚举对象名)也可以
    • 枚举类的主要方法
      • int compareTo(E o):比较两个枚举对象的顺序,调用对象位于参数对象之前返回负int
      • String name():返回枚举对象的名字,就是枚举类中第一行列出的枚举对象的名字
      • int ordinal():返回该枚举对象的索引号,就是在枚举类第一行的顺序号,第一个顺序号0
      • String toString():枚举类一般都重写这个方法
      • static <T extends Enum>T valueOf(Class enumType,String name):Enum的静态方法,返回一个枚举类中与name相同名称的枚举对象,比如Enum.valueOf(Season.class,"AUTOMN")

    枚举类的成员变量、方法、构造器

    • 枚举类中可以包含类变量、类方法、实例变量、实例方法、构造方法
    • 实例变量一般都在构造方法中初始化,枚举类一般都设计为不可变类,用private final修饰,且不提供setter方法
    • 实例变量、构造器、第一行声明枚举对象:
      • 第一行声明枚举对象时,如果不写圆括号,或者写无参数的圆括号,那么构造器要么不写,要么是无参构造器
      • 也就是说如果不写构造器,那么有一个默认的无参构造器,初始化赋值就是:0;0.0;false;null
      • 如果写了带参数的圆括号,那么就得写对应的构造器
      • 如果写了有参数的构造器,那么第一行声明枚举对象时,就得传入对应的参数
      • 以上所述,就是说第一行声明枚举对象时,实际上就是在调用构造方法创建对象,然后将这些对象赋值给声明的枚举对象名

    枚举类实现接口

    • 枚举类可以像类一样,实现若干个接口,也用implements
    • 可以把接口的方法实现一次,每个枚举对象公用相同的一个方法,示例
    package testpack;
    public class Test1{  
        public static void main(String[] args) { 
        	Season s=Enum.valueOf(Season.class, "SUMMER");
        	s.year();
        }
    }
    enum Season implements Year{
    	SPRING,SUMMER,AUTOMN,WINTER;
    	public void year(){
    		System.out.println("一年有四季");
    	}
    }
    interface Year{
    	public void year();
    }
    
    • 还可以每个枚举对象,都把接口的抽象方法实现一次,各个对象的这个方法行为不同,示例
    package testpack;
    public class Test1{  
        public static void main(String[] args) { 
        	Season s1=Enum.valueOf(Season.class, "SPRING");
        	Season s2=Enum.valueOf(Season.class, "SUMMER");
        	Season s3=Enum.valueOf(Season.class, "AUTOMN");
        	Season s4=Enum.valueOf(Season.class, "WINTER");
        	s1.year();
        	s2.year();
        	s3.year();
        	s4.year();
        }
    }
    enum Season implements Year{
    	SPRING{
    		public void year(){           //实际上就是匿名内部类
    			System.out.println("一年有四季:这是春天");
    		}
    	},SUMMER{
    		public void year(){           //创建的不是Season的对象,而是Season的匿名子类的对象
    			System.out.println("一年有四季:这是夏天");
    		}
    	},AUTOMN{
    		public void year(){
    			System.out.println("一年有四季:这是秋天");
    		}
    	},WINTER{
    		public void year(){
    			System.out.println("一年有四季:这是冬天");
    		}
    	};
    	
    }
    interface Year{
    	public void year();
    }
    
    • 上面的代码实际上就是创建了Season的匿名子类的对象,看编译后生的字节码文件

    Test1.class
    Year.class
    Season.class
    Season$1.class
    Season$2.class
    Season$3.class
    Season$4.class

    枚举类可以包含抽象方法

    • 枚举类可以包含抽象方法,但不需要用abstract修饰该枚举类
    • 每个枚举值必须实现这个抽象方法
    • 这个跟实现一个接口是一个道理,只是把抽象方法从接口转移到自己这个枚举类里

    其他

    • switch语句的控制表达式可以是任何枚举类型
  • 相关阅读:
    Reference Counting GC (Part two :Partial Mark & Sweep)
    Reference Counting GC (Part one)
    Union File System
    Linux Cgroups
    Mark Sweep GC
    取模运算
    负数取模怎么算
    牛客【2021寒假集训营第一场】J-一群小青蛙呱蹦呱蹦呱
    记codeforces一个简单模拟题
    筛法求素数
  • 原文地址:https://www.cnblogs.com/sonng/p/6094577.html
Copyright © 2020-2023  润新知