Java——反射机制(重点)(一)

简介: Java——反射机制(重点)(一)

文章目录


Java反射机制

反射的概述

查看Class类在Java中的API详解

反射的使用(这里使用Student类做演示)

1、获取class对象的三种方式

2、通过反射获取构造方法并使用

3、获取成员变量并调用

4、获取成员方法并调用

5、反射main方法

6、反射方法的其它使用之---通过反射运行配置文件内容

7、反射方法的其它使用之---通过反射越过泛型检查


Java反射机制


反射的概述


反射:框架设计的灵魂


(使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码))


框架:半成品软件。可以在框架的基础上进行软件开发,简化编码


反射:将类的各个组成部分封装为其他对象,这就是反射机制


Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。


要想解剖一个类,必须先要获取到该类的字节码文件对象,而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象。


以上的总结就是什么是反射


反射就是把java类中的各种成分映射成一个个的Java对象


例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。

(其实:一个类中这些成员方法、构造方法、在加入类中都有一个类来描述) 如图是类的正常加载过程:反射的原理在与class对象。 熟悉一下加载的时候:Class对象的由来是将class文件读入内存,并为之创建一个Class对象。


20190920234324723.png


查看Class类在Java中的API详解


如何阅读java中的api详见java基础之——String字符串处理


20190920234453753.png


Class 类的实例表示正在运行的 Java 应用程序中的类和接口。也就是jvm中有N多的实例每个类都有该Class对象。(包括基本数据类型)


Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass 方法自动构造的。也就是这不需要我们自己去处理创建,JVM已经帮我们创建好了。


20190920234625524.png


反射的使用(这里使用Student类做演示)


1.先写一个Student类


2.获取Class对象的三种方式如下:

1.1 Object ——> getClass();

1.2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性

1.3 通过Class类的静态方法:forName(String className)(常用)


其中1.1是因为Object类中的getClass方法、因为所有类都继承Object类。从而调用Object类来获取


20190920234831758.png


package fanshe;
/**
 * 获取Class对象的三种方式
 * 1 Object ——> getClass();
 * 2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
 * 3 通过Class类的静态方法:forName(String  className)(常用)
 *
 */
public class Fanshe {
  public static void main(String[] args) {
  //第一种方式获取Class对象  
  Student stu1 = new Student();//这一new 产生一个Student对象,一个Class对象。
  Class stuClass = stu1.getClass();//获取Class对象
  System.out.println(stuClass.getName());
  //第二种方式获取Class对象
  Class stuClass2 = Student.class;
  System.out.println(stuClass == stuClass2);//判断第一种方式获取的Class对象和第二种方式获取的是否是同一个
  //第三种方式获取Class对象
  try {
    Class stuClass3 = Class.forName("fanshe.Student");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
    System.out.println(stuClass3 == stuClass2);//判断三种方式是否获取的是同一个Class对象
  } catch (ClassNotFoundException e) {
    e.printStackTrace();
  } 
  }
}


注意:在运行期间,一个类,只有一个Class对象产生。


三种方式常用第三种,第一种对象都有了还要反射干什么。第二种需要导入类的包,依赖太强,不导包就抛编译错误。一般都第三种,一个字符串可以传入也可写在配置文件中等多种方法。


1、获取class对象的三种方式


1.Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象

// 多用于配置文件,将类名定义在配置文件中。读取文件,加载类


2.类名.class :通过类名的属性class获取

// 多用于参数的传递

3.对象.getClass() :getClass()方法在Object类中定义

// 多用于对象的获取字节码的方式


结论:

同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。


2、通过反射获取构造方法并使用


student类:

package fanshe;
public class Student {
  //---------------构造方法-------------------
  //(默认的构造方法)
  Student(String str){
  System.out.println("(默认)的构造方法 s = " + str);
  }
  //无参构造方法
  public Student(){
  System.out.println("调用了公有、无参构造方法执行了。。。");
  }
  //有一个参数的构造方法
  public Student(char name){
  System.out.println("姓名:" + name);
  }
  //有多个参数的构造方法
  public Student(String name ,int age){
  System.out.println("姓名:"+name+"年龄:"+ age);//这的执行效率有问题,以后解决。
  }
  //受保护的构造方法
  protected Student(boolean n){
  System.out.println("受保护的构造方法 n = " + n);
  }
  //私有构造方法
  private Student(int age){
  System.out.println("私有的构造方法   年龄:"+ age);
  }
}


共有6个构造方法


测试类:

package fanshe;
import java.lang.reflect.Constructor;
/*
 * 通过Class对象可以获取某个类中的:构造方法、成员变量、成员方法;并访问成员;
 * 
 * 1.获取构造方法:
 *    1).批量的方法:
 *    public Constructor[] getConstructors():所有"公有的"构造方法
            public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
 *    2).获取单个的方法,并调用:
 *    public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:
 *    public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;
 *    
 *    调用构造方法:
 *    Constructor-->newInstance(Object... initargs)
 */
public class Constructors {
  public static void main(String[] args) throws Exception {
  //1.加载Class对象
  Class clazz = Class.forName("fanshe.Student");
  //2.获取所有公有构造方法
  System.out.println("**********************所有公有构造方法*********************************");
  Constructor[] conArray = clazz.getConstructors();
  for(Constructor c : conArray){
    System.out.println(c);
  }
  System.out.println("************所有的构造方法(包括:私有、受保护、默认、公有)***************");
  conArray = clazz.getDeclaredConstructors();
  for(Constructor c : conArray){
    System.out.println(c);
  }
  System.out.println("*****************获取公有、无参的构造方法*******************************");
  Constructor con = clazz.getConstructor(null);
  //1>、因为是无参的构造方法所以类型是一个null,不写也可以:这里需要的是一个参数的类型,切记是类型
  //2>、返回的是描述这个无参构造函数的类对象。
  System.out.println("con = " + con);
  //调用构造方法
  Object obj = con.newInstance();
  //  System.out.println("obj = " + obj);
  //  Student stu = (Student)obj;
  System.out.println("******************获取私有构造方法,并调用*******************************");
  con = clazz.getDeclaredConstructor(char.class);
  System.out.println(con);
  //调用构造方法
  con.setAccessible(true);//暴力访问(忽略掉访问修饰符)
  obj = con.newInstance('男');
  }
}


