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修饰的方法可以在其类外部被调用
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章