Java反射机制

简介: Java反射机制

e1ce5f0fba50f9e6eaa266c988df2314.png

虚拟机在class文件的加载阶段,把类信息保存在方法区数据结构中,并在Java堆中生成一个Class对象,作为类信息的入口。


假如你写了一段代码:Object o=new Object();


运行了起来!


首先JVM会启动,你的代码会编译成一个.class文件,然后被类加载器加载进jvm的内存中,你的类Object加载到方法区中,创建了Object类的class对象到堆中,注意这个不是new出来的对象,而是类的类型对象,每个类只有一个class对象,作为方法区类的数据结构的接口。jvm创建对象前,会先检查类是否加载,寻找类对应的class对象,若加载好,则为你的对象分配内存,初始化也就是代码:new Object()。


反射之中包含了一个“反”的概念,所以要想解释反射就必须先从“正”开始解释:一般而言,当用户使用一个类的时候,应该先知道这个类,而后通过这个类产生实例化对象。


但是“反”指的是通过对象找到类。

package cn.design.factory;
public class ReflactTest {
    public static void main(String[] args) {
        BenzSport bs=new BenzSport();
        System.out.println(bs.getClass().getName());
    }
}

ea5e2a0f8b3b45d67d14cce58c83cd88.png

以上的代码使用了一个getClass()方法,而后就可以得到对象所在的“包.类”名称,这就属于“反”了,但是在这个“反”的操作之中有一个getClass()就作为发起一切反射操作的开端。


BenzSport的父类是Object类,而上面所使用getClass()方法就是Object类之中所定义的方法。


24476cdde5c3fde15932a9e31ea73ea5.png

取得Class对象:public final Class<?> getClass(),反射之中的所有泛型都定义为?,返回值都是Object。


而这个getClass()方法返回的对象是Class类的对象(在堆中的class类对象作为方法区数据接口的接口)所以这个Class就是所有反射操作的源头。


但是在讲解其真正使用之前还有一个需要先解释的问题,既然Class是所有反射操作的源头,那么这个类肯定是最为重要的, 而如果要想取得这个类的实例化对象,Java中定义了三种方式:

方式一:通过Object类的getClass()方法取得,基本不用:

package cn.design.factory;
public class ReflactTest {
    public static void main(String[] args) {
        BenzSport bs=new BenzSport();//通过类获取对象
        Class<?> c=bs.getClass();//通过对象获取类对象
        System.out.println(c);//反着来
    }
}

2239ff9d06d0f802ade72a43409fa310.png

方式二:使用“类.class”取得,在日后学习Hibernate开发的时候使用

package cn.design.factory;
public class ReflactTest {
    public static void main(String[] args) {
        BenzSport bs=new BenzSport();//通过类获取对象
        Class<?> c=BenzSport.class;//通过对象获取类对象
        System.out.println(c.getName());//反着来
    }
}

方式三:使用Class类内部定义的一个static方法,主要使用

public static Class<?> forName(String className) throws ClassNotFoundException

package cn.design.factory;
public class ReflactTest {
    public static void main(String[] args) throws Exception {
        BenzSport bs=new BenzSport();
        Class<?> c=Class.forName("cn.design.factory.BenzSport");
        System.out.println(c.getName());
    }
}

取得了Class类的对象有什么用处呢?对于对象的实例化操作之前一直依靠构造方法和关键字new完成,可是有了Class类对象之后,现在又提供了另外一种对象的实例化方法:

package cn.design.factory;
public class ReflactTest {
    public static void main(String[] args) throws Exception {
        BenzSport bs=new BenzSport();
        Class<?> c = Class.forName("cn.design.factory.BenzSport");//获取类对象(Object对象)
        Object o=c.newInstance();//实例化一个对象和new的作用一样
        BenzSport bbs=(BenzSport) o;//向下转型为你需要的类型
        System.out.println(bbs);
    }
}

反射的深入应用

以上只是利用了Class类作为了反射实例化对象的基本应用,但是对于一个实例化对象而言,它需要调用类之中的构造方法、普通方法、属性,而这些操作都可以通过反射机制完成。

一:调用构造方法

