反射、类加载与垃圾回收

反射、类加载与垃圾回收

反射

Java执行的过程:

Java文件——》编译——》.class字节码——运行——》类加载器(static/string常量)/字节码校验器/解释器——》OS

它允许运行中的程序对自身进行检查,并直接操作程序中的内部属性

重点语句:反射允许我们在运行时探究和使用编译时未知的类

反射使用步骤:
1、获取Class对象
1-1、通过类名获取类的Class对象——无动态性
优势:可以获取所有类型的Class对象;
劣势:没有动态效果;
例如:Class stuClass = studentBean.class;
          Class stuClass =String.class;
    Class intClass =int.class;
    Class voidClass =void.class;
    Class  intArrayClass = int【】.class; 
          Class   compClass = comparable.class;
1-2、通过实例对象获取类的Class对象
只能获取Object子类类型的getClass对象——类、数组,原因是因为getClass方法是定义在Object当中的;
可以根据传入的对象配合动态绑定,具备一定的动态效果
    StudentBean stu= new studentBean();
    Class   stuClass0=stu.getClass();

1-3、通过类的字符串形式的类全名,获取Class对象
通过这句代码可以主动加载一个类,而加载类的时候自动执行类当中的静态代码块;
具备动态性;
本方式只支持类、接口;
try{
//写代码时可以不确定className的值,运行起来后通过外部读文件,用户输入等各种手段获取,才最终确定
  String className="con.lang.bean.StudentBean"; 
Class  stuClass1=Class.forName(className);
}catch{

}

     java.lang.Sring  类全名
"con.lang.bean.StudentBean"  字符串形式的类全名

     Class  stuClass1=Class.forName("con.lang.bean.StudentBean");   获取Class对象

使用情况:
如果使用场景要求动态性——编译时未知,运行时需要探究和使用的,那么放弃第一种,选择后两种;
再判断如果场景中能获取到要探究类的实例对象,选择第二种;
否则只能选择第三种,要求从程序外部(配置文件,数据库,用户输入)获取类的字符串形式类全名。

 

2、探究到类的信息(属性/构造/方法)

2-0、类的声明信息
   String name =   stuClass.getName();
    String name =   stuClass.getSimpleName();   这里得到简单的类名    
    int classMod=stuClass.getmodifiers();
    String  classModStr = Modfier.toString(classMod);
    String superClassName=stuClass.getSuperclass().getSimpleName();//获取父类
    Class[] stuInterfaces = stuClass.getInterfaces();//获取接口
    String interStr=“”;
    if(stuInterfaces!=null&&stuInterfaces.length!=0){
    interStr="implements";
    for(int i=0;i<stuInterfaces.length;i++){
        interStr+=stuInterfaces[i].getSimpleName();
        if(i!=stuInterfaces.length-1){
        interStr+=",";
}
}

}
    System.out.println("package"+packageName+";")
    System.out.println(classModStr+“class”+name
“extends”+superClassName+"{");
Class对象:  package——包、   filed——属性、  Construtor ——构造、 method ——方法;


(相同名的,用的多的用导入import,用得少的用全名)
2-1、类的属性声明信息——JDK的反射当中使用Filed类型表示属性,Declared表示单复数
探究属性一共有4个常用方法:
1、filed【】 allPublicFields=stuClass.getFields();//返回所有的公共属性(包括从继承结构中获取的)
2、filed【】 allFields=stuClass.DeclaredFields();//返回所有声明的属性(只包括定义在本类身上的)

try{
3、Field thePublicField = stuClass.getField(“stuName”);//通过属性名寻找该类是否包含一个同名的公共属性(包括从继承结构获取的)
}catch{
}

4、Field  theField =stuClass.getDeclaredField("stuName");//通过属性名寻找该类是否包含一个在自己本类声明的同名属性

for(Field f :  allFields){
String fieldName = f.getName();//属性名
Class  typeClass  = f.getType();
String typeName=typeClass.getSimpleName();
String fMod=Modifier.toString(f.getModifiers());
system.out.println("\t"+fMod+""+typeName+""+f.getName()+";");

}

2-2、类的构造声明信息——JDK的反射当中使用Constructor类型表示构造,Declared表示单复数
探究构造有4个方法
1、Constructor<StudentBean>[ ] allPublicCons=stuClass.getConstructors();//返回所有的公共构造
2、Constructor<StudentBean>[ ] allCons=stuClass.getDeclaredConstructors();//f返回所有的构造(不受访问修饰符限制)
3、//获取指定的构造方法,必须传入参数列表
 Constructor<StudentBean> thePublicCon=stu.Class.getConstructor(String.class, int.class, boolean.class);//返回指定某个的公共构造
4、 Constructor<StudentBean> theCon=stu.Class.getDeclaredConstructor();//获取指定的构造(不受访问修饰符限制)

for(Constructor<StudentBean> Con  : allCons){
String conName=con.getName();//构造名
String conMod=Modifier.toString (con.getModifiers());//构造修饰符
Parameter 【】 params=con.getParameters();构造参数
Class【 】 exceptions= con.getExceotionTypes();抛出异常
String paramStr=“”;
if(params!=null&&params.length!=0){
    for(int i=0;i<params.length;i++){
Parameter p=params[i]
}

}

 


}

2-3、类的行为声明信息——JDK的反射当中使用Method类型表示构造

 

Method【】 allPublicMethod=stuClass。getMethod

 

3、使用类的信息      属性     赋值/取值
                构造     产生实例对象(这里反射就是第三种产生实例对象的方法了。1、new一个实例化对象。2、反序列化一个实例对象)
                方法     调用

3-1、使用Class对象记录的类的信息
try{
Constructor con=getDeclaredConstructor(String.class, int.class, boolean.class);//通过Class对象获取到指定构造方法
StudentBean  s=(StudentBean)con.newInstance("zhang2",18,true);//注意:1、要考虑con的访问修饰符能不能在这里调用到,2、考虑参数的匹配(个数、顺序、类型)

//补充:如果通过反射的方式调用公共无参构造产生实例对象,可以利用以下方简便方法:
首先,利用Class对象的newInstance方法

try{
StudentBean  s=(StudentBean)stuClass.newInstance();//这是框架和工具设计人员在设计是默认使用的,也就成为了JavaBean的规范——必须要有公共无参构造
}
}


3-2、用探究到的属性,给实例对象的该属性赋值取值
StudentBean s1=new StudentBean ();
StudentBean s2=new StudentBean ();
StudentBean s3=new StudentBean ();
try{
filed  f=stuClass.getFields("stuName");
f.set(s1,"古天乐");//给属性赋值;注意:1、第一个参指代给那个实例对象的属性赋值;2、注意操作书写位置是否与访问修饰符相符;3、值的类型是否与属性的类型相符;
system.out.println(f.get(s1));//从属性取值;注意:1、参数是指代从哪个实例对象中取值;2、注意书写未知是否与访问修饰符相符;3、返回值的类型是否与属性的类型相符
system.out.println(f.get(s2));


stu.setStuName("郭靖");//实例对象;是哪个方法;这个方法的实参
}


3-3、用探究到的方法,让实例对象调用该方法

 

类加载

类加载  ——》连接(验证--->准备--->解析)  ——》初始化


student类:
相对关系——》实例对象 :类型 student/数量 不限    ——》给程序员用的
                           类模板对象:类型   .Class     数量只有一个     ——》给JVM用的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值