栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

反射机制篇

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

反射机制篇

反射机制
  • 一. 反射机制
    • 2.1 反射快速入门
    • 2.2 反射机制
    • 2.3 反射和传统的方法时间对比
      • 2.3.1 时间复杂度对比
      • 2.3.1 反射代码优化
  • 二. class类
    • 2.1 `Class`类的基本介绍
      • 2.1.1 Class类图
      • 2.1.1 Class类加载方法
      • 2.1.3 对于某个类的`Class`类对象,在中只有一份,因此类只加载一次
      • 2.1.4 每个类的实例都会记得自己是由哪个`Class`实例所生成
      • 2.1.5 通过`Class`可以完整地得到一个类的完整结构,通过一系列`API`
      • 2.1.6 Class对象是存放在堆中的
      • 2.1.7 类的字节码二进制数据,放在方法区的,有的地方称为类的元数据
    • 2.2 获取Class类对象
    • 2.3 哪些类型有Class对象
  • 三. 类加载
  • 四. 反射获取类的结构信息
  • 五. 反射相关类
  • 六. class类常用方法

一. 反射机制
2.1 反射快速入门
  • (1). 根据配置文件调用源代码的信息,在不更改源代码,只需要更改配置文件,就可以实现功能的实现。
  • (2). 这样的需求在学习框架时特别多(开闭原则:不修改源代码,扩容功能)

各文件层次结构

re.properties配置文件:

classfullpath=com.hspedu.Cat
method=hi

Cat类猫:

package com.hspedu;

public class Cat {
    private String name = "招财猫";
    private String cry = "喵喵喵";
    public void hi(){
        //常用方法
        System.out.println("hi" + name);
    }
    
    public void cry(){
        System.out.println("cry" + cry);
    }
    
}

Java源代码:

package com.hspedu.reflection.question;

import com.hspedu.Cat;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

public class ReflectionQuetion {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {

    //根据配置文件re.properties指定信息,创建Cat对象并调用方法hi
    //1.使用传统方法  使用new创造对象
        Cat cat = new Cat();
        cat.hi();
     @SuppressWarnings({"all"})
    //2.使用配置文件读取配置信息
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\re.properties"));

        String classfullpathName = properties.get("classfullpath").toString();
        String methodName = properties.get("method").toString();
        System.out.println("classfullpath=" + classfullpathName);
        System.out.println("method=" + methodName);
        
    //这里的classfulpath 还有 method 读取的仅仅是配置文件的字符串信息,而非真正的类。
    //目前的策略,没有合适的可以解决这样的问题。只能通过:配置信息 + 反射机制 解决这样的问题。     
        
    //3.利用反射机制创建对象
        // (1).加载类,返回class类型的对象clc
        Class clc = Class.forName(classfulpathName);	//注意了,这里没有双引号,直接采用的名字
        
        // (2).通过clc类创建类的对象实例
        Object o = clc.newInstance();
        System.out.println("o的运行类=" + o.getClass());
        
        // (3).通过clc得到方法对象 
        Method method = clc.getMethod(methodName);
        method.invoke(o);

    }

}

仿真结果:

"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=52611:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection.question.ReflectionQuetion
hi招财猫
classfullpath=com.hspedu.Cat
method=hi
o的运行类=class com.hspedu.Cat
=====================
hi招财猫

Process finished with exit code 0

修改 re.properties 配置文件,而其他的不要动:

classfullpath=com.hspedu.Cat
method=cry

修改 re.properties 配置文件后的仿真结果:

"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=53025:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection.question.ReflectionQuetion
hi招财猫
classfullpath=com.hspedu.Cat
method=cry
o的运行类=class com.hspedu.Cat
=====================
cry喵喵喵

Process finished with exit code 0



