网站首页 > java教程 正文
枚举
枚举本质也是一种类,只不过是这个类的对象是有限的、固定的几个,不能让用户随意创建。
如果枚举类的实例只有一个,则可以看做是单例的实现方式。
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-10-06 关于Java中枚举Enum的深入剖析(java中枚举类型的使用)
- 2024-10-06 常用类及枚举类(一)(枚举类和普通类的区别)
- 2024-10-06 深入剖析Java Enum类型(javaenum使用实例)
- 2024-10-06 Java enum——不一样的枚举对象(java 枚举使用)
- 2024-10-06 Java的enum的用法详解(java enum使用)
- 2024-10-06 学习廖雪峰的JAVA教程---java核心类(枚举类)
- 2024-10-06 Java枚举(JAVA枚举类型怎么用)
- 2024-10-06 java高级特性之泛型和枚举(java 泛型实现)
- 2024-10-06 java里枚举非常实用的3个方法,程序员一般都不注意
- 2024-10-06 给大伙讲一讲枚举的使用以及原理(枚举是干嘛的)
你 发表评论:
欢迎- 最近发表
-
- 你真的会用 Java 中的线程池吗?多个企业级线程池工具类封装实践
- 线程池的实现原理、优点与风险、以及四种线程池实现
- Java线程池ThreadPoolExecutor实现原理剖析
- 深入分析线程池的实现原理(线程池是干嘛的)
- 一文搞懂JAVA线程池工作原理(java线程池的工作流程)
- Java线程池的工作原理(java线程池的实现原理)
- 5分钟读懂C#中TcpClient、TcpListener和Socket三个类的角色
- JVM对象的创建过程(jvm运行过程中创建的对象一般存放在方法区)
- 对象组成与Java内存模型JMM分析(java对象在内存中存储的结构)
- JVM对象内存分配详细过程(栈上分配->TLAB->老年代->Eden区)
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)