Java 框架技术基础---反射

Class 类的使用

在 Java 面向对象的世界里,万事万物皆对象!

  • 但是注意 Java 语言中,静态成员、普通数据类型都不是对象(封装类弥补了普通数据类型的不足)
  • 我们所编写的每一个类都是对象,类是 java.lang.Class 类的实例对象。 There is a class named Class 即这里有一个名称为 Class 的类,我们所写的每一个对象所属的类都是它的实例

Class 类的实例对象如何获取?

有以下代码中的三种方式:

package com.fy.reflect;

public class Test01 {

    public static void main(String[] args) throws ClassNotFoundException {
        // 类  A 的实例对象如何表示
        A a = new A();
        /* 类 A 也是 Class 类一个实例对象,因为任何一个类都是  Class 类的实例对象,
         * 官网称之为类类型,有如下三种表示方法
        */
        // 第一种表示方法:任何一个类都有一个隐藏的静态成员方法去获取 Class 实例
        Class c1 = A.class;
        // 第二种表示方法:利用某一个类的对象的  getClass()方法
        Class c2 = a.getClass();
        // Class 动态加载一个类
        Class c3 = Class.forName("com.fy.reflect.A");
        
        // 一个类只可能是 Class 类的一个实例对象,所以下面的输出都为 true
        System.out.println(c1 == c2); //输出  true
        System.out.println(c1 == c3); //输出  true
    }
}
class A{
    
}

如何理解动态加载类?

Class.forName("类的全称")

  • 不仅表示了类的类类型,还代表了动态加载类
  • 一定区分编译和运行

如何理解编译时刻加载类是静态加载类,运行时刻加载类是动态加载类

举个例子,我们 Java 开发者一般选择的 IDE 工具都是 Eclipse 或者 MyEclipse,比如以下代码,我创建了 Eclipse,没创建 MyEclipse 类,书写代码时就会出现错误(即编译出错),导致程序无法运行。也就是即使有了 Eclipse,没有 MyElicpse 也不能开发。但我们实际开发中,只有一个 IDE 工具给我们就能进行开发,不管有没有另外一个。再联想下,某个项目中有几十个功能,若是某个功能有问题其他功能就不能使用么?显然不合理。

public class JavaIDE {

    public static void main(String[] args) {
        //new 是静态加载类,在编译时都会加载所用到的类
        Eclipse e = new Eclipse();
        e.coding();
        MyEclipse m = new MyEclipse();
        m.coding();
    }
}
class Eclipse {
    public static void coding() {
        System.out.println("This is Eclipse");
    }
}

因此我们想到,用到某个功能就去加载某个类,即动态加载类。
为了更好的演示效果,希望大家在这里用文本编辑器编写代码,在 cmd 中利用 javac 命令编译、 java 命令运行代码

public class JavaIDE {

    public static void main(String[] args) throws Exception {
        // 动态加载,在运行时加载类
        Class c = Class.forName(args[0]);
        // 通过类类型,创建该对象
        IdeAble ia = (IdeAble)c.newInstance();
        ia.coding();
    }
}

在这里,我们通过类类型创建对象时,传统理念是

Eclipse e = (Eclipse)c.newInstance();

但是当我们需要的工具是 MyEclipse 时,这样则不满足功能要求。因此选择一个标准接口,所有功能类都去实现它,创建对象时只需创建接口对象就行。

这样需要什么功能,就去加载某个功能类就行。

interface IdeAble{
    public void coding();
}
class Eclipse implements IdeAble{
    public void coding() {
        System.out.println("This is Eclipse");
    }
}
class MyEclipse implements IdeAble{
    public void coding() {
        System.out.println("This is MyEclipse");
    }
}

再在cmd下,编译 JavaIDE 和 Eclipse,在运行。

当我们需要使用 Eclipse 功能时再去编写相应的代码,只要满足 IdeAble 接口标准就行,再运行即可


方法的反射

    //获取类的所有方法
    public static void getMethods(Object obj) {
        Class c = obj.getClass();
        // 获取类所有的方法,包括从父类继承而来的
        Method[] methods = c.getMethods();
        for (Method method : methods) {
            // 获取方法的返回类类型
            Class returnType = method.getReturnType();
            System.out.print(returnType.getName() + " ");
            // 获取方法的名称
            System.out.print(method.getName() + "(");
            // 获取参数类型,得到的是参数列表的类型的类类型
            Class[] paramTypes = method.getParameterTypes();
            int i = 0;
            for (Class class1 : paramTypes) {
                if (i == paramTypes.length - 1) {
                    System.out.print(class1.getName());
                } else {
                    System.out.print(class1.getName() + ",");
                }
                i++;
            }
            System.out.println(")");
        }
      }

成员变量的反射

//获取类的所有成员属性
    public static void getField(Object obj) {
        Class c = obj.getClass();
        Field[] fields = c.getFields();
        for (Field field : fields) {
            System.out.println(field.getName());
        }
    }

构造函数的反射

//获取类的所有构造方法
    public static void getConstructor(Object obj) {
        Class c = obj.getClass();
        Constructor[] constructors= c.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.print(constructor.getName()+" (");
            Class[] conParams= constructor.getParameterTypes();
            int i=0;
            for (Class class1 : conParams) {
                if (i == conParams.length-1) {
                    System.out.print(class1.getName());
                    
                }else{
                    System.out.print(class1.getName()+",");
                }
                i++;
            }
            System.out.println(")");
        }
    }

Java类加载机制

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容