2.2 反射机制
    1. 反射机制允许程序在执行期间借助于Reflection API取得任何类的内部信息(比如:成员变量,构造器,成员方法等等),并能操作对象的属性及方法。反射再设计模式和框架底层都会用到。
    1. 加载完类之后,在堆之中就会产生一个Class类型的对象,这个对象包含了类的完整的结构信息。通过这个镜子得到类的结构,所以,形象的称之为:反射
    1. 优点:可以动态的创建和使用对象。没有反射技术,框架技术就失去了底层支撑。
    1. 缺点:使用反射基本是解释执行,对执行速度有影响。

  • java.lang.Class: 代表一个类,Class对象表示某个类加载后再堆中的对象
  • java.lang.reflect.Method: 代表类的方法,Method对象表示某个类的方法
  • java.lang.reflect.Field: 代表类的成员变量,Field对象表示某个类的成员变量
  • java.lang.reflect.Constructor: 代表类的构造方法,Constructor对象表示构造器
    这些类在java.lang.reflec

java.lang.reflect.Field的使用:

 

        System.out.println("=========  getField  ================");
        //得到name字段:
        Field nameField = clc.getField("age");  //getFiled不能得到私有的属性
        System.out.println(nameField.get(o));   //传统写法 对象.成员变量

java.lang.reflect.Constructor的使用:

// Cat 修改版本

package com.hspedu;

public class Cat {
    private String name = "招财猫";
    private String cry = "喵喵喵";
    public int age = 10;
	//增加 Cat 的构造器函数
    public Cat(String name){
        this.name = name;
    }
    //Cat没有了默认的无参构造函数,得重新建立一个无参数的构造函数
    public Cat(){

    }

    public void hi(){
        //常用方法
        System.out.println("hi" + name);
    }

    public void cry(){
        System.out.println("cry" + cry);
    }

}
//具体代码:

        System.out.println("=========  java.lang.reflect.Constructor  ================");
        //java.lang.reflect.Constructor: 代表类的构造方法,Constructor对象表示构造器
        Constructor constructor = clc.getConstructor(); //()中可以指定构造器的参数类型,返回无参构造器
        System.out.println(constructor);

        Constructor constructor1 = clc.getConstructor(String.class);    //这里传入的String.class就是String类的class对象
        System.out.println(constructor1);       //输出带形式参数String的构造器
//仿真结果:

=========  java.lang.reflect.Constructor  ================
public com.hspedu.Cat()
public com.hspedu.Cat(java.lang.String)


2.3 反射和传统的方法时间对比
2.3.1 时间复杂度对比

时间对比源代码:

package com.hspedu.reflection0;

import com.hspedu.Cat;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;



public class Reflection02 {
    public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
        m1();
        m2();
    }

    //传统方法来调用hi
    public static void m1(){
        Cat cat = new Cat();
        long start = System.currentTimeMillis();
        for(int i=0; i<90000000; i++){
            cat.hi();
        }
        long end = System.currentTimeMillis();
        System.out.println("传统 m1 方法来调用 hi 耗时=" + (end - start));
    }


    //反射机制调用方法
    public static void m2() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        Class clc = Class.forName("com.hspedu.Cat");
        Object o = clc.newInstance();
        Method hi = clc.getMethod("hi");
        long start = System.currentTimeMillis();
        for(int i=0; i<90000000; i++){
            hi.invoke(o);
        }
        long end = System.currentTimeMillis();
        System.out.println("反射机制的 m2 方法来调用 hi 耗时=" + (end - start));
    }


}

仿真结果:

"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=53251:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection0.Reflection02
传统 m1 方法来调用 hi 耗时=10
反射机制的 m2 方法来调用 hi 耗时=537

Process finished with exit code 0


2.3.1 反射代码优化

反射部分的代码调用优化:

  • Method和Field、Constructor对象都有setAccessible()方法
  • setAccessible()作用是启动和禁用访问安全检查的开关
  • 参数值为true表示反射的对象在使用时取消访问检查,提高反射效率。参数值为false表示反射的对象在使用时开启访问检查
package com.hspedu.reflection0;

import com.hspedu.Cat;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;



public class Reflection02 {
    public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {

        m1();
        m2();
        m3();
    }

