Java的反射從類加載 到 連接 再到 初始化

類的使用分爲三個步驟:
類的加載->類的連接->類的初始化
1,類的加載
當程序運行的時候,系統會首先把我們要使用的Java類加載到內存中。這裏加載的是編譯後的.class文件。
每個類加載到內存中,會創建一個對應的Class對象。這個Class對象保存了這個類有哪些成員(數據成員,方法成員)。
【注意:這裏只有在某個Java類被使用的時候,纔會被加載。
每個類多次使用構造函數初始化,只會被加載到內存中一次,只會創建一個該類的Class對象】

加載時機:任何用到這個類的時候。
2,類加載器(JVM中用於加載的)
作用:將.class文件(可能在磁盤上,也可能在網絡上)加載到內存中,並生成與之對應的java.lang.Class對象
分類:
Bootstrap ClassLoader 根類加載器
加載JRE中的核心類,比如java.lang.String 。。。
Extension ClassLoader 擴展類加載器
加載JRE中的擴展類
System ClassLoader 系統類加載器
一般用來加載我們自己寫的類

//即將被加載的類
public class StudentFarther {

private int x;
public String y;

public StudentFarther() {
	
}
private StudentFarther(int x) {
	this.x = x;
}

private void setX(int x) {
	this.x = x;
}
public void setY(String y) {
	this.y = y;
}
}

----------------------------------------------------------
public class Student extends StudentFarther{

private int id;
protected String userName;
 String passWord;
public String phone;

private Student(int id) {
	this.id = id;
}

public Student(String userName, String passWord) {
	this.userName = userName;
	this.passWord = passWord;
}

public Student() {
}

public Student(int id, String userName, String passWord) {
	this.id = id;
	this.userName = userName;
	this.passWord = passWord;
}

public void setPhone(String p) {
	phone = p;
}

public void study() {
	System.out.println(userName+"正在學習");
}

public void study(String subject)
{
	System.out.println(userName+"正在學習"+subject);
}

@Override
public String toString() {
	return id+" "+userName+" "+passWord+" "+phone;
}

private int getId() {
	return id;
}

protected String getUserName() {
	return userName;
}

String getPassWord(){
	return passWord;
}	

public String getPhone() {
	return phone;
}
}

-------------------------------------------------------------
//關於獲得該類生成的Class的實例:
	Student s1 = new Student(1,"鐵樹王","123");
	Student s2 = new Student(2,"花開王","456");
	
	//獲取Class對象(反射的第一步)
	//方式一:通過對象獲得
	Class c1 = s1.getClass();
	Class c2 = s2.getClass();
	
	System.out.println(s1 == s2);//false
	System.out.println(s1.equals(s2));//false
	System.out.println(c1 == c2);//true
	System.out.println(c1.equals(c2));//true
	
	//方式二:通過類獲得
	Class c3 = Student.class;
	System.out.println(c1 == c3);//true
	
	//方式三:Class.forName("類路徑"),必須傳遞完整路徑(加上包名)
	Class c4 = Class.forName("reflexDemo.Student");
	System.out.println(c1 == c4);//true

反射:
解釋:在程序運行的時候,查看一個類有哪些信息(包含的數據成員和方法成員)。這個過程稱之爲反射

當我們不知道某個類的用法時–>我們需要使用反射獲取到類的信息,裏面有哪些成員,再使用。
反射(不知道---->獲取類信息—>使用(實例化對象,調用屬性和方法))

使用反射構造對象:

Class c = Class.forName("reflexDemo.Student");
	
	//1、得到所有的public構造方法
	Constructor[] con =c.getConstructors();
	
	//遍歷輸出所有的public構造方法
	for(Constructor cons:con)
		System.out.println(cons);
	
	//2、得到指定構造方法
	Constructor con1 = c.getConstructor(String.class,String.class);
	System.out.println(con1);
	
	//3、調用獲得的指定的構造方法構造並輸出對象
	Object obj = con1.newInstance("大鐵樹","123");
	System.out.println(obj);  //輸出:0(默認值) 大鐵樹 123
	-------------------------------------------------------------
Class可以使用的其他方法:
	關於構造方法:
	.getDeclaredConstructor(Class<?> ... parameterTypes );//忽略訪問權限,獲取指定參數列表的構造方法
	.getDeclaredConstructors();//忽略訪問權限,獲取所有構造方法
	關於字段:
	.getFields();//獲得所有public成員變量【包括父類(直接與間接父類)的】
	.getField("m");//獲得指定變量名的public成員變量【包括父類(直接與間接父類)的】
	.getDeclaredFields();//獲得所有的成員變量
	.getDeclaredField("passWord");//獲得指定變量名的成員變量
	關於方法:
	.getMethods();//獲得所有public的成員方法[包括父類的(直接與間接父類)]
	.getMethod("hashCode"[,Class... parameterTypes]);//獲得指定方法名的public成員方法[包括父類(直接與間接父類)],
	指定參數列表獲得,傳遞所需參數調用!
	.getDeclaredMethods();//獲得所有成員方法
	.getDeclaredMethod("study", String.class);//獲得指定方法名的成員方法
	
 Constructor可以使用的方法:
	.newInstance ()//使用該構造方法構造實例
	.setAccessible(true)//忽略該構造方法的訪問權限
Field可以使用的方法:
	.get(s);//得到實例s中field字段的值
	.setAccessible(true);//使private的字段可以在其類的外部訪問
Method可以使用的方法:
	.invoke(s[,Object... orgs]);//調用實例s中的該method方法,如需傳遞參數則進行傳遞
	.setAccessible(true);//使private修飾的方法可以在其類外部被調用
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章