iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java中反射的学习笔记分享
  • 379
分享到

Java中反射的学习笔记分享

Java 反射 2022-11-13 19:11:34 379人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

目录简介一个简单的例子设置使用反射模拟instanceof运算了解类的方法获取有关构造函数的信息查找类字段按名称调用方法创建新对象更改字段的值使用数组总结简介 反射是Java编程语言

简介

反射是Java编程语言中的一个特性。它允许执行的Java程序检查或 操作 自身,并操作程序的内部属性。例如,Java类可以获取其所有成员的名称并显示它们。

从程序内部检查和操作Java类的能力听起来可能不太显示,但是在其他编程语言中,这个特性根本不存在。例如,在C或C ++ 程序中无法获取有关该程序中定义的函数的信息。

反射的一个具体用途是在JavaBeans中,软件组件可以通过一个构建工具进行可视化操作。该工具使用反射来获取Java组件 (类) 动态加载时的属性。

一个简单的例子

要了解反射是如何工作的,请考虑以下简单示例:

import java.lang.reflect.*;

 
   public class DumpMethods {
      public static void main(String args[])
      {
         try {
            Class c = Class.forName(args[0]);
            Method m[] = c.getDeclaredMethods();
            for (int i = 0; i < m.length; i++)
            System.out.println(m[i].toString());
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }

对于以下项的调用:

java DumpMethods java.util.Stack

输出为:

public java.lang.Object java.util.Stack.push(

    java.lang.Object)
   public synchronized 
     java.lang.Object java.util.Stack.pop()
   public synchronized
      java.lang.Object java.util.Stack.peek()
   public boolean java.util.Stack.empty()
   public synchronized 
     int java.util.Stack.search(java.lang.Object)

也就是说,类的方法名称java.util.Stack列出了它们及其完全限定的参数和返回类型。

此程序使用加载指定的类 class.forName, 然后调用 getDeclaredMethods 方法检索类中定义的方法列表. java.lang.reflect.Method是表示单个类方法的类。

设置使用反射

反射类,例如Method,在java.lang.反射中找到。使用这些类必须遵循三个步骤。第一步是获得一个java.lang.Class要操作的类的对象。java.lang.Class用于表示正在运行的Java程序中的类和接口。

获取类对象的一种方法是:

Class c = Class.forName("java.lang.String");

上述代码获取的类对象 String.

另一种方法是使用:

Class c = int.class;

或者

Class c = Integer.TYPE;

获取基本类型的类信息。后一种方法访问预定义TYPE 包装类型 (例如Integer) 为基本类型。

第二步是调用方法,例如getDeclaredMethods,以获取该类声明的所有方法的列表。

一旦掌握了这些信息,那么第三步就是使用反射api来操作这些信息。例如:

Class c = Class.forName("java.lang.String"); 
Method m[] = c.getDeclaredMethods(); 
System.out.println(m[0].toString());

在下面的示例中,将三个步骤结合在一起,以呈现如何使用反射处理特定应用的独立插图。

模拟instanceof运算

一旦掌握了类信息,下一步通常是询问有关类对象的基本问题。

例如,Class.isInstance方法可以用来模拟instanceof 运算:

class A {}

   public class instance1 {
      public static void main(String args[])
      {
         try {
            Class cls = Class.forName("A");
            boolean b1 
              = cls.isInstance(new Integer(37));
            System.out.println(b1);
            boolean b2 = cls.isInstance(new A());
            System.out.println(b2);
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }

在此示例中,类对象A被创建,然后我们检查类实例对象,以查看它们是否是AInteger(37)不是,但是new A()是。

了解类的方法

反射最有价值和最基本的用途之一是找出类中定义了哪些方法。为此,可以使用以下代码:

import java.lang.reflect.*;

   public class method1 {
      private int f1(
       Object p, int x) throws NullPointerException
      {
         if (p == null)
            throw new NullPointerException();
         return x;
      }
        
      public static void main(String args[])
      {
         try {
           Class cls = Class.forName("method1");
        
            Method methlist[] 
              = cls.getDeclaredMethods();
            for (int i = 0; i < methlist.length;
               i++) {  
               Method m = methlist[i];
               System.out.println("name 
                 = " + m.getName());
               System.out.println("decl class = " +
                              m.getDeclarinGClass());
               Class pvec[] = m.getParameterTypes();
               for (int j = 0; j < pvec.length; j++)
                  System.out.println("
                   param #" + j + " " + pvec[j]);
               Class evec[] = m.getExceptionTypes();
               for (int j = 0; j < evec.length; j++)
                  System.out.println("exc #" + j 
                    + " " + evec[j]);
               System.out.println("return type = " +
                                  m.getReturnType());
               System.out.println("-----");
            }
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }

程序首先获取method1的类描述,然后调用getDeclaredMethods(一个用于获取类中定义的每个方法的函数)检索Method 对象列表。这些方法包括public、protect、package和priva。如果你在程序中使用getMethods 而不是getDeclaredMethods,还可以获取继承方法的信息。

程序的输出为:

name = f1
   decl class = class method1
   param #0 class java.lang.Object
   param #1 int
   exc #0 class java.lang.NullPointerException
   return type = int
   -----
   name = main
   decl class = class method1
   param #0 class [Ljava.lang.String;
   return type = void
   -----

获取有关构造函数的信息

使用类似的方法来找出类的构造函数。例如:

import java.lang.reflect.*;
        
   public class constructor1 {
      public constructor1()
      {
      }
        
      protected constructor1(int i, double d)
      {
      }
        
      public static void main(String args[])
      {
         try {
           Class cls = Class.forName("constructor1");
        
           Constructor ctorlist[]
               = cls.getDeclaredConstructors();
         for (int i = 0; i < ctorlist.length; i++) {
               Constructor ct = ctorlist[i];
               System.out.println("name 
                 = " + ct.getName());
               System.out.println("decl class = " +
                            ct.getDeclaringClass());
               Class pvec[] = ct.getParameterTypes();
               for (int j = 0; j < pvec.length; j++)
                  System.out.println("param #" 
                     + j + " " + pvec[j]);
               Class evec[] = ct.getExceptionTypes();
               for (int j = 0; j < evec.length; j++)
                  System.out.println(
                    "exc #" + j + " " + evec[j]);
               System.out.println("-----");
            }
          }
          catch (Throwable e) {
             System.err.println(e);
          }
      }
   }

在此示例中没有检索到返回类型信息,因为构造函数实际上没有真正的返回类型。

运行此程序时,输出为:

name = constructor1
   decl class = class constructor1
   -----
   name = constructor1
   decl class = class constructor1
   param #0 int
   param #1 double
   -----

查找类字段

还可以找出类中定义了哪些数据字段。为此,可以使用以下代码:

import java.lang.reflect.*;
        
   public class field1 {
      private double d;
      public static final int i = 37;
      String s = "testing";
        
      public static void main(String args[])
      {
         try {
            Class cls = Class.forName("field1");
        
            Field fieldlist[] 
              = cls.getDeclaredFields();
            for (int i 
              = 0; i < fieldlist.length; i++) {
               Field fld = fieldlist[i];
               System.out.println("name
                  = " + fld.getName());
               System.out.println("decl class = " +
                           fld.getDeclaringClass());
               System.out.println("type
                  = " + fld.getType());
               int mod = fld.getModifiers();
               System.out.println("modifiers = " +
                          Modifier.toString(mod));
               System.out.println("-----");
            }
          }
          catch (Throwable e) {
             System.err.println(e);
          }
       }
   }

此示例与前面的示例相似。一个新功能是使用Modifier。这是一个反射类,表示在字段成员上找到的修饰符,例如private int。修饰符本身由整数表示,并且Modifier.toString用于返回默认声明顺序中的字符串表示形式 (例如final之前的static)。程序的输出为:

name = d
   decl class = class field1
   type = double
   modifiers = private
   -----
   name = i
   decl class = class field1
   type = int
   modifiers = public static final
   -----
   name = s
   decl class = class field1
   type = class java.lang.String
   modifiers =
   -----

与方法一样,可以仅获取有关类中声明的字段的信息 (getDeclaredFields),或获取有关超类中定义的字段的信息 (getFields)。

按名称调用方法

到目前为止,已经提出的例子都与获取class有关。但是也可以以其他方式使用反射,例如调用指定名称的方法。

要了解其工作原理,请考虑以下示例:

import java.lang.reflect.*;
        
   public class method2 {
      public int add(int a, int b)
      {
         return a + b;
      }
        
      public static void main(String args[])
      {
         try {
           Class cls = Class.forName("method2");
           Class partypes[] = new Class[2];
            partypes[0] = Integer.TYPE;
            partypes[1] = Integer.TYPE;
            Method meth = cls.getMethod(
              "add", partypes);
            method2 methobj = new method2();
            Object arglist[] = new Object[2];
            arglist[0] = new Integer(37);
            arglist[1] = new Integer(47);
            Object retobj 
              = meth.invoke(methobj, arglist);
            Integer retval = (Integer)retobj;
            System.out.println(retval.intValue());
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }

假设一个程序想要调用add方法,但直到执行时才知道。也就是说,在执行期间指定方法的名称 (例如,这可以由JavaBeans开发环境完成)。上面的程序展示了一种方法。

getMethod用于在类中查找具有两个integer参数类型并具有适当名称的方法。一旦找到此方法并将其捕获到Method 对象,它是在适当类型的对象实例上调用的。要调用方法,必须构造一个参数列表,基本整数值为37和47Integer 对象。返回值 (84) 也被包含在Integer 对象。

创建新对象

构造函数不等同于方法调用,因为调用构造函数等同于创建新对象 (最准确地说,创建新对象涉及内存分配和对象构造)。所以最接近前面例子的是:

import java.lang.reflect.*;
        
   public class constructor2 {
      public constructor2()
      {
      }
        
      public constructor2(int a, int b)
      {
         System.out.println(
           "a = " + a + " b = " + b);
      }
        
      public static void main(String args[])
      {
         try {
           Class cls = Class.forName("constructor2");
           Class partypes[] = new Class[2];
            partypes[0] = Integer.TYPE;
            partypes[1] = Integer.TYPE;
            Constructor ct 
              = cls.getConstructor(partypes);
            Object arglist[] = new Object[2];
            arglist[0] = new Integer(37);
            arglist[1] = new Integer(47);
            Object retobj = ct.newInstance(arglist);
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }

它查找处理指定参数类型并调用它的构造函数,以创建对象的新实例。这种方法的价值在于它纯粹是动态的,在执行时而不是在编译时使用构造函数查找和调用。

更改字段的值

反射的另一个用途是改变对象中数据字段的值。它的值再次从反射的动态性质中导出,其中可以在执行程序中按名称查找字段,然后更改其值。以下示例说明了这一点:

import java.lang.reflect.*;
        
   public class field2 {
      public double d;
        
      public static void main(String args[])
      {
         try {
            Class cls = Class.forName("field2");
            Field fld = cls.getField("d");
            field2 f2obj = new field2();
            System.out.println("d = " + f2obj.d);
            fld.setDouble(f2obj, 12.34);
            System.out.println("d = " + f2obj.d);
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }

在此示例中,d字段的值设置为12.34。

使用数组

反射的一个用途是创建和操作数组。Java语言中的数组是类的一种特殊类型,并且可以将数组引用分配给Object

要查看数组的工作方式,请考虑以下示例:

import java.lang.reflect.*;
        
   public class array1 {
      public static void main(String args[])
      {
         try {
            Class cls = Class.forName(
              "java.lang.String");
            Object arr = Array.newInstance(cls, 10);
            Array.set(arr, 5, "this is a test");
            String s = (String)Array.get(arr, 5);
            System.out.println(s);
         }
         catch (Throwable e) {
            System.err.println(e);
         }
      }
   }

此示例创建一个10长的字符串数组,然后将数组中的位置5设置为字符串值。将检索并显示该值。

以下代码说明了对数组的更复杂的操作:

import java.lang.reflect.*;
        
   public class array2 {
      public static void main(String args[])
      {
         int dims[] = new int[]{5, 10, 15};
         Object arr 
           = Array.newInstance(Integer.TYPE, dims);
        
         Object arrobj = Array.get(arr, 3);
         Class cls = 
           arrobj.getClass().getComponentType();
         System.out.println(cls);
         arrobj = Array.get(arrobj, 5);
         Array.setInt(arrobj, 10, 37);
        
         int arrcast[][][] = (int[][][])arr;
         System.out.println(arrcast[3][5][10]);
      }
   }

此示例创建一个5x10x15的int数组,然后继续将数组中的位置 [3][5][10] 设置为值37。请注意,多维数组实际上是数组数组,因此,例如,在第一个array.get之后,arrobj中的结果是10x15数组。再次将其剥离以获得15长的数组,并使用Array.setInt

请注意,创建的数组类型是动态的,不必在编译时知道。

总结

Java反射非常有用,因为它支持按名称动态检索有关类和数据结构的信息,并允许在执行的Java程序中进行操作。此功能非常强大,但是也要谨慎使用

以上就是Java中反射的学习笔记分享的详细内容,更多关于Java反射的资料请关注编程网其它相关文章!

--结束END--

本文标题: Java中反射的学习笔记分享

本文链接: https://www.lsjlt.com/news/170911.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java中反射的学习笔记分享
    目录简介一个简单的例子设置使用反射模拟instanceof运算了解类的方法获取有关构造函数的信息查找类字段按名称调用方法创建新对象更改字段的值使用数组总结简介 反射是Java编程语言...
    99+
    2022-11-13
    Java 反射
  • Java Unsafe学习笔记分享
    目录sun.misc.Unsafe获取Unsafe实例重点API使用场景避免初始化内存崩溃(Memory corruption)抛出异常(Throw an Exception)大数组...
    99+
    2024-04-02
  • Java分布式教程:学习笔记分享!
    Java分布式是一个非常重要的知识点,它可以让我们在多台服务器上部署应用程序,从而提高应用程序的可伸缩性和可靠性。本文将分享一些Java分布式的学习笔记,包括分布式原理、分布式架构、分布式锁、分布式缓存、分布式事务等方面的内容。同时,我们...
    99+
    2023-08-31
    教程 学习笔记 分布式
  • Java 打包对象:学习笔记分享
    Java 是一门面向对象的编程语言,它的面向对象特性使得 Java 开发者可以轻松地组织代码和数据。但是,在编写代码的过程中,我们经常需要将一组相关的对象打包在一起进行处理。这就是 Java 打包对象的重要作用。本文将会分享 Java 打...
    99+
    2023-10-03
    打包 对象 学习笔记
  • 打包 Java 对象:学习笔记分享
    Java 是一种常用的编程语言,开发者们常常需要将自己编写的 Java 对象打包成可执行的 JAR 文件。本文将分享一些打包 Java 对象的经验和技巧,以便于读者能够更加轻松地完成这项任务。 一、什么是 JAR 文件 JAR 文件是 J...
    99+
    2023-10-04
    打包 对象 学习笔记
  • python入门学习笔记分享
    一、python的基础语法 1.行连接的方法是最后加上一个‘\' 2.注释:多行注释三引号,#行注释;三引号定义的字符串原样输出(保存原格式) 3.I/O语句:用逗号分隔零个或多个表...
    99+
    2024-04-02
  • 如何在 Windows 上学习 Java 编程?分享我的学习笔记!
    在当今数字化时代,计算机编程已经成为一项越来越重要的技能。而 Java 编程语言则是其中最受欢迎和广泛使用的一种语言。在 Windows 系统上学习 Java 编程,无疑是一条高效而且实用的学习路径。在本篇文章中,我将分享我的学习笔记,希望...
    99+
    2023-10-09
    windows 学习笔记 日志
  • ASP API教程:学习笔记分享!
    ASP API是一种常用的Web开发技术,它可以通过API(应用程序接口)来访问和操作数据,从而实现Web应用程序的开发。如果您正在学习ASP API,本文将为您提供一些有用的笔记和代码示例,帮助您更好地理解和应用这项技术。 了解ASP...
    99+
    2023-11-06
    api 教程 学习笔记
  • 学习PHP Path文件:笔记分享!
    PHP是一门流行的服务器端脚本语言,能够与HTML一起使用,可以创建动态页面和交互式网站。在PHP中,Path文件是一种重要的概念,它可以让你在PHP中访问和操作文件系统中的文件和目录。在本篇文章中,我们将深入研究PHP Path文件,分...
    99+
    2023-07-05
    path 文件 学习笔记
  • 从接口到大数据:Java学习笔记分享
    Java是目前最流行的编程语言之一,它被广泛应用于Web开发、移动应用开发、企业应用开发等领域。本文将分享我在学习Java过程中的一些笔记和心得,内容涵盖从接口到大数据的知识点。 一、接口 接口是Java中的一种特殊的类,它只包含抽象方法和...
    99+
    2023-10-17
    大数据 接口 学习笔记
  • Go编程算法:学习笔记分享
    Go语言是一门现代化的编程语言,它的出现给开发者带来了更多的选择和机会。在Go语言中,算法是一个非常重要的部分。本篇文章将会分享一些关于Go编程算法的学习笔记,帮助读者更好地掌握这门语言。 一、排序算法 排序算法是编程中常见的算法之一,它...
    99+
    2023-06-20
    编程算法 学习笔记 自然语言处理
  • Python 日志如何记录?学习笔记分享!
    Python是一种流行的编程语言,广泛应用于各种领域。当我们在编写Python代码时,我们需要记录应用程序中发生的事件和错误信息。这就是Python日志的作用。Python日志可以帮助我们快速定位应用程序中的问题,以便更快地解决它们。在这篇...
    99+
    2023-08-07
    关键字 日志 学习笔记
  • PHP学习笔记:打包和分享你的笔记,从HTTP中获取更多的学习资源!
    PHP是一种广泛使用的服务器端脚本语言,用于创建动态网页和Web应用程序。如果你正在学习PHP,你可能已经积累了大量的学习笔记,包括代码片段、参考文档和教程等等。在本文中,我们将讨论如何打包和分享你的PHP学习笔记,以及如何从HTTP中获...
    99+
    2023-11-15
    学习笔记 打包 http
  • Python Spring 中的对象是什么?学习笔记分享!
    Python Spring 是一个流行的 Python web 开发框架,它能帮助开发者快速地构建高效的 web 应用程序。在 Python Spring 中,对象是一个非常重要的概念,因为它们是应用程序中的主要构建块。在本篇文章中,我们...
    99+
    2023-08-31
    spring 学习笔记 对象
  • ASP中的关键字有哪些?学习笔记分享!
    ASP(Active Server Pages)是一种基于服务器端的脚本语言,它可以生成动态网页,而在ASP中有很多关键字是我们必须要掌握的。在本篇文章中,我们将会学习到ASP中的关键字有哪些,以及如何使用它们来实现一些功能。 一、变量类型...
    99+
    2023-08-05
    关键字 学习笔记 并发
  • OpenCV机器学习MeanShift算法笔记分享
    MeanShift算法 Mean shift 是一种机器学习算法,并不仅仅局限于图像上的应用。关于 Mean shift 算法介绍的书和文章很多,这里就不多介绍了。简单的说,Mean...
    99+
    2024-04-02
  • 打包攻略:Go Path 学习笔记分享!
    Go Path 是一个非常重要的概念,它是 Go 语言中的一个环境变量,用于指定 Go 语言的工作目录。在编写 Go 程序时,我们经常需要引用其他的包,而这些包可能是我们自己写的,也可能是其他人写的。因此,我们需要将这些包放在一个统一的目...
    99+
    2023-08-24
    path 教程 打包
  • ASP 响应是什么?学习笔记分享!
    ASP响应是什么?学习笔记分享! ASP(Active Server Pages)是一种基于服务器端的Web应用程序开发技术。在ASP中,响应(Response)是指Web服务器向客户端发送数据的过程。在本文中,我们将介绍ASP响应的基本概...
    99+
    2023-10-18
    响应 学习笔记 分布式
  • PHP学习笔记(观隅反三)
    前言 不知不觉距离上篇PHP的文章 PHP学习笔记(才贯二酉)已经过去好多天了,今天看到推送——1024程序员节,莫名还有些小激动(os:自知自己的一些雕虫小技肯定和程序员这个技术深似海的称号扯不上什...
    99+
    2023-09-01
    1024程序员节 php 开发语言
  • Laravel 中 PHP 响应的实用指南:学习笔记分享。
    Laravel 是一种流行的 PHP 框架,它提供了许多功能强大的工具和库来帮助开发者快速构建高质量的 Web 应用程序。在 Laravel 中,响应(Response)是一个非常重要的概念,它定义了应用程序如何向客户端发送数据。在本篇文章...
    99+
    2023-08-09
    响应 学习笔记 laravel
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作