后台输出:

**********************所有公有构造方法*********************************
public fanshe.Student(java.lang.String,int)
public fanshe.Student(char)
public fanshe.Student()
************所有的构造方法(包括:私有、受保护、默认、公有)***************
private fanshe.Student(int)
protected fanshe.Student(boolean)
public fanshe.Student(java.lang.String,int)
public fanshe.Student(char)
public fanshe.Student()
fanshe.Student(java.lang.String)
*****************获取公有、无参的构造方法*******************************
con = public fanshe.Student()
调用了公有、无参构造方法执行了。。。
******************获取私有构造方法,并调用*******************************
public fanshe.Student(char)
姓名:男


调用方法:


    获取构造方法:


批量的方法:

public Constructor[] getConstructors():所有"公有的"构造方法

public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)


获取单个的方法,并调用:

public Constructor getConstructor(Class… parameterTypes):获取单个的"公有的"构造方法:

public Constructor getDeclaredConstructor(Class… parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;


调用构造方法:

Constructor–>newInstance(Object… initargs)


newInstance是 Constructor类的方法(管理构造函数的类)


API的解释为

newInstance(Object… initargs)


使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。


它的返回值是T类型,所以newInstance是创建了一个构造方法的声明类的新实例对象。并为之调用


目录
相关文章
|
3月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
140 2
|
3月前
|
Java 编译器
探索Java中的异常处理机制
【10月更文挑战第35天】在Java的世界中,异常是程序运行过程中不可避免的一部分。本文将通过通俗易懂的语言和生动的比喻,带你了解Java中的异常处理机制,包括异常的类型、如何捕获和处理异常,以及如何在代码中有效地利用异常处理来提升程序的健壮性。让我们一起走进Java的异常世界,学习如何优雅地面对和解决问题吧!
|
2月前
|
Java 数据库连接 Spring
反射-----浅解析(Java)
在java中,我们可以通过反射机制,知道任何一个类的成员变量(成员属性)和成员方法,也可以堆任何一个对象,调用这个对象的任何属性和方法,更进一步我们还可以修改部分信息和。
|
2月前
|
Java 开发者
Java中的异常处理机制深度剖析####
本文深入探讨了Java语言中异常处理的重要性、核心机制及其在实际编程中的应用策略,旨在帮助开发者更有效地编写健壮的代码。通过实例分析,揭示了try-catch-finally结构的最佳实践,以及如何利用自定义异常提升程序的可读性和维护性。此外,还简要介绍了Java 7引入的多异常捕获特性,为读者提供了一个全面而实用的异常处理指南。 ####
105 20
|
2月前
|
Java 程序员
深入理解Java异常处理机制
Java的异常处理是编程中的一块基石,它不仅保障了代码的健壮性,还提升了程序的可读性和可维护性。本文将深入浅出地探讨Java异常处理的核心概念、分类、处理策略以及最佳实践,旨在帮助读者建立正确的异常处理观念,提升编程效率和质量。
154 1
|
2月前
|
Java 开发者 UED
深入探索Java中的异常处理机制##
本文将带你深入了解Java语言中的异常处理机制,包括异常的分类、异常的捕获与处理、自定义异常的创建以及最佳实践。通过具体实例和代码演示,帮助你更好地理解和运用Java中的异常处理,提高程序的健壮性和可维护性。 ##
79 2
|
2月前
|
Java 数据库连接 开发者
Java中的异常处理机制:深入解析与最佳实践####
本文旨在为Java开发者提供一份关于异常处理机制的全面指南,从基础概念到高级技巧,涵盖try-catch结构、自定义异常、异常链分析以及最佳实践策略。不同于传统的摘要概述,本文将以一个实际项目案例为线索,逐步揭示如何高效地管理运行时错误,提升代码的健壮性和可维护性。通过对比常见误区与优化方案,读者将获得编写更加健壮Java应用程序的实用知识。 --- ####
|
3月前
|
运维 Java 编译器
Java 异常处理:机制、策略与最佳实践
Java异常处理是确保程序稳定运行的关键。本文介绍Java异常处理的机制,包括异常类层次结构、try-catch-finally语句的使用,并探讨常见策略及最佳实践,帮助开发者有效管理错误和异常情况。
189 6
|
2月前
|
开发框架 安全 Java
Java 反射机制:动态编程的强大利器
Java反射机制允许程序在运行时检查类、接口、字段和方法的信息,并能操作对象。它提供了一种动态编程的方式,使得代码更加灵活,能够适应未知的或变化的需求,是开发框架和库的重要工具。
91 4
|
2月前
|
Java 程序员 UED
深入理解Java中的异常处理机制
本文旨在揭示Java异常处理的奥秘,从基础概念到高级应用,逐步引导读者掌握如何优雅地管理程序中的错误。我们将探讨异常类型、捕获流程,以及如何在代码中有效利用try-catch语句。通过实例分析,我们将展示异常处理在提升代码质量方面的关键作用。
63 3

热门文章

最新文章