    //传统方法来调用hi
    public static void m1(){
        Cat cat = new Cat();
        long start = System.currentTimeMillis();
        for(int i=0; i<90000000; i++){
            cat.hi();
        }
        long end = System.currentTimeMillis();
        System.out.println("传统 m1 方法来调用 hi 耗时=" + (end - start));
    }


    //反射机制调用方法
    public static void m2() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        Class clc = Class.forName("com.hspedu.Cat");
        Object o = clc.newInstance();
        Method hi = clc.getMethod("hi");
        long start = System.currentTimeMillis();
        for(int i=0; i<90000000; i++){
            hi.invoke(o);
        }
        long end = System.currentTimeMillis();
        System.out.println("反射机制的 m2 方法来调用 hi 耗时=" + (end - start));
    }



    //反射机制调用方法 + 性能优化
    public static void m3() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        Class clc = Class.forName("com.hspedu.Cat");
        Object o = clc.newInstance();
        Method hi = clc.getMethod("hi");

        hi.setAccessible(true); //在反射方法调用时,取消访问检查

        long start = System.currentTimeMillis();
        for(int i=0; i<90000000; i++){
            hi.invoke(o);
        }
        long end = System.currentTimeMillis();
        System.out.println("反射机制的 m3 方法来调用 hi 耗时=" + (end - start));
    }



}

"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=53289:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection0.Reflection02
传统 m1 方法来调用 hi 耗时=10
反射机制的 m2 方法来调用 hi 耗时=648
反射机制的 m3 方法来调用 hi 耗时=329

Process finished with exit code 0


二. class类
2.1 Class类的基本介绍
  • 1.Class也是类,因此也继承了Object类
  • 2.Class类对象不是new出来的,而是系统创建出来的
  • 3.对于某个类的Class类对象,在呢村中只有一份,因此类只加载一次
  • 4.每个类的实例都会记得自己是由哪个Class实例所生成
  • 5.通过Class可以完整地得到一个类的完整结构,通过一系列API
  • 6.Class对象是存放在堆的
  • 7.类的字节码二进制数据,是放在方法区的,有的地方称之为类的元数据

2.1.1 Class类图


2.1.1 Class类加载方法
  • 通过ClassLoader 里面的loadClass()生成的Class对象

传统的方法:

反射的方法:


2.1.3 对于某个类的Class类对象,在中只有一份,因此类只加载一次

同一个类通过Class类产生对象

package com.hspedu.reflection0.class_;

import com.hspedu.Cat;

public class Class01 {

    public static void main(String[] args) throws ClassNotFoundException {
        //2. Class类对象不是new出来的,而是系统创建出来的
        //(1).传统的new对象

        //(2).反射方式
        Class clc1 = Class.forName("com.hspedu.Cat");
        Class clc2 = Class.forName("com.hspedu.Cat");
        System.out.println(clc1.hashCode());
        System.out.println(clc2.hashCode());
        

    }

}

"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=53688:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection0.class_.Class01
356573597
356573597
//这里表明,产生的是同一个对象
Process finished with exit code 0


不同的类通过Class类产生对象

package com.hspedu.reflection0.class_;

import com.hspedu.Cat;

public class Class01 {

    public static void main(String[] args) throws ClassNotFoundException {
        //2. Class类对象不是new出来的,而是系统创建出来的
        //(1).传统的new对象

        //(2).反射方式
        Class clc1 = Class.forName("com.hspedu.Cat");
        Class clc2 = Class.forName("com.hspedu.Cat");
        System.out.println(clc1.hashCode());
        System.out.println(clc2.hashCode());


        Class clc3 = Class.forName("com.hspedu.Dog");
        System.out.println(clc3.hashCode());


    }

}

"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=53697:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection0.class_.Class01
356573597
356573597
1735600054
//这里表明了,产生了不同的对象
Process finished with exit code 0

Class方法和传统方法一起做对比,可看出采用Class的方法的特点

package com.hspedu.reflection0.class_;

import com.hspedu.Cat;

public class Class01 {

