java反射

第一部分:
类的加载机制:
1.new Person()加载到内存
2.Person.静态成员 加载到内存
class被加载到内存,那么class中的静态代码块就会被运行
3.创建了这个类的子类对象
4.使用反射技术调用这个类
5.直接在cmd中 (java 这个类)相当于运行这个类里面的main方法,也会加载进去。直接使用java.exe命令运行某个主类

第二部分:
类的加载器 ClassLoader,分为三类加载器
运行class,加载到内存,方法区
1.引导类加载器:BootClassLoder。负责加载JDK中的核心类库
jre/lib/rt.jar
2.扩展类加载器:ExtClassLoader
负责加载JDK的扩展类库
jre/lib/ext/
3.应用类加载器:AppClassLoader
加载我们自己写的类,或者是第三方jar包

第三部分:
获取类的加载器

public class MyClassLoader {
    public static void main(String[] args) {
        ClassLoader cl = String.class.getClassLoader();
        System.out.println(cl);
    }
}

输出的结果为null
这是因为类加载器是C++编写,根本和java无关,所以所有的核心类库是看不到的。

public class MyClassLoader {
    public static void main(String[] args) {
        //核心类库里面的类
        ClassLoader cl = String.class.getClassLoader();
        System.out.println(cl);
        //扩展类
        ClassLoader c1 = DNSNameService.class.getClassLoader();
        System.out.println(c1);
        //自己写的类
        ClassLoader c2 = MyClassLoader.class.getClassLoader();
        System.out.println(c2);
    }
}

null
sun.misc.Launcher$ExtClassLoader@29453f44
sun.misc.Launcher$AppClassLoader@18b4aac2

第四部分:
双亲委派:
类加载器的特性:双亲委派,谁用谁加载

public class Test {
    public static void main(String[] args) {
        String s = "abc";
        new Person();
    }
}

java Test 运行此类,Test就要加载到内存中,App加载器加载到内存中!!
Test使用了String,道理上String是APP加载,但是APP加载任务交给他的双亲,交给Ext,Ext加载任务交给Boot加载器。
当遇到new Person()的时候,APP加载器不加载,把他交给Ext,Ext交给Boot加载器,Boot不管之后,App再加载。

第五部分:
class文件对象产生
APP加载器将class文件加载到方法区中,并且为这个class文件堆区中创建一个对象。
那么这个对象是怎么产生的呢?是由java.lang.class类产生的。

第六部分:
反射:
概念:将java代码的各个组成部分封装为其他对象,可以在程序运行的过程中操作这些对象,这就是java的反射机制。
一个类内部包含构造方法、成员变量、成员方法。所谓的反射技术,就是要打开这个类,可以直接拿取类内部的东西来使用,而不是像之前那样通过new对象来实现。拿到的构造方法为Constructor类(里面有newInstance来创建对象),拿到的成员变量为Field类(set()给变量赋值),拿到的成员方法为Method类(invoke()调用方法)。
那么如何打开class呢?其实就是获得class文件的对象。

第六部分:
获取class文件对象的三种方式

package reflect;
//1.对象方法getClass()获取  (getClass()定义在Object类)
//2.使用类的静态属性class获取
//3.Class类静态方法 forName()获取
//三个方法中第三个最常用,这个方法的扩展性最好,因为参数是字符串,字符串未必提前写好,数据源可以外来,通过IO读取
public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException{
        //1.对象方法getClass()获取
        Student stu = new Student();
        Class c1 = stu.getClass();
        System.out.println(c1);

        //2.使用类的静态属性class获取
        //每一个数据类型,无论是基本还是引用类型,JVM赋予这个类型一个静态属性,名字就是class
        Class c2 = Student.class;
        System.out.println(c2);
        System.out.println(c1==c2);

        //3.Class类静态方法 forName()获取
        //注意:字符串形式的类名,必须是全限定名 包名.类名
        Class c3 = Class.forName("reflect.Student");
        System.out.println(c3);
    }
}

第七部分:

package reflect;

public class Student {
    private String name;
    private int age;
    
    // static{
    //     System.out.println("静态代码块");
    // }
    
    public Student(){

    }

    public Student(String name, int age){
        this.name = name;
        this.age = age;
    }

    public void study(){
        System.out.println("学生在学习");
    }

    public void eat(String s,double d){
        System.out.println("带参数方法:" + s + "::" + d);
    }