package cn.design.factory;
import java.lang.reflect.Constructor;
public class ReflactTest {
    public static void main(String[] args) throws Exception {
        BenzSport bs=new BenzSport();
        Class<?> c = Class.forName("cn.design.factory.BenzSport");//获取类对象(Object对象)
        Constructor<?> con[]=c.getConstructors();//获取全部的构造方法
        for(int i=0;i<con.length;i++){
            System.out.println(con[i]);
        }
    }
}

cc2635a61527c28abd2b7d11486a71c5.png

如果被反射的类中没有无参构造方法的话会报错

package cn.design.factory;
import java.lang.reflect.Constructor;
public class ReflactTest {
    public static void main(String[] args) throws Exception {
        Class<?> c = Class.forName("cn.design.factory.BenzSport");//获取类对象(Object对象)
        Object o=c.newInstance();
    }
}

7225dbed542826de0e638eea36967514.png

package cn.design.factory;
import java.lang.reflect.Constructor;
public class ReflactTest {
    public static void main(String[] args) throws Exception {
        Class<?> c = Class.forName("cn.design.factory.BenzSport");//获取类对象(Object对象)
        Constructor<?> cons=c.getConstructor(String.class);
        Object o =cons.newInstance("C级别轿跑");
    }
}

d1dcdf78a3e4c6100eb5f723013e2b99.png

很明显,调用无参构造方法实例化对象要比调用有参构造的更加简单、方便,所以在日后的所有开发之中,凡是有简单Java类出现的地方,都一定要提供无参构造。

二:调用普通方法

package cn.design.factory;
import java.lang.reflect.Method;
public class ReflactTest {
    public static void main(String[] args) throws Exception {
        Class<?> c = Class.forName("cn.design.factory.BenzSport");//获取类对象(Object对象)
        Method meths[]=c.getMethods();//获取类中全部的方法包括自身类的方法及父类的方法
        for(int i=0;i<meths.length;i++){
            System.out.println(meths[i]);
        }
    }
}


ed12dc393a1b200576873e04789aa277.png

package cn.design.factory;
import java.lang.reflect.Method;
public class ReflactTest {
    public static void main(String[] args) throws Exception {
        Class<?> c = Class.forName("cn.design.factory.BenzSport");//获取类对象(Object对象)
        Object obj=c.newInstance();
        Method runMet=c.getMethod("run");//调用run方法
        runMet.invoke(obj);//调用无参方法run()
        String attr="Name";
        Method setMet=c.getMethod("set"+attr, String.class);//调用set(String)方法
        Method getMet=c.getMethod("get"+attr);//调用String get()方法
        setMet.invoke(obj, "梅赛德斯奔驰");
        System.out.println(getMet.invoke(obj));
    }
}

2375e7310e1b736dc608352c822e27bd.png

在日后的所有框架技术开发之中,简单Java类都是如此应用的,所以必须按照标准进行。

三:调用成员

package cn.design.factory;
import java.lang.reflect.Field;
public class ReflactTest {
    public static void main(String[] args) throws Exception {
        Class<?> c = Class.forName("cn.design.factory.BenzSport");//获取类对象(Object对象)
        Field field[]=c.getDeclaredFields();//获取全部属性
        for(int i=0;i<field.length;i++){
            System.out.println(field[i]);
        }
    }
}

29f09f1b73e3e86dccdb82e7674027ce.png

package cn.design.factory;
import java.lang.reflect.Field;
public class ReflactTest {
public static void main(String[] args) throws Exception {
Class<?> c = Class.forName("cn.design.factory.BenzSport");//获取类对象(Object对象)
Field field[]=c.getDeclaredFields();//获取全部属性
for(int i=0;i<field.length;i++){
System.out.println(field[i]);
}
Object obj=c.newInstance();// 对象实例化属性才会分配空间
Field nameField=c.getDeclaredField("name");
nameField.setAccessible(true);//解除封装
nameField.set(obj, "翎野君");//对象.name="翎野君"
System.out.println(nameField.get(obj));//对象.name
}
}

3ad63a1f43a9066e1a2212b1c51bb18e.png


