类的使用分为三个步骤:
类的加载->类的连接->类的初始化
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修饰的方法可以在其类外部被调用