    public String toString(){
        return "Student{" + "name='" + name + '\'' + ",age=" + age + '}';
    }
}
package reflect;

import java.lang.reflect.Constructor;

/**
 * 反射技术:
 * 1. 获取一个类class文件对象,获取到Class类的对象
 * 2. Class类的对象中的方法,获取出类的成员(构造,变量,方法)
 * 3. 运行获取出来的成员
 *
 * 反射案例一:
 *   反射解剖,Student类,获取无参构造方法
 *   运行无参数构造(对象创建)
 */
public class ReflectDemo2 {
    public static void main(String[] args) throws Exception{
        Class c = Class.forName("reflect.Student");
        //获取Student类中的构造方法Class类的方法
        //方法 getConstructors() 获取到类中所有公共权限的构造方法
        //返回的是Constructor[]数组
        // Constructor[] cons = c.getConstructors();
        // for(Constructor con : cons){
        //     System.out.println(con);
        // }

        //只获取无参构造方法
        Constructor con = c.getConstructor();
        System.out.println(con);
        //运行构造方法,创建对象,Constructor方法 Object  newInstance(Object ...a) 传递实际参数
        Object object = con.newInstance();
        System.out.println(object);//打印对象时候,会自动调用类里面的toString方法

        //以上代码的作用就相当于我new Student,但是这样就把代码写死了,采用这样方式,我只需要更换字符串,就可以建立出新的其他类的对象
    }

}

第八部分:

package reflect;

import java.lang.reflect.Constructor;

/**
 *反射案例2:
 *  运行有参数构造(对象创建)
 */
public class ReflectDemo3 {
    public static void main(String[] args) throws Exception{
        Class c = Class.forName("reflect.Student");
        //class方法,获取有参数的构造,String int
        //传递构造方法参数列表中,数据类型的class文件对象 getConstructor(Class...p)
        Constructor con = c.getConstructor(String.class,int.class);
        System.out.println(con);
        //运行构造方法,创建对象,Constructor方法 newInstance(传递构造方法实际参数 Object o)
        Object object = con.newInstance("张三",20);
        System.out.println(object);
    }
}

第九部分:

package reflect;

/**
 * 反射案例3:
 *  反射获取Student类的无参构造方法执行
 *  使用简单的方法,减少代码量
 *
 *  前提:
 *      被反射的类,必须具备public权限的无参构造
 */
public class ReflectDemo4 {
    public static void main(String[] args) throws Exception{
        Class c = Class.forName("reflect.Student");
        //Class类中,定义方法 Object newInstance() 运行无参数构造,创建对象
        Object object = c.newInstance();
        System.out.println(object);
    }
}

第十部分:

package reflect;

import java.lang.reflect.Constructor;

/**
 * 暴力反射:打破类的封装性
 * 反射私有执行(不推荐使用)
 *
 * Constructor构造方法对象
 * Field 成员变量对象
 * Method 成员方法对象
 *
 * 共同继承父类 AccessibleObject
 * 父类中定义方法 srtAccessible(true)  取消java的运行时期的安全检查
 */
public class ReflectDemo5 {
    public static void main(String[] args) throws Exception{
        Class c = Class.forName("reflect.Student");
        //Class类的方法,获取Student类中的私有构造方法
        //方法名字:getDeclaredConstructor()
        Constructor con = c.getDeclaredConstructor(String.class);
        con.setAccessible(true);

        Object o = con.newInstance("张三");
        System.out.println(o);
    }
}

第十一部分:

package reflect;

import java.lang.reflect.Method;

/**
 * 获取无参成员方法
 * Method[] getMethods() 获取所有public修饰的成员方法,包括父类中
 * Method getMethod("方法名",方法的参数类型...类型)
 *      根据方法名和参数类型获得一个方法对象,只能获取public修饰的
 *
 * Method中常用方法
 * Object invoke(Object obj,Object...args)
 *  返回值Object 表示调用方法后,该方法的返回值
 *  根据参数args调用对象obj的该成员方法
 *  如果obj=null,则表示该方法为静态方法
 */
public class ReflectDemo6 {
    public static void main(String[] args) throws Exception{
        Class c = Class.forName("reflect.Student");
        Object object = c.newInstance();
        //获取study方法
        Method method = c.getMethod("study");
        //执行方法,传递对象
        method.invoke(object);
		//获得指定方法,eat
		Method method1 = c.getMethod("eat",String.class,double.class);
		//运行方法eat
		method.invoke(object,"字符串"9.8);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值