目录
相关文章
|
16天前
|
监控 算法 Java
Java中的内存管理:理解Garbage Collection机制
本文将深入探讨Java编程语言中的内存管理,特别是垃圾回收(Garbage Collection, GC)机制。我们将从基础概念开始,逐步解析垃圾回收的工作原理、不同类型的垃圾回收器以及它们在实际项目中的应用。通过实际案例,读者将能更好地理解Java应用的性能调优技巧及最佳实践。
58 0
|
14天前
|
Java 程序员
深入理解Java异常处理机制
【9月更文挑战第20天】在Java编程世界中,异常处理是一项基础而重要的技能。本文将通过通俗易懂的语言和生动的比喻,带你走进Java异常的世界,了解它们的本质、分类以及如何优雅地处理这些不请自来的特殊“客人”。从简单的try-catch语句到复杂的异常链追踪,我们将一步步揭开异常处理的面纱,让你在遇到问题时不再手足无措。
42 21
|
3天前
|
Java 程序员 开发者
深入理解Java中的异常处理机制
【9月更文挑战第31天】在Java编程中,异常处理是维护程序健壮性的关键。本文将通过浅显易懂的语言和生动的例子,带你了解Java异常处理的基本概念、分类以及如何优雅地处理它们。从初学者到资深开发者,每个人都能从中获得新的洞见和技巧,让你的代码更加健壮和易于维护。
10 4
|
2天前
|
Java 编译器 开发者
Java中的异常处理机制:从基础到进阶
本文深入探讨Java编程语言中的异常处理机制,从基础知识出发,逐步解析异常的分类、捕获和处理方法。通过实际案例分析,展示如何在开发过程中有效利用异常处理提高代码的稳定性和可维护性。进一步探讨了自定义异常的创建和使用场景,以及在Java中进行异常处理的最佳实践。文章旨在为Java开发者提供一个全面而详细的异常处理指南,帮助开发者更好地理解和运用Java的异常处理机制。
|
6天前
|
Java 数据库连接
深入理解Java异常处理机制
【9月更文挑战第28天】在Java编程中,异常处理是确保程序健壮性的关键。本文通过浅显易懂的语言和生动的例子,带你一步步了解Java的异常处理机制。从try-catch-finally的基本用法,到自定义异常类,再到异常处理的最佳实践,我们将一起探索如何在代码中优雅地处理那些不期而遇的小插曲。
14 4
|
8天前
|
Java 程序员 数据库连接
Java中的异常处理机制:理解与实践
本文将深入探讨Java语言中异常处理的核心概念、重要性以及应用方法。通过详细解析Java异常体系结构,结合具体代码示例,本文旨在帮助读者更好地理解如何有效利用异常处理机制来提升程序的健壮性和可维护性。
|
9天前
|
Java 开发者 UED
深入理解Java中的异常处理机制
本文旨在通过通俗易懂的语言,详细解析Java异常处理的核心概念及应用。从异常的基本分类到具体处理方法,再到最佳实践和常见误区,一步步引领读者深入理解这一关键技术,提升编程质量和效率。
16 2
|
9天前
|
Java 程序员 数据库连接
深入理解Java中的异常处理机制
【9月更文挑战第25天】在Java的海洋中航行,不可避免地会遇到异常的风暴。本文将作为你的航海图,指引你穿越异常处理的迷雾,让你学会如何使用try-catch语句、finally块以及throw和throws关键字来驾驭这些风暴。我们将一起探索自定义异常的岛屿,并了解如何创建和使用它们。准备好了吗?让我们启航,确保你的代码不仅能够抵御异常的狂澜,还能优雅地处理它们。
|
9天前
|
Java 开发者
Java中的异常处理机制深度解析
在Java编程中,异常处理是保证程序稳定性和健壮性的重要手段。本文将深入探讨Java的异常处理机制,包括异常的分类、捕获与处理、自定义异常以及一些最佳实践。通过详细讲解和代码示例,帮助读者更好地理解和应用这一机制,提升代码质量。
12 1
|
14天前
|
Java 程序员 数据库连接
深入理解Java中的异常处理机制
【9月更文挑战第20天】在Java编程的世界中,异常处理是一块不可忽视的拼图。本文将带你深入探讨Java的异常处理机制,从异常的基础概念到高级应用,通过实际代码示例,揭示如何优雅地管理程序中的错误和异常情况。我们将一起学习如何使用try-catch语句捕获异常,了解finally块的重要性,以及何时使用throws关键字。此外,我们还会探索自定义异常类的创建和利用,以及最佳实践来优化你的异常处理策略。无论你是Java新手还是有经验的开发者,这篇文章都将为你提供有价值的见解和技巧,帮助你编写更加健壮和易于维护的代码。
25 7
下一篇
无影云桌面