加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

Java 反射机制浅析

发布时间:2020-12-13 21:19:34 所属栏目:PHP教程 来源:网络整理
导读:学习Java的同学注意了!!! 学习进程中遇到甚么问题或想获得学习资源的话,欢迎加入Java学习交换群,群号码: 183993990 我们1起学Java! Java反射机制是在运行状态中,对任意1个 类 ,都能够知道这个类的所有属性和方法;对任意1个 对象 ,都能够调用它的

学习Java的同学注意了!!! 
学习进程中遇到甚么问题或想获得学习资源的话,欢迎加入Java学习交换群,群号码:183993990  我们1起学Java!


      Java反射机制是在运行状态中,对任意1个,都能够知道这个类的所有属性和方法;对任意1个对象,都能够调用它的任意1个方法和属性;这类动态获得的信息和动态调用对象的方法的功能称为Java语言的反射机制。反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行动的1种能力。这1概念的提出很快引发了计算机科学领域关于利用反射性的研究。它首先被程序语言的设计领域所采取,并在Lisp和面向对象方面获得了成绩。固然反射本身其实不是1个新概念,它可能会使我们联想到光学中的反射概念,虽然计算机科学赋予了反射概念新的含义,但是,从现象上来讲,它们确切有某些相通的地方,这些有助于我们的理解。

      Java反射机制主要提供下面几种用处:

  • 在运行时判断任意1个对象所属的类
  • 在运行时构造任意1个类的对象
  • 在运行时判断任意1个类所具有的成员变量和方法
  • 在运行时调用任意1个对象的方法

      首先看1个简单的例子,通过这个例子来理解Java的反射机制是如何工作的。

复制代码

package com.wanggc.reflection;

import java.lang.reflect.Method;

/**
* Java 反射练习。
*
*
@author Wanggc
*/
public class ForNameTest {


* 入口函数。
*
*
@param args
* 参数
*
@throws Exception
* 毛病信息
*/
static void main(String[] args) throws Exception {
// 取得Class
Class<?> cls = Class.forName(args[0]);
通过Class取得所对应对象的方法
Method[] methods = cls.getMethods();
输出每一个方法名
for (Method method : methods) {
System.out.println(method);
}
}
}

复制代码

      当传入的参数是java.lang.String时,会输出以下结果

复制代码