    public static void main(String[] args) throws ClassNotFoundException {
        //2. Class类对象不是new出来的,而是系统创建出来的
        //(1).传统的new对象

        //(2).反射方式
        Class clc1 = Class.forName("com.hspedu.Cat");
        Class clc2 = Class.forName("com.hspedu.Cat");
        System.out.println("Class方法产生的Cat对象clc1:" + clc1.hashCode());
        System.out.println("Class方法产生的Cat对象clc2:" + clc2.hashCode());


        Class clc3 = Class.forName("com.hspedu.Dog");
        System.out.println("Class方法产生的Dog对象clc3:" + clc3.hashCode());

        Cat cat1 = new Cat();
        Cat cat2 = new Cat();
        System.out.println("传统方法对象cat1:" + cat1.hashCode());
        System.out.println("传统方法对象cat2:" + cat2.hashCode());



    }

}

"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=53728:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection0.class_.Class01
Class方法产生的Cat对象clc1:356573597
Class方法产生的Cat对象clc2:356573597
Class方法产生的Dog对象clc3:1735600054
传统方法对象cat1:21685669
传统方法对象cat2:2133927002

Process finished with exit code 0


2.1.4 每个类的实例都会记得自己是由哪个Class实例所生成

2.1.5 通过Class可以完整地得到一个类的完整结构,通过一系列API


2.1.6 Class对象是存放在堆中的

2.1.7 类的字节码二进制数据,放在方法区的,有的地方称为类的元数据

Class类应用实例:


实例1 —> 输出clc:

package com.hspedu.reflection0.class_;




public class Class02{
    public static void main(String[] args) throws ClassNotFoundException {
        String classAllPAth = "com.hspedu.Car";

        //获取读到的CAr类,对应的Class对象
        //表示不确定的Java类型
        Class clc = Class.forName(classAllPAth);

        //输出clc
        System.out.println(clc);            //如果输出clc对象,是哪个类的Class对象,com.hspedu.Car
        System.out.println(clc.getClass()); //输出clc运行时类型:java.lang.Class

    }

}


"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=53840:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection0.class_.Class02
class com.hspedu.Car
class java.lang.Class

Process finished with exit code 0


实例2 —> 得到包名:

package com.hspedu.reflection0.class_;




public class Class02{
    public static void main(String[] args) throws ClassNotFoundException {
        String classAllPAth = "com.hspedu.Car";

        //获取读到的CAr类,对应的Class对象
        //表示不确定的Java类型
        Class clc = Class.forName(classAllPAth);

        //得到包名
        System.out.println(clc.getPackage().getName());

    }
}

"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=53855:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection0.class_.Class02
com.hspedu

Process finished with exit code 0



实例3 —> 其他方法:

//为了显示更加方便,将Car类进行一定的更改
package com.hspedu;

public class Car {
    public String brand = "宝马";	//这里如果是私有属性,利用反射机制来获取对象属性会报错的,后面再看私有属性的获取
    public int price = 500000;
    public String color = "白色";

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + ''' +
                ", price=" + price +
                ", color='" + color + ''' +
                '}';
    }
}

package com.hspedu.reflection0.class_;

import com.hspedu.Car;

import java.lang.reflect.Field;




public class Class02{
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        String classAllPAth = "com.hspedu.Car";

        //获取读到的CAr类,对应的Class对象
        //表示不确定的Java类型
        Class clc = Class.forName(classAllPAth);

        //1. 得到包名
        System.out.println("得到包名" + clc.getPackage().getName());

        //2. 得到全类名
        System.out.println("得到全类名" + clc.getName());

        //3. 通过clc创建对象实例
        Car car = (Car) clc.newInstance();
        System.out.println(car);

        //4. 通过反射获取对象属性 brand
        Field brand = clc.getField("brand");
        System.out.println(brand.get(car)); //宝马

        //5. 通过反射给属性赋值
        brand.set(car,"奔驰"); //方法.对象。和传统的Java是反着的。
        System.out.println(brand.get(car)); //奔驰

        //6. 获取所有属性
        System.out.println("==========");
        Field[] fields = clc.getFields();
        for(Field f:fields){
            System.out.println(f.get(car));
        }


    }
}

