网站首页 > 精选教程 正文
枚举
枚举本质也是一种类,只不过是这个类的对象是有限的、固定的几个,不能让用户随意创建。
如果枚举类的实例只有一个,则可以看做是单例的实现方式。
JDK5.0之前
私有化类的构造器,保证不能在类的外部创建其对象;
在类的内部创建枚举类的实例。声明为:public static final, 对外暴露这些常量对象;
对象如果有实例变量,应该声明为private final(建议,不是必须),并在构造器中初始化。
package com.demo.enumdemo;
public class SeasonTest {
public static void main(String[] args) {
System.out.println(Season.SPRING);
System.out.println(Season.SPRING.getSeasonName());
System.out.println(Season.SPRING.getSeasonDesc());
}
}
class Season {
// 声明当前类的对象的实例变量 使用private final修饰
private final String seasonName;
private final String seasonDesc; // 季节的描述
// 1. 私有化类的构造器
private Season(String seasionName, String seasonDesc) {
this.seasonName = seasionName;
this.seasonDesc = seasonDesc;
}
// 2. 提供实例变量的get方法
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
// 3. 创建当前类的实例 使用public static final修饰
public static final Season SPRING = new Season("春天", "春暖花开");
public static final Season SUMMER = new Season("夏天", "夏日炎炎");
public static final Season AUTUMN = new Season("秋天", "秋高气爽");
public static final Season WINTER = new Season("冬天", "冰冷刺骨");
@Override
public String toString() {
return "Season{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
}
JDK5.0之后
使用enum关键字定义的枚举类,默认其父类是java.lang.Enum类;
使用enum关键字定义的枚举类,不要显示的定义其父类,否则报错。
package com.demo.enumdemo;
public class SeasonTest {
public static void main(String[] args) {
System.out.println(Season.SPRING.getClass()); // class com.demo.enumdemo.Season
System.out.println(Season.SPRING.getClass().getSuperclass()); // class java.lang.Enum
}
}
enum Season {
// 1. 必须在枚举类的开头声明多个对象。对象之间使用,隔开
SPRING("春天", "春暖花开"),
SUMMER("夏天", "夏日炎炎"),
AUTUMN("秋天", "秋高气爽"),
WINTER("冬天", "冰冷刺骨");
// 2. 声明当前类的对象的实例变量 使用private final修饰
private final String seasonName;
private final String seasonDesc; // 季节的描述
// 3. 私有化类的构造器
private Season(String seasionName, String seasonDesc) {
this.seasonName = seasionName;
this.seasonDesc = seasonDesc;
}
// 4. 提供实例变量的get方法
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
}
Enum类中常用的方法
- String toString():默认返回的是常量名(对象名), 可以继续手动重写该方法
- static 枚举类型[] values():返回枚举类型的对象数组。该方法可以方便地遍历所有的枚举值,是一个静态方法。
- static 枚举类型 valueOf(String name):可以把一个字符串转为对应的枚举类对象。要求字符串必须是枚举对象。
- String name():得到当前枚举常量的名称。
- int ordinal():返回当前枚举常量的次序号,默认从0开始。
public class SeasonTest {
public static void main(String[] args) {
// toString()
System.out.println(Season.SPRING);
// name()
System.out.println(Season.SPRING.name());
// values()
for (Season value : Season.values()) {
System.out.println("value = " + value);
}
// 字符串转枚举类型
// valueOf() 返回当前枚举类中名称为objName的枚举类对象。如果枚举类中不存在objName名称的对象,报错。
String objName = "WINTER";
Season season = Season.valueOf(objName);
System.out.println("season = " + season);
// ordinal()
System.out.println(Season.AUTUMN.ordinal());
}
}
枚举类实现接口的操作
- 情况1:枚举类实现接口,在枚举类中重写接口中的抽象方法。当通过不同的枚举类对象调用此方法时,执行的是同一个方法。
- 情况2:让枚举类的每一个对象重写接口中的抽象方法。当通过不同的枚举类对象调用此方法时,执行的是不同的实现方法。
package com.demo.enumdemo;
public class SeasonTest {
public static void main(String[] args) {
for (Season value : Season.values()) {
value.show();
}
}
}
interface Info {
void show();
}
enum Season implements Info {
// 1. 必须在枚举类的开头声明多个对象。对象之间使用,隔开
SPRING("春天", "春暖花开") {
public void show() {
System.out.println("SPRING");
}
},
SUMMER("夏天", "夏日炎炎") {
public void show() {
System.out.println("SUMMER");
}
},
AUTUMN("秋天", "秋高气爽") {
public void show() {
System.out.println("AUTUMN");
}
},
WINTER("冬天", "冰冷刺骨") {
public void show() {
System.out.println("WINTER");
}
};
// 2. 声明当前类的对象的实例变量 使用private final修饰
private final String seasonName;
private final String seasonDesc; // 季节的描述
// 3. 私有化类的构造器
private Season(String seasionName, String seasonDesc) {
this.seasonName = seasionName;
this.seasonDesc = seasonDesc;
}
// 4. 提供实例变量的get方法
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
}
Annotation ---- 注解
可用于修饰包、类、构造器、方法、成员变量、参数、局部变量的声明。
注解可以在类编译、运行时进行加载,体现不同的功能。
注解是一种趋势,框架 = 注解 + 反射 + 设计模式
元注解
对现有的注解进行解释说明的注解。
元数据
String name = "Tom";
String 和 name 修饰 "Tom"的两个结构,因此可以把String 和 name 看成 "Tom"的元数据。
反射
反射被视为"动态语言"的关键,在运行期间借助Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
通过反射,可以调用类中私有的结构。
Class
java.exe命令对指定的.class文件进行解释运行,.class字节码文件加载到内存中(存放在方法区),加载到内存中的.class文件对应的结构即为Class的一个实例。
运行时类在内存中会缓存起来,在整个执行期间,只会加载一次。
获取Class实例的方式
package com.demo;
import org.junit.Test;
public class ClassTest {
@Test
public void test1() throws ClassNotFoundException {
// 第一种方式:调用运行时类的静态属性:class
Class<Person> clazz1 = Person.class;
// 第二种方式:调用运行时类的对象的getClass()
Person person = new Person();
Class<? extends Person> clazz2 = person.getClass();
// 第三种方式:调用Class的静态方法forName(String className)** 能够更好的体现动态性
String className = "com.demo.Person"; // 类的全限定名
Class<?> clazz3 = Class.forName(className);
// 第四种方式:使用类加载器的方式
Class<?> clazz4 = ClassLoader.getSystemClassLoader().loadClass("com.demo.Person");
}
}
所有Java类型都有Class对象
// Properties: 处理属性文件
@Test
public void test3() throws Exception {
Properties pros = new Properties();
// 读取的文件默认路径为: 当前module下
// FileInputStream is = new FileInputStream(new File("info.properties"));
// 通过类的加载器读取的问及那的默认路径为:当前module下的src
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("info.properties");
pros.load(is);
String name = pros.getProperty("name");
String pwd = pros.getProperty("password");
System.out.println(name + ": " + pwd);
}
创建对象
- newInstance():要求高
要求提供的空参构造器的权限要足够;
空参的构造器:
1)子类对象在实例化时,子类的构造器的首行默认调用父类空参的构造器;
2)在反射中,经常用来创建运行时类的对象,要求各个运行时类提供一个空参的构造器,便于编写创建运行时类对象的代码;
@Test
public void test3() throws Exception {
Class clazz = Person.class;
// 创建Person的实例
Person person = (Person) clazz.newInstance(); // 调用Person的空参构造器
}
- JDK9通过Constructor类调用newInstance(..)
获取运行类的完整结构
Class clazz = Class.forName("com.demo.Person");
// 获取运行时父类
Class superclass = clazz.getSuperclass();
// 获取运行时带泛型的父类
Type genericSuperclass = clazz.getGenericSuperclass();
// 获取运行时类实现的接口 类可以实现多个接口
Class[] interfaces = clazz.getInterfaces();
// 获取运行时类所在的包
Package aPackage = clazz.getPackage();
// 强转带参数的泛型
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
// 泛型参数的数组
Type[] arguments = parameterizedType.getActualTypeArguments();
// 获取指定参数名称
System.out.println(((Class)arguments[0]).getName());
调用指定属性
Class clazz = Class.forName("com.demo.Person");
Person person = (Person) clazz.newInstance();
// 获取运行时类指定名的属性
Field nameField = clazz.getDeclaredField("name");
// 确保属性可以访问
nameField.setAccessible(true);
// 设置属性的值
nameField.set(person, 2);
// 获取属性的值
nameField.get(person);
调用指定方法
// 获取运行时方法
Method showNationMethod = clazz.getDeclaredMethod("showNation", String.class, int.class);
// 确保方法可访问
showNationMethod.setAccessible(true);
// 通过Method实例调用invoke(Object obj, Object ... objs),即对方法的调用
showNationMethod.invoke(person, "CHN", 10);
调用静态方法
// 获取运行时方法
Method showInfoMethod = clazz.getDeclaredMethod("showInfo");
// 确保方法可访问
showInfoMethod.setAccessible(true);
// 通过Method实例调用invoke(Object obj, Object ... objs),即对方法的调用
showInfoMethod.invoke(null);
调用构造器
Class clazz = Person.class;
// 通过Class的实例调用getDeclaredConstructor(Class ...args)
Constructor constructor = clazz.getDeclaredConstructor(String.class, int.class);
// 确保此构造器时可以访问的
constructor.setAccessible(true);
// 通过Constructor实例调用newInstance(Object ...args),返回一个运行时类的实例
Person tom = (Person) constructor.newInstance("Tom", 12);
调用注解
Class clazz = Customer.class;
// 获取类声明上的注解
Table annotation = (Table) clazz.getDeclaredAnnotation(Table.class);
Field nameField = clazz.getDeclaredField("name");
// 获取属性声明的注解
Column nameColumn = nameField.getDeclaredAnnotation(Column.class);
System.out.println(nameColumn.columnName());
System.out.println(nameColumn.columnType());
猜你喜欢
- 2024-11-09 Java基础入门要学哪些 怎么掌握反射和枚举
- 2024-11-09 谈谈枚举的新用法--java java枚举类型有什么用
- 2024-11-09 Java面试基础回顾16-枚举 java面试基础知识点
- 2024-11-09 实际工作中推荐使用java枚举类型,提高开发效率#编程
- 2024-11-09 java枚举enumeration java枚举根据value获取key
- 2024-11-09 大年初二来简单聊聊java中枚举类的前世今生
- 2024-11-09 如何用枚举消除if/else?-枚举高阶用法
- 2024-11-09 干货 | 一文搞定Python 枚举 python 枚举遍历
- 2024-11-09 Scala学习九之枚举和Trait了解 枚举compareto
- 2024-11-09 java中的enum第一期:enum存在的意义
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)