boolean java.lang.String.equals(java.lang.Object)
public java.lang.String java.lang.String.toString()
int java.lang.String.hashCode()
int java.lang.String.compareTo(java.lang.String)
int java.lang.String.compareTo(java.lang.Object)
int java.lang.String.indexOf(int)
int,int java.lang.String.indexOf(java.lang.String)
int java.lang.String.indexOf(java.lang.String,255); line-height:1.5!important">static java.lang.String java.lang.String.valueOf(char)
boolean)
float)
char[],255); line-height:1.5!important">double)
char[])
static java.lang.String java.lang.String.valueOf(java.lang.Object)
long)
char java.lang.String.charAt(int java.lang.String.codePointAt(int java.lang.String.codePointBefore(int java.lang.String.codePointCount(int java.lang.String.compareToIgnoreCase(java.lang.String)
public java.lang.String java.lang.String.concat(java.lang.String)
boolean java.lang.String.contains(java.lang.CharSequence)
boolean java.lang.String.contentEquals(java.lang.CharSequence)
boolean java.lang.String.contentEquals(java.lang.StringBuffer)
static java.lang.String java.lang.String.copyValueOf(boolean java.lang.String.endsWith(java.lang.String)
boolean java.lang.String.equalsIgnoreCase(java.lang.String)
static java.lang.String java.lang.String.format(java.lang.String,java.lang.Object[])
static java.lang.String java.lang.String.format(java.util.Locale,java.lang.String,255); line-height:1.5!important">byte[] java.lang.String.getBytes(java.lang.String) throws java.io.UnsupportedEncodingException
void java.lang.String.getBytes(byte[],255); line-height:1.5!important">byte[] java.lang.String.getBytes()
byte[] java.lang.String.getBytes(java.nio.charset.Charset)
void java.lang.String.getChars(native java.lang.String java.lang.String.intern()
boolean java.lang.String.isEmpty()
int java.lang.String.lastIndexOf(java.lang.String)
int java.lang.String.lastIndexOf(int java.lang.String.lastIndexOf(java.lang.String,255); line-height:1.5!important">int java.lang.String.length()
boolean java.lang.String.matches(java.lang.String)
int java.lang.String.offsetByCodePoints(boolean java.lang.String.regionMatches(boolean,255); line-height:1.5!important">public java.lang.String java.lang.String.replace(java.lang.CharSequence,java.lang.CharSequence)
public java.lang.String java.lang.String.replace(char,255); line-height:1.5!important">public java.lang.String java.lang.String.replaceAll(java.lang.String,java.lang.String)
public java.lang.String java.lang.String.replaceFirst(java.lang.String,255); line-height:1.5!important">public java.lang.String[] java.lang.String.split(java.lang.String)
public java.lang.String[] java.lang.String.split(java.lang.String,255); line-height:1.5!important">boolean java.lang.String.startsWith(java.lang.String)
boolean java.lang.String.startsWith(java.lang.String,255); line-height:1.5!important">public java.lang.CharSequence java.lang.String.subSequence(public java.lang.String java.lang.String.substring(char[] java.lang.String.toCharArray()
public java.lang.String java.lang.String.toLowerCase()
public java.lang.String java.lang.String.toLowerCase(java.util.Locale)
public java.lang.String java.lang.String.toUpperCase()
public java.lang.String java.lang.String.toUpperCase(java.util.Locale)
public java.lang.String java.lang.String.trim()
final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
void java.lang.Object.wait() long,255); line-height:1.5!important">int) native java.lang.Class java.lang.Object.getClass()
void java.lang.Object.notify()
void java.lang.Object.notifyAll()

复制代码

      这样就列出了java.lang.String类的所有方法名、及其限制符、返回类型及抛出的异常。这个程序使用Class类forName方法载入指定的类,然后调用getMethods方法返回指定类的方法列表。java.lang.reflect.Method用来表述某个类中的单1方法。

      使用java的反射机制,1般需要遵守3步:

    1. 取得你想操作类的Class对象
    2. 通过第1步取得的Class对象去获得操作类的方法或是属性名
    3. 操作第2步获得的方法或是属性

     Java运行的时候,某个类不管生成多少个对象,他们都会对应同1个Class对象,它表示正在运行程序中的类和接口。如何获得操作类的Class对象,经常使用的有3种方式:

    1. 调用Class的静态方法forName,如上例;
    2. 使用类的.class语法,如:Class<?> cls = String.class;
    3. 调用对象的getClass方法,如:String str = "abc";Class<?> cls = str .getClass();

      下面将通过实例讲述如何通过前面所诉的3步来履行某对象的某个方法:

复制代码

 1 package com.wanggc.reflection;
2
3 import java.lang.reflect.Method;
4
5
6 * Java 反射练习。
7 *
8 * Wanggc
9 10 class ReflectionTest {
11 throws Exception {
12 DisPlay disPlay = new DisPlay();
13 14 Class<?> cls = disPlay.getClass();
15 通过Class取得DisPlay类的show方法16 Method method = cls.getMethod("show",String.class);
17 调用show方法18 method.invoke(disPlay,"Wanggc");
19 }
20 }
21
22 class DisPlay {
23 void show(String name) {
24 System.out.println("Hello :" + name);
25 }
26 }

复制代码

      前面说过,Java程序的每一个类都会有个Class对象与之对应。Java反射的第1步就是取得这个Class对象,如代码14行。固然,每一个类的方法也必有1个Method对象与之对应。要通过反射的方式调用这个方法,就要首先取得这个方法的Method对象,如代码16行,然后用Method对象反过来调用这个方法,如代码18行。注意16行getMethod方法的第1个参数是方法名,第2个是此方法的参数类型,如果是多个参数,接着添加参数就能够了,由于getMethod是可变参数方法。履行18行代码的invoke方法,其实也就是履行show方法,注意invoke的第1个参数,是DisPlay类的1个对象,也就是调用DisPlay类哪一个对象的show方法,第2个参数是给show方法传递的参数。类型和个数1定要与16行的getMethod方法1直。

      上例讲述了如何通过反射调用某个类的方法,下面将再通过1个实例讲述如何通过反射给某个类的属性赋值:

复制代码

  1   2 
3 import java.lang.reflect.Field;
4
5 6 * Java 反射之属性练习。
7 8 9 10 11 12 建立学生对象 13 Student student = new Student();
14 为学生对象赋值 15 student.setStuName("Wanggc");
16 student.setStuAge(24);
17 建立拷贝目标对象 18 Student destStudent = 19 拷贝学生对象 20 copyBean(student,destStudent);
21 输出拷贝结果 22 System.out.println(destStudent.getStuName() + ":"
23 + destStudent.getStuAge());
24 }
25
26 27 * 拷贝学生对象信息。
28 *
29 * from
30 * 拷贝源对象
31 dest
32 * 拷贝目标对象
33 Exception
34 * 例外
35 36 private void copyBean(Object from,Object dest) 37 获得拷贝源对象的Class对象 38 Class<?> fromClass = from.getClass();
39 获得拷贝源对象的属性列表 40 Field[] fromFields = fromClass.getDeclaredFields();
41 获得拷贝目标对象的Class对象 42 Class<?> destClass = dest.getClass();
43 Field destField = null;
44 for (Field fromField : fromFields) {
45 获得拷贝源对象的属性名字 46 String name = fromField.getName();
47 获得拷贝目标对象的相同名称的属性 48 destField = destClass.getDeclaredField(name);
49 设置属性的可访问性(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读