【Java核心基础知识】09 - Java反射

多线程知识点目录

多线程并发(1)- https://www.jianshu.com/p/8fcfcac74033
多线程并发(2)-https://www.jianshu.com/p/a0c5095ad103
多线程并发(3)-https://www.jianshu.com/p/c5c3bbd42c35
多线程并发(4)-https://www.jianshu.com/p/e45807a9853e
多线程并发(5)-https://www.jianshu.com/p/5217588d82ba
多线程并发(6)-https://www.jianshu.com/p/d7c888a9c03c

一、动态语言

动态语言,是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化。比如常见的JavaScript就是动态语言,除此之外RybyPython等也属于动态语言,而C、C++则不属于动态语言。从反射角度说Java属于半动态语言。

二、反射机制概念

Java反射机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。

三、反射的应用场合

3.1 编译时类型和运行时类型

在Java程序中许多对象在运行时会出现两种类型:编译时类型运行时类型

编译时类型(Compile-time Type)通常是你声明变量时所使用的类型。这个类型在编译时期确定,并且会用于编译期的检查,比如类型检查和转换。

运行时类型(Runtime Type)是对象实际的生命周期中的具体类型。这个类型在运行时确定,并且可以动态地改变。

例如:

Person p = new Student

在这里,p的编译时类型是Person,这是你在声明变量时指定的类型。然而,p的运行时类型实际上是Student,因为p实际上指向的是一个Student类型的对象。

3.2 编译时类型无法获取具体方法

编译时类型无法获取具体方法的原因是Java的类型擦除机制。在Java中,泛型类型的信息是在编译期确定的,但这些信息在运行时会被擦除,以便支持Java的动态类型安全和性能优化。

因此,尽管你可以在编译时获取变量的类型信息,但是在运行时,Java虚拟机(JVM)会忽略这些类型信息,而只关注对象的实际运行时类型。这意味着在运行时,你无法通过编译时类型来获取具体方法,因为编译时类型的信息在运行时被擦除了。

如果你想在运行时获取具体方法的信息,你可以使用Java的反射API。反射API允许你在运行时检查类、接口、字段和方法的信息,甚至可以调用对象的方法。通过反射API,你可以动态地获取对象的运行时类型信息,并据此进行相应的操作

四、Java反射API

Java反射API是一组在Java编程语言中用于在运行时检查和操作类、接口、字段和方法的功能强大的API。通过反射API,你可以在运行时获取类的信息,创建对象,调用方法,获取和设置字段值等

以下是一些常用的反射API:

  1. Class类:反射的核心类,代表一个类或接口,提供了一系列方法用于获取类的信息,如名称、注解、成员变量和方法等。
  2. Field类:代表一个字段,提供了一系列方法用于获取字段的类型、名称、访问修饰符等信息,并可以获取和设置字段的值。
  3. Method类:代表一个方法,提供了一系列方法用于获取方法的参数、返回值、访问修饰符等信息,并可以调用该方法。
  4. Constructor类:代表一个构造方法,提供了一系列方法用于创建对象实例。

五、反射使用步骤

  1. 获取想要操作的Class对象,这是反射的核心,可以通过Class对象任意调用类的方法。

  2. 调用Class类的方法是反射的使用阶段。

  3. 使用反射API来操作这些信息。

    import java.lang.reflect.Method;  
      
    public class ReflectionExample {  
        public static void main(String[] args) {  
            try {  
                // 获取String类的Class对象  
                Class<?> stringClass = String.class;  
      
                // 获取一个构造方法  
                Constructor<?> stringConstructor = stringClass.getConstructor(String.class);  
      
                // 创建新的String对象  
                Object stringObject = stringConstructor.newInstance("Hello World");  
      
                // 获取并调用String类的length()方法  
                Method lengthMethod = stringClass.getMethod("length");  
                int length = (Integer) lengthMethod.invoke(stringObject);  
                System.out.println("Length: " + length);  
      
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
    }
    

六、获取Class对象的3种方法

6.1 调用某个对象的getClass方法

Person p = new Persion();
Class clazz = p.getClass();

6.2 调用某个类的class属性来获取该类对应的Class对象

Class clazz = p.class;

6.3 使用class类中的forName()静态方法(最安全、性能最好)

Class clazz = Class.forName("com.example.MyClass");

注意:使用forName()方法时,需要确保类的完全限定名是正确的,否则会抛出ClassNotFoundException异常。


6.4 通过Class对象获取类中方法和属性

// 获取Person类的Class对象
Class clazz = Class.forName("com.example.Person");
// 获取Person类的所有方法信息
Method[] methodArr = clazz.getDeclaredMethods();
for(Method m : methodArr){
    System.out.println(m.toString());
}
// 获取Person类的所有成员属性
Field[] fieldArr = clazz.getDeclaredFields();
for(Field f : fieldArr){
    System.out.println(f.toString());
}
// 获取Person类的所有构造方法信息
Constructor[] constructorArr = clazz.getDeclaredConstructors();
for(Constructor c : constructorArr){
    System.out.println(c.toString());
}

七、创建对象的两种方法

7.1 Class对象的newInstance()

使用Class对象的newInstance()方法来创建该Class对象对应类的实例,但是,这种方法要求该Class对象对应的类由默认的空构造器。

Class clazz = Class.forName("com.example.Person");
Person p = (Person) clazz.newInstance();

7.2 调用Constructor对象的newInstance()

先试用Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建Class对象对应类的实例,通过这种方法可以选定构造方法创建实例。

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