在某些狀況下,一個類的對象是有限且固定的,對於這種對象的實例有限且固定的類,在 Java 中被稱爲枚舉類(Enum);枚舉類是爲了提升代碼可讀性,原始值是int類型(從0開始)。java
建立角色類型枚舉類(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() 方法遍歷全部枚舉值: 返回一個包含所有枚舉值的數組,能夠用來遍歷全部枚舉值。bash
for(RoleTypeEnum rt : RoleTypeEnum.values()) {
System.out.print(rt);//STUDENT TEACHER HEADER
}
複製代碼
舉個栗子🌰:微信
包含抽象方法的枚舉類: 定義一個 Calculator 枚舉類,有4個枚舉值PLUS、MINUS、TIMES、DIVIDE,分別表明加、減、乘、除,該枚舉類有一個 calculate() 抽象方法,用於完成計算。框架
包含抽象方法的枚舉類Calculator:ide
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));
}
}
複製代碼
1、什麼是反射? Java反射說的是在運行狀態中,對於任何一個類,咱們都可以知道這個類有哪些屬性和方法。對於任何一個對象,咱們都可以對它的屬性和方法進行調用。咱們把這種動態獲取對象信息和調用對象方法的功能稱之爲反射機制。ui
解釋:在程序運行的時候,查看一個類有哪些信息(包含的成員變量和成員方法),這個過程稱之爲反射。this
通常狀況下:若是咱們知道咱們要使用哪一個類,那麼咱們只須要用這個類建立對象,而後就能夠經過這個對象調用類裏面的數據變量和方法。 可是若是咱們不知道咱們要使用哪一個類,這個時候咱們就須要使用反射來獲取到類的信息,知道里面有哪些屬性和方法,再使用。
不知道類-->獲取類信息-->使用(實例化對象,調用屬性和方法):這就是反射。 能夠先看完下面的栗子🌰了,再來理解反射機制,會更清楚。
給定一個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);
}
}
複製代碼
一、獲取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
複製代碼
二、利用反射構造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();
}
}
複製代碼
三、利用反射獲取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
}
}
複製代碼
四、利用反射獲取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,"編程");
}
}
複製代碼
看到這裏你已經對反射有了一個簡單的瞭解,可使用反射獲取一些屬性方法,其實咱們平時寫代碼不多用到反射技術,可是在咱們使用的一些主流框架中反射技術應用是很是普遍的,因此學好反射也是很是有必要的。
今日寄語:
歡迎關注我的微信公衆號:桃李報春