"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=53886:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection0.class_.Class02
得到包名com.hspedu
得到全类名com.hspedu.Car
Car{brand='宝马', price=500000, color='白色'}
宝马
奔驰
==========
奔驰
500000
白色

Process finished with exit code 0


2.2 获取Class类对象
  • 编译阶段:Class.forName()
  • 类加载阶段:类.class
  • 运行阶段:对象.getClass()

package com.hspedu.reflection0.class_;

import com.hspedu.Car;


public class GetClass_ {
    

    public static void main(String[] args) throws ClassNotFoundException {
        //1. Class.forName
        String classALLPath = "com.hspedu.Car"; //通过读取配置文件获取到的
        Class clc = Class.forName(classALLPath);
        System.out.println(clc);

        //2. 类.class。应用场景:参数传递
        Class clc1 = Car.class;
        System.out.println(clc1);

        //3. 通过: 对象.getClass(),应用场景,有对象实例
        Car car = new Car();
        Class clc2 = car.getClass();
        System.out.println(clc2);

        //4. 通过类加载器得到Class对象,一共有4种类加载器
        //(1).先得到类加载器car
        ClassLoader classLoader = car.getClass().getClassLoader();
        //(2).通过类加载器得到Class对象
        Class clc3 = classLoader.loadClass(classALLPath);
        System.out.println(clc3);


        //clc clc1 clc2 clc3其实是同一个对象
        System.out.println("======clc clc1 clc2 clc3的hashcode()======");
        System.out.println(clc.hashCode());
        System.out.println(clc1.hashCode());
        System.out.println(clc2.hashCode());
        System.out.println(clc3.hashCode());

        //基本数据类型
        System.out.println("======基本数据类型:======");
        Class integerClass = int.class;
        Class characterClass = char.class;
        Class booleanClass = boolean.class;
        System.out.println(integerClass);       //int
        System.out.println(characterClass);


        //基本数据类型对应的包装类
        System.out.println("======基本数据类型对应的包装类:======");
        Class type1 = Integer.TYPE;
        Class type2 = Character.TYPE;
        System.out.println(type1);
        System.out.println(type2);
        System.out.println("type1的hashcode:" + type1.hashCode());
        System.out.println("包装类hashcode:" + integerClass.hashCode());



    }


}

"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=53967:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection0.class_.GetClass_
class com.hspedu.Car
class com.hspedu.Car
class com.hspedu.Car
class com.hspedu.Car
======clc clc1 clc2 clc3的hashcode()======
356573597
356573597
356573597
356573597
======基本数据类型:======
int
char
======基本数据类型对应的包装类:======
int
char
type1的hashcode:1735600054
包装类hashcode:1735600054

Process finished with exit code 0


2.3 哪些类型有Class对象
    1. 外部类,成员内部类,静态内部类,局部内部类,匿名内部类
    1. interface接口
    1. 数组
    1. enum:枚举
    1. annotation:注解
    1. 基本数据类型
    1. void
package com.hspedu.reflection0.class_;

import java.io.Serializable;

public class ALLTypeClas {
    public static void main(String[] args) {

        //外部类
        Class cls1 = String.class;
        //接口
        Class cls2 = Serializable.class;
        //数组
        Class cls3 = Integer[].class;
        //二维数组
        Class cls4 = float[][].class;
        //注解
        Class cls5 = Deprecated.class;
        //枚举
        Class cls6 = Thread.State.class;
        //long基本数据类型
        Class cls7 = long.class;
        //void
        Class cls8 = void.class;
        //Class
        Class cls9 = Class.class;

        System.out.println(cls1);
        System.out.println(cls2);
        System.out.println(cls3);
        System.out.println(cls4);
        System.out.println(cls5);
        System.out.println(cls6);
        System.out.println(cls7);
        System.out.println(cls8);
        System.out.println(cls9);


    }

}

