### 1.Class類
普通對象構造方式:
~~~
// 創建Book實例對象
Book book = new Book();
~~~
對于Class的實例對象如何構造呢?
Class的構造函數是私有的,只有JVM才能創建實例對象
~~~
// Class的構造函數是私有的,只有JVM才能創建Class實例對象
Class class1 = new Class(); // 錯誤
~~~
~~~
public final class Class<T> implements java.io.Serializable,
java.lang.reflect.GenericDeclaration,
java.lang.reflect.Type,
java.lang.reflect.AnnotatedElement {
/*
* Constructor. Only the Java Virtual Machine creates Class
* objects.
*/
private Class() {}
....
}
~~~
Class有三種表示方式:
(1)XXX.class ?XXX為類名 ?
實際再告訴我們任何一個類都有一個隱含的已經太成員變量class
~~~
Class class1 = Book.class;
~~~
(2)XXX.getClass() ?XXX為對象名稱
已知該類的實例對象,通過getClass()方法獲取
~~~
Book book = new Book();
Class class2 = book.getClass();
~~~
(3)通過Class類的forName方法獲取 ?
~~~
try {
Class class3 = Class.forName("com.qunar.bean.Book");
System.out.println(class1 == class2);
System.out.println(class1 == class3);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
~~~
我們完全可以通過類的類類型創建該類的對象實例,通過class1,class2以及class3創建Book的實例
~~~
try {
Class class3 = Class.forName("com.qunar.bean.Book");
// 通過類類型的newInstance方法創建實例對象
Book book2 = (Book)class3.newInstance();
book2.setPrice("23.4");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
~~~
### 2.Class動態加載類
Class.forName("類的全稱") 不僅表示了類的類類型,還代表了動態加載類。
編譯時刻加載類是靜態加載類,運行時刻加載類是動態加載類。
### 3.反射
反射機制--用來檢查可用的方法,并返回方法名。
人們想要在運行時獲取類的信息的另一個動機,便是希望提供在跨網絡的遠程平臺上創建和運行對象的能力。這被稱為遠程方法調用,它允許一個Java程序將對象分布到多臺機器上。
class類與java.lang.reflect類庫一起對反射的概念進行了支持,該類庫包含了Filed,Method以及Constructor類(每個類都實現了Member接口)。這些類型的對象是由JVM在運行時創建的,用以表示未知類里對應的成員。這樣你就可以使用Constructor創建新的對象,用get()和set()方法讀取和修改與Field對象關聯的字段,用invoke()方法調用與method對象關聯的方法。另外,還可以調用getFields(),getMethods()和getConstructors()等很便利的方法,以返回表示字段,方法以及構造器的對象的數組。這樣,匿名對象的類信息就能在運行時被完全確定下來,而在編譯時不需要知道任何事情。
其實,反射機制并沒有什么神奇之處。當通過反射與一個未知類型的對象打交道時,JVM只知道簡單的檢查這個對象,看它屬于哪個特定的類。在用它做其他事情之前,我們必須先加載這個類的class對象。因此,那個類的.class文件對于JVM來說必須是可獲取的,要么在本地機器上,要么可以通過網絡可以獲得。對于反射機制而言,在編譯時不能取得.class文件,只能在運行時打開和檢查.class文件。
3.1 獲取方法信息
~~~
package com.qunar.reflect;
public class ReflectDemo {
public static void main(String[] args) {
// int的類類型
Class class1 = int.class;
Class class2 = String.class;
Class class3 = double.class;
Class class4 = Double.class;
Class class5 = void.class;
System.out.println("class1->" + class1.getName());
System.out.println("class2->" + class2.getName());
System.out.println("class3->" + class3.getName());
System.out.println("class4->" + class4.getName());
System.out.println("class5->" + class5.getName());
}
}
~~~
運行結果:
<table cellspacing="0" cellpadding="0" style="margin:8px 0px; border-collapse:collapse; border:1px solid rgb(187,187,187); width:892px"><tbody><tr><td style="padding:4px 8px; border-collapse:collapse; border:1px solid rgb(187,187,187); width:875px"><br/><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">class1->int</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">class2->java.lang.String</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">class3->double</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">class4->java.lang.Double</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">class5->void</span></div></td></tr></tbody></table>
~~~
// 只打印簡單名稱(不包含包名稱)
System.out.println("class2->" + class2.getSimpleName()); // String
~~~
~~~
/**
* 打印類成員方法信息(public函數,包括父類繼承而來的)
* @param object
*/
public static void PrintClassPublicFunction(Object object){
// 獲取類的信息,首先獲取類的類類型
// 傳遞的是哪個子類的對象 c 就是該子類的類類型
Class c = object.getClass();
System.out.println("類的全稱是:" + c.getName());
// 一個成員方法就是一個method對象
// getMethods方法是獲取的是所有public的函數,包括父類繼承而來的
Method[] methods = c.getMethods();
for (Method method : methods) {
// 獲取方法返回值類型的類類型
Class returnType = method.getReturnType();
System.out.print(returnType.getName() + " ");
// 獲取方法的名稱
System.out.print(method.getName() + "(");
// 獲取方法參數
// 得到方法參數列表中類型的類類型
Class[] paramTypes = method.getParameterTypes();
int size = paramTypes.length;
for (int i = 0;i < size;++i) {
if(i != 0){
System.out.print(",");
}//if
System.out.print(paramTypes[i].getName());
}//for
System.out.println(")");
}//for
}
~~~
運行結果:
<table cellspacing="0" cellpadding="0" style="margin:8px 0px; border-collapse:collapse; border:1px solid rgb(187,187,187); width:892px"><tbody><tr><td style="padding:4px 8px; border-collapse:collapse; border:1px solid rgb(187,187,187); width:875px"><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">boolean?startsWith(java.lang.String)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">boolean?startsWith(java.lang.String,int)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.CharSequence?subSequence(int,int)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.String?substring(int,int)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.String?substring(int)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">[C?toCharArray()</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.String?toLowerCase(java.util.Locale)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.String?toLowerCase()</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.String?toUpperCase()</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.String?valueOf([C)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.Class?getClass()</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">void?notify()</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">void?notifyAll()</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">void?wait(long)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">void?wait(long,int)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">void?wait()</span></div>....</td></tr></tbody></table>
3.2 獲取成員變量信息
~~~
/**
* 打印類成員變量信息
* @param object
*/
public static void PrintClassFiled(Object object){
// 獲取類的信息,首先獲取類的類類型
// 傳遞的是哪個子類的對象 c 就是該子類的類類型
Class c = object.getClass();
/* 成員變量也是對象,java.lang.reflect.Field 類封裝了關于成員變量的操作
* getFields()方法獲取的是所有的public的成員變量的信息
* getDeclaredFields()獲取的是該類自己聲明的成員變量的信息
*/
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
// 得到成員變量的類型的類類型
Class fieldType = field.getType();
// 得到成員變量的類型
System.out.print(fieldType.getName() + " ");
// 得到成員變量的名稱
System.out.println(field.getName());
}//for
}
~~~
運行結果:
<table cellspacing="0" cellpadding="0" style="margin:8px 0px; border-collapse:collapse; border:1px solid rgb(187,187,187); width:892px"><tbody><tr><td style="padding:4px 8px; border-collapse:collapse; border:1px solid rgb(187,187,187); width:875px"><br/><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">int?MIN_VALUE</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">int?MAX_VALUE</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.Class?TYPE</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">[C?digits</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">[C?DigitTens</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">[C?DigitOnes</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">[I?sizeTable</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">int?value</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">int?SIZE</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">long?serialVersionUID</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">boolean?$assertionsDisabled</span></div></td></tr></tbody></table>
3.3 獲取構造函數信息
~~~
/**
* 打印類構造函數信息
* @param object
*/
public static void PrintClassConstructor(Object object){
// 獲取類的信息,首先獲取類的類類型
// 傳遞的是哪個子類的對象 c 就是該子類的類類型
Class c = object.getClass();
/* 構造函數也是對象,java.lang.reflect.Constructor 類封裝了關于構造函數的操作
* getConstructors()方法獲取的是所有的public的構造函數的信息
* getDeclaredConstructors()獲取的是該類自己聲明的構造函數的信息
*/
Constructor[] constructors = c.getConstructors();
for (Constructor constructor : constructors) {
// 構造函數的名稱
System.out.print(constructor.getName() + "(");
// 獲取構造函數的參數列表,得到的是參數列表的類類型
Class[] paramTypes = constructor.getParameterTypes();
int size = paramTypes.length;
for(int i = 0;i < size;++i){
if(i != 0){
System.out.print(",");
}//if
// 得到參數名稱
System.out.print(paramTypes[i].getName());
}//for
System.out.println(")");
}//for
}
~~~
運行結果:
<table cellspacing="0" cellpadding="0" style="margin:8px 0px; border-collapse:collapse; border:1px solid rgb(187,187,187); width:892px"><tbody><tr><td style="padding:4px 8px; border-collapse:collapse; border:1px solid rgb(187,187,187); width:875px"><br/><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.String([B)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.String([B,int,int)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.String([B,java.nio.charset.Charset)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.String([B,java.lang.String)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.String([B,int,int,java.nio.charset.Charset)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.String(java.lang.StringBuilder)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.String(java.lang.StringBuffer)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.String([I,int,int)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.String([C,int,int)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.String([C)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.String(java.lang.String)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.String()</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.String([B,int,int,java.lang.String)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.String([B,int)</span></div><div style="margin:0px"><span style="font-size:14pt; color:windowtext; font-family:微軟雅黑">java.lang.String([B,int,int,int)</span></div></td></tr></tbody></table>
3.4 方法的反射
如何獲取某個方法?方法的名稱和方法的參數列表才能唯一決定某個方法。
如何進行操作?通過method.invoke(對象,參數列表)
~~~
package com.qunar.reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import com.qunar.bean.Calculates;
public class ReflectDemo {
public static void main(String[] args) {
// 獲取類的信息,首先獲取類的類類型
Calculates calculates = new Calculates();
calculates.setNum1(20);
calculates.setNum2(40);
Class c = calculates.getClass();
/* getMethod()方法獲取的是public的方法信息
* getDeclaredMethod()獲取的是該類自己聲明的方法的信息
*/
try {
// 獲取方法 名稱和參數列表共同決定
// Method method = c.getDeclaredMethod("add", new Class[]{int.class,int.class});
Method method = c.getDeclaredMethod("add", int.class,int.class);
// 方法的反射
// 對于calculates.add(10,40)來說,方法的反射操作是用method方法調用 和 calculates.add(10,40)的效果一樣
// int result = (int)method.invoke(calculates, new Object[]{10,40});
int result = (int)method.invoke(calculates, 10,40);
System.out.println(result);
// 對于沒有參數的方法
Method method2 = c.getDeclaredMethod("print");
method2.invoke(calculates);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
~~~
- 前言
- [Hibernate開發之路](1)Hibernate配置
- [Hibernate開發之路](2)Hibernate問題
- [Hibernate開發之路](3)基礎配置
- [Hibernate開發之路](4)ID生成策略
- [Hibernate開發之路](5)聯合主鍵
- [設計模式實踐之路](1)單例模式
- [Java]UDP通信的簡單例子
- [Java]套接字地址InetAddress講解
- [Java開發之路](1)final關鍵字
- [Java開發之路](2)Java字符串
- [Java開發之路](3)Java常用類
- [Java開發之路](4)String、StringBuffer與StringBuilder詳解
- [Java開發之路](5)異常詳解
- [Java開發之路](6)File類的使用
- [Java開發之路](7)RandomAccessFile類詳解
- [Java開發之路](8)輸入流和輸出流
- [Java開發之路](9)對象序列化與反序列化
- [Java開發之路](10)DOM解析XML文檔
- [Java開發之路](11)SAX解析XML文檔
- [Java開發之路](12)JDOM和DOM4J解析XML文檔
- [Java開發之路](14)反射機制
- [Java開發之路](15)注解
- [Java開發之路](16)學習log4j日志
- [Java開發之路](18)關于Class.getResource和ClassLoader.getResource的路徑問題
- [Java開發之路](19)Long緩存問題
- [Java開發之路](20)try-with-resource 異常聲明
- [Java開發之路](21)Comparator與Comparable
- [Java]Java工程師成神之路
- [細說Java](1)圖說字符串的不變性
- [細說Java](2)Java中字符串為什么是不可變的
- [細說Java](3)創建字符串是使用&quot; &quot;還是構造函數?