Java枚举类和反射机制
一、Java枚举类(Enum):
在某些情况下,一个类的对象是有限且固定的,对于这种对象的实例有限且固定的类,在 Java 中被称为 枚举类(Enum) ;枚举类是为了提高代码可读性,原始值是int类型(从0开始)。
创建角色类型枚举类(RoleTypeEnum):Java 中使用 enum 关键字来定义枚举类
// 定义一个角色类型的枚举类
public enum RoleTypeEnum {
// 在第一行显式地列出3个枚举实例(枚举值),系统会自动添加 public static final 修饰
STUDENT,TEACHER,HEADER //0-学生,1-老师,2-校长
复制代码
int ordinal(): 返回枚举值在枚举类中的索引值(从0开始),即枚举值在枚举声明中的顺序,这个顺序根据枚举值声明的顺序而定。
public class Demo01_Enum {
public static void main(String[] args) {
RoleTypeEnum rt1 = RoleTypeEnum.STUDENT;
RoleTypeEnum rt2 = RoleTypeEnum.HEADER;
//int ordinal(): 返回枚举值在枚举类中的索引值(从0开始)
System.out.println(rt1);//STUDENT
System.out.println(rt1.ordinal());//0
System.out.println(rt2);//HEADER
System.out.println(rt2.ordinal());//2
复制代码
static values() 方法遍历所有枚举值: 返回一个包含全部枚举值的数组,可以用来遍历所有枚举值。
for(RoleTypeEnum rt : RoleTypeEnum.values()) {
System.out.print(rt);//STUDENT TEACHER HEADER
复制代码
举个栗子🌰:
包含抽象方法的枚举类: 定义一个 Calculator 枚举类,有4个枚举值PLUS、MINUS、TIMES、DIVIDE,分别代表加、减、乘、除,该枚举类有一个 calculate() 抽象方法,用于完成计算。
包含抽象方法的枚举类Calculator:
public enum Calculator {
// 加法运算
PLUS { // 花括号部分其实是一个匿名内部子类
@Override
public int calculate(int x, int y) {
return x + y;
// 减法运算
MINUS { // 花括号部分其实是一个匿名内部子类
@Override
public int calculate(int x, int y) {
// TODO Auto-generated method stub
return x - y;
// 乘法运算
TIMES { // 花括号部分其实是一个匿名内部子类
@Override
public int calculate(int x, int y) {
return x * y;
// 除法运算
DIVIDE { // 花括号部分其实是一个匿名内部子类
@Override
public int calculate(int x, int y) {
return x / y;
//为该枚举类定义一个抽象方法,枚举类中所有的枚举值都必须实现这个方法
public abstract int calculate(int x, int y);
复制代码
加、减、乘、除计算:
public class TestDemo {
public static void main(String[] args) {
//加、减、乘、除计算
System.out.println("2 + 2 = " + Calculator.PLUS.calculate(2, 2));
System.out.println("5 - 2 = " + Calculator.MINUS.calculate(5, 2));
System.out.println("2 * 2 = " + Calculator.TIMES.calculate(2, 2));
System.out.println("4 / 2 = " + Calculator.DIVIDE.calculate(4, 2));
二、Java类的加载机制和反射:
一、什么是反射?
Java反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类有哪些属性和方法。对于任何一个对象,我们都能够对它的属性和方法进行调用。我们把这种动态获取对象信息和调用对象方法的功能称之为反射机制。
解释:在程序运行的时候,查看一个类有哪些信息(包含的成员变量和成员方法),这个过程称之为反射。
一般情况下:如果我们知道我们要使用哪个类,那么我们只需要用这个类创建对象,然后就可以通过这个对象调用类里面的数据变量和方法。
但是如果我们不知道我们要使用哪个类,这个时候我们就需要使用反射来获取到类的信息,知道里面有哪些属性和方法,再使用。
不知道类-->获取类信息-->使用(实例化对象,调用属性和方法):这就是反射。
可以先看完下面的栗子🌰了,再来理解反射机制,会更清楚。
给定一个User类:(里面有很多属性、构造方法和普通方法,有些是私有的,有些是公共的)
public class User {
private int id;
private String name;
private String password;
public int age;
public User() {}
private User(int id) {
this.id=id;
public User(int id,String name,String password,int age) {
this.id=id;
this.name=name;
this.password=password;
this.age=age;
public void show() {
System.out.println(id+":"+name+":"+password);
public void study() {
System.out.println("学习");
public void study(String courseName) {
System.out.println("正在学习"+courseName);
private void shower(String courseName) {
System.out.println("正在学习私有"+courseName);
复制代码
1、获取Class对象:
方法一:通过对象来获取 user1.getClass()
User user1 = new User(101, "admin", "123456");
User user2 = new User(102, "User01", "123");
Class c1 = user1.getClass();//获取user1的Class对象
Class c2 = user2.getClass();//获取user2的Class对象
System.out.println(c1);//class com.sikiedu.chapter4.User
System.err.println(c2);//class com.sikiedu.chapter4.User
复制代码
方法二:通过类来获取 User.class
Class class4 = User.class;
System.out.println(class4);
复制代码
方法三:通过 Class.forName("路径类名")
Class class5 = Class.forName("java.lang.Math");
System.out.println(class5);//class java.lang.Math
复制代码
2、利用反射构造User类的对象(获取构造方法):
通过类对象c得到所有的public构造方法(公共的):c.getConstructors();
通过类对象c得到所有的构造方法(包括私有的):c.getDeclaredConstructors();
通过类对象c得到public单个构造方法:c.getConstructor();
通过类对象c得到private单个构造方法(私有的):c.getDeclaredConstructor();
调用无参构造方法:Object object= con.newInstance();
调用私有的无参构造方法(需设置setAccessible(true)):
con.setAccessible(true);
Object object = con.newInstance();
举个栗子🌰:
public class Demo02 {
public static void main(String[] args) throws Exception {
//1.取到类对象
Class c = Class.forName("com.sikiedu.chapter4.User");
//通过类对象得到所有的构造方法(包括私有的)
Constructor[] con = c.getDeclaredConstructors();
for(Constructor conall : con) {
System.out.println(conall);
//2.通过类对象得到类的单个构造方法public
Constructor con1 = c.getConstructor();//无参的构造方法
Constructor con2 = c.getConstructor(int.class,String.class,String.class);//有参数的构造方法
//加上Declared获取私有的构造方法private
Constructor con3 = c.getDeclaredConstructor(int.class);
//3.调用无参构造方法
Object o1 = con1.newInstance();
Object o2 = con2.newInstance(1001,"admin","123");
con3.setAccessible(true);//是否可以接触私有的,设置为true
Object o3 = con3.newInstance(123);
User user = (User)o3;
user.show();
复制代码
3、利用反射获取User类的成员变量:
通过类对象c得到所有的public成员变量(公共的):c.getFields();
通过类对象c得到所有的成员变量(包括私有的):c.getDeclaredFields();
通过类对象c得到public单个成员变量:c.getField("age").get(user1);
通过类对象c得到private单个成员变量(私有的):
c.getDeclaredField("name").get(user1);
举个栗子🌰:
public class Demo03 {
public static void main(String[] args) throws Exception {
User user1 = new User(1001,"admin","123456",21);
//1.取到类对象
Class c = Class.forName("com.sikiedu.chapter4.User");
//利用反射得到User的所有成员变量(包括私有的)
Field[] fields= c.getDeclaredFields();
for(Field field : fields) {
System.out.println(field);
// private int com.sikiedu.chapter4.User.id
// private java.lang.String com.sikiedu.chapter4.User.name
// private java.lang.String com.sikiedu.chapter4.User.password
// public int com.sikiedu.chapter4.User.age
//利用反射得到User的public成员变量(公共的)
Field[] fields2= c.getFields();
for(Field field : fields2) {
System.out.println(field);
// public int com.sikiedu.chapter4.User.age
//得到单个公共的
Field fieldage = c.getField("age");
System.out.println(fieldage.get(user1));//21
//得到单个私有的
Field fieldname = c.getDeclaredField("name");
fieldname.setAccessible(true);
System.out.println(fieldname.get(user1));//admin
复制代码
4、利用反射获取User类的成员方法:
通过类对象c得到所有成员方法(包括父类的):c.getMethods();
通过类对象c得到自身的所有成员方法(包括私有的private):c.getDeclaredMethods();
通过类对象c得到public单个成员方法:c.getMethod("show").invoke(user1);
通过类对象c得到private单个成员方法(私有的):
c.getDeclaredMethod("shower",String.class).invoke(user1,"编程");
举个栗子🌰:
public class Demo02 {
public static void main(String[] args) throws Exception {
User user1 = new User(1001,"admin","123456",21);
//1.取到类对象
Class c = Class.forName("com.sikiedu.chapter4.User");
//利用反射得到User的所有成员方法(包括父类的)
Method[] methods= c.getMethods();
for(Method method : methods) {
System.out.println(method);
// public void com.sikiedu.chapter4.User.show()
// public void com.sikiedu.chapter4.User.study()
// public void com.sikiedu.chapter4.User.study(java.lang.String)
// public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
// public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
// public final void java.lang.Object.wait() throws java.lang.InterruptedException
// public boolean java.lang.Object.equals(java.lang.Object)
// public java.lang.String java.lang.Object.toString()
// public native int java.lang.Object.hashCode()
// public final native java.lang.Class java.lang.Object.getClass()
// public final native void java.lang.Object.notify()
// public final native void java.lang.Object.notifyAll()
//利用反射得到User的自身的所有成员方法(包括私有的private)
Method[] methods2= c.getDeclaredMethods();
for(Method method : methods2) {
System.out.println(method);
// public void com.sikiedu.chapter4.User.study()
// public void com.sikiedu.chapter4.User.study(java.lang.String)
// public void com.sikiedu.chapter4.User.show()
//得到单个成员方法
Method method = c.getMethod("show");
Object object = method.invoke(user1);
//得到单个有参数
Method method2 = c.getDeclaredMethod("shower",String.class);
method2.setAccessible(true);
Object object2 = method2.invoke(user1,"编程");
看到这里你已经对反射有了一个简单的了解,可以使用反射获取一些属性方法,其实我们平时写代码很少用到反射技术,但是在我们使用的一些主流框架中反射技术应用是非常广泛的,所以学好反射也是非常有必要的。
今日寄语:
"人的一生为什么要努力?" "因为最痛苦的事,不是失败,是我本可以!"——杨熹文
欢迎关注个人微信公众号:桃李报春