"C:Program FilesJavajdk1.8.0_152binjava.exe" "-javaagent:D:软件下载ideaideaIntelliJ IDEA 2021.1libidea_rt.jar=54011:D:软件下载ideaideaIntelliJ IDEA 2021.1bin" -Dfile.encoding=UTF-8 -classpath "C:Program FilesJavajdk1.8.0_152jrelibcharsets.jar;C:Program FilesJavajdk1.8.0_152jrelibdeploy.jar;C:Program FilesJavajdk1.8.0_152jrelibextaccess-bridge-64.jar;C:Program FilesJavajdk1.8.0_152jrelibextcldrdata.jar;C:Program FilesJavajdk1.8.0_152jrelibextdnsns.jar;C:Program FilesJavajdk1.8.0_152jrelibextjaccess.jar;C:Program FilesJavajdk1.8.0_152jrelibextjfxrt.jar;C:Program FilesJavajdk1.8.0_152jrelibextlocaledata.jar;C:Program FilesJavajdk1.8.0_152jrelibextnashorn.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunec.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunjce_provider.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunmscapi.jar;C:Program FilesJavajdk1.8.0_152jrelibextsunpkcs11.jar;C:Program FilesJavajdk1.8.0_152jrelibextzipfs.jar;C:Program FilesJavajdk1.8.0_152jrelibjavaws.jar;C:Program FilesJavajdk1.8.0_152jrelibjce.jar;C:Program FilesJavajdk1.8.0_152jrelibjfr.jar;C:Program FilesJavajdk1.8.0_152jrelibjfxswt.jar;C:Program FilesJavajdk1.8.0_152jrelibjsse.jar;C:Program FilesJavajdk1.8.0_152jrelibmanagement-agent.jar;C:Program FilesJavajdk1.8.0_152jrelibplugin.jar;C:Program FilesJavajdk1.8.0_152jrelibresources.jar;C:Program FilesJavajdk1.8.0_152jrelibrt.jar;E:刘建成javaprojectProoutproductionPro" com.hspedu.reflection0.class_.ALLTypeClas
class java.lang.String
interface java.io.Serializable
class [Ljava.lang.Integer;
class [[F
interface java.lang.Deprecated
class java.lang.Thread$State
long
void
class java.lang.Class

Process finished with exit code 0


三. 类加载
  • 反射机制是java实现动态语言的关键,也就是通过反射实现类动态加载。

    • 静态加载:编译时加载相关的类,如果没有则报错,依赖性太强

    • 动态加载:运行时加载需要的类,如果运行时不用该类,即使不存在该类,则不报错,降低了依赖性

静态加载和动态加载对比的代码:

package com.hspedu.reflection0.class_;

import com.hspedu.Dog;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner;

public class ClassLoad_ {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        Scanner scanner = new Scanner(System.in);

        System.out.println("请输入key");

        String key = scanner.next();

        switch(key){
            case "1":
                Dog dog = new Dog();
                dog.cry();
                dog.laugh();    //Dog里面没有这个类。编译时,如果有问题,则会报错,
                break;
            case "2": //文件夹中没有Person这个类,编译时没有报错。在运行时,如果用到Person类,发现没有才会报错。
                Class cls = Class.forName("Person");    //运行时,就算没有Person,只要不用他,是不会报错的。
                Object o = cls.newInstance();
                Method m = cls.getMethod("hi");
                m.invoke(o);
                System.out.println("ok~");
                break;
            default:
                System.out.println("do nothing~");


        }




    }

}


类加载流程图:



  • 类加载的各个阶段
    • JVM在该阶段的主要目的是将字节码从不同的数据源(可能是class文件、也可能是jar包,甚至网络)转换为二进制字节流加载到内存中,并生成一个代表该类的java.lang.Class对象
  • 连接阶段
    • 验证:
      • 1.目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,姑且不会危害虚拟机自身的安全。
      • 2.包括:文件格式验证(是否以魔数oxcafebabe开头)、元数据验证,字节码验证和符号引用验证
      • 3.可以考虑使用 -Xverify:none 参数来关闭大部分的类验证措施,缩短虚拟机类加载的时间。
    • 准备:
    • 解析

四. 反射获取类的结构信息

参考链接


五. 反射相关类

参考链接


六. class类常用方法

参考链接

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1039537.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号