Java原来如此-反射机制
在Java运行时环境中,对于任意一个类,能知道这个类有哪些属性和方法。对于任意一个对象,能调用它的任意一个方法。这种动态获取类的信息以及动态调用对象的方法的功能来自于Java语言的反射(Reflection)机制。
Java反射机制主要提供了以下功能。
1. 在运行时判断任意一个对象所属的类。
2. 在运行时构造任意一个类的对象。
3. 在运行时判断任意一个类所具有的成员变量和方法。
4. 在运行时调用任意一个对象的方法。
反射机制是Java被视为动态语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其方法修饰符,父类,实现的接口,属性,方法等信息,并可于运行时改变属性内容或调用方法。
Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体,或对其属性设值,或唤起其方法。这种“看透class”的能力被称为introspection(內省,内观,反省)。Reflection和introspection是常被并提的两个术语。
在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中:
Class类:代表一个类。
Field类:代表类的成员变量(成员变量也称为类的属性)。
Method类:代表类的方法。
Constructor类:代表类的构造方法。
Array类:提供了动态创建数组,以及访问数组的元素的静态方法。
要想使用反射,首先需要获得待处理类或对象所对应的Class对象。
获取某个类或某个对象所对应的class对象的常用的3种方式:
1. 使用Class类的静态方法forName:Class.forName(“java.lang.String”);
2. 使用类的.class语法:String.class;
3. 使用对象的getClass()方法:String s = “aa”;Class<?> clazz = s.getClass();
在java.lang.Object类中定义了getClass()方法,因此对于任意一个Java对象,都可以通过此方法获得对象的类型。Class类是Reflection API中的核心类,它有以下方法
getName():获得类的完整名字。
getFields():获得类的public类型的属性。
getDeclaredFields():获得类的所有属性。
getMethods():获得类的public类型的方法。
getDeclaredMethods():获得类的所有方法。
getMethod(String name,Class[]parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes参数指定方法的参数类型。
getConstructors():获得类的public类型的构造方法。
getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes参数指定构造方法的参数类型。
newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
以下程序演示了Reflection API的基本作用,它读取命令行参数指定的类名,然后打印这个类所具有的方法信息。
package com.zhouyu.reflect; import java.lang.reflect.Method; public class ReflectTest
{
public static void main(String[] args)
{
try
{
Class<?> classType = Class.forName(args[0]);
Method[] methods = classType.getDeclaredMethods();
for(Method method : methods)
{
System.out.println(method);
}
}
catch(Exception e)
{
System.out.println(e.toString());
}
}
}
以下代码运用反射机制调用InvokeTester对象的add()和echo()方法:
package com.zhouyu.reflect; import java.lang.reflect.*; public class InvokeTester
{
public int add(int num1,int num2)
{
return num1 + num2;
} public String echo(String message)
{
return "hello" + message;
} public static void main(String[] args) throws Exception
{
/*
//传统方式
InvokeTester invokeTester = new InvokeTester();
System.out.println(invokeTester.add(1,2));
System.out.println(invokeTester.echo("Tom"));
*/ //反射方式
Class<?> classType = InvokeTester.class;
Object invokeTester = classType.newInstance();
Method addMethod = classType.getMethod("add",new Class[]{int.class,int.class});
Object result = addMethod.invoke(invokeTester,new Object[]{1,2});
System.out.println((Integer)result); Method echoMethod = classType.getMethod("echo",new Class[]{String.class});
Object resultStr = echoMethod.invoke(invokeTester,new Object[]{"Tom"});
System.out.println((String)resultStr);
}
}
Method类的invoke(Objectobj,Object args[])方法接收的参数必须为对象,如果参数为基本类型数据,必须转换为相应的包装类型的对象。Invoke()方法的返回值总是对象,如果实际被调用的方法的返回类型是基本类型数据,那么invoke()方法会把它转换为相应的包装类型的对象,再将其返回。
若想通过类的不带参数的构造方法来生成对象,我们有两种方式:
1. 先获取Class对象,然后通过该Class对象的newInstance()方法直接生成即可:
Class<?> classType = String.class;
Object obj = classType.newInstance();
2. 先获得Class对象,然后通过该对象获得对应的Constructor对象,再通过该Constructor对象的newInstance()方法生成:
Class<?> classType = Customer.class;
Constructor cons = classType.getConstructor(new Class[]{});
Object obj = cons.newInstance(new Object[]{});
若想通过类的带参数的构造方法生成对象,只能使用下面这一种方式:
Class<?> classType = Customer.class;
Constructor cons = classType.getConstructor(newClass[]{String.class,int.class});
Object obj = cons.newInstance(new Object[]{“hello”,3});
实例
package com.zhouyu.reflect; import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method; public class ReflectTester
{
//该方法实现对Customer对象的拷贝操作
public Object copy(Object object)
{
Object objectCopy = null;
try
{
Class<?> classType = object.getClass();
/*
//不带参数的第一种方法
Object obj = classType.newInstance();
*/
//不带参数的第二种方法
Constructor cons = classType.getConstructor(new Class[]{});
objectCopy = cons.newInstance(new Object[]{});
/*
//带参数的
Constructor cons2 = classType.getConstructor(new Class[]{String.class,int.class});
Object obj3 = cons2.newInstance(new Object[]{"Tom",32}); System.out.println(obj);
System.out.println(obj2);
System.out.println(obj3);
*/
// 获得对象的所有成员变量
Field[] fields = classType.getDeclaredFields(); for (Field field : fields)
{
String name = field.getName(); String firstLetter = name.substring(0, 1).toUpperCase();// 将属性的首字母转换为大写 String getMethodName = "get" + firstLetter + name.substring(1);
String setMethodName = "set" + firstLetter + name.substring(1); Method getMethod = classType.getMethod(getMethodName,
new Class[] {}); Method setMethod = classType.getMethod(setMethodName,
new Class[] { field.getType() }); Object value = getMethod.invoke(object, new Object[] {}); setMethod.invoke(objectCopy, new Object[] { value });
} }
catch (Exception e)
{
System.out.println(e.toString());
}
return objectCopy;
} public static void main(String[] args)
{
Customer customer = new Customer("Tom", 20);
customer.setId(1L); ReflectTester test = new ReflectTester(); Customer customer2 = (Customer) test.copy(customer); System.out.println(customer2.getId() + "," + customer2.getName() + ","
+ customer2.getAge());
}
} class Customer
{
private Long id; private String name; private int age; public Customer()
{ } public Customer(String name, int age)
{
this.name = name;
this.age = age;
} public Long getId()
{
return id;
} public void setId(Long id)
{
this.id = id;
} public String getName()
{
return name;
} public void setName(String name)
{
this.name = name;
} public int getAge()
{
return age;
} public void setAge(int age)
{
this.age = age;
}
}
Java.lang.Array类提供了动态创建和访问数组元素的各种静态方法。
实例
package com.zhouyu.reflect; import java.lang.reflect.Array; public class ArrayTester1
{
public static void main(String[] args) throws Exception
{
Class<?> classType = Class.forName("java.lang.String"); Object array = Array.newInstance(classType, 10); Array.set(array, 5, "hello"); String str = (String)Array.get(array, 5); System.out.println(str);
}
}
Java原来如此-反射机制的更多相关文章
- Java 类反射机制分析
Java 类反射机制分析 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某 ...
- java的反射机制
一.java的反射机制浅谈 最近研究java研究得很给力,主要以看博文为学习方式.以下是我对java的反射机制所产生的一些感悟,希望各位童鞋看到失误之处不吝指出.受到各位指教之处,如若让小生好好感动, ...
- Java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别
一.Java的反射机制 每个Java程序执行前都必须经过编译.加载.连接.和初始化这几个阶段,后三个阶段如下图: 其中
- java笔记--反射机制之基础总结与详解
一.反射之实例化Class类的5种方式: java的数据类型可以分为两类,即引用类型和原始类型(即基本数据类型). 对于每种类型的对象,java虚拟机会实例化不可变的java.lang.Class对象 ...
- JAVA的反射机制学习笔记(二)
上次写JAVA的反射机制学习笔记(一)的时候,还是7月22号,这些天就瞎忙活了.自己的步伐全然被打乱了~不能继续被动下去.得又一次找到自己的节奏. 4.获取类的Constructor 通过反射机制得到 ...
- java笔录---反射机制(1)
引言 为了方便记忆java的反射机制,在这里仔细的总结了一下.主要是怕以后忘记了,这样也方便回忆.因为最近利用空余时间深入的了解spring和Mybatis框架, 像spring中核心模块IO ...
- Java高新技术 反射机制
Java高新技术 反射机制 知识概要: (1)反射的基石 (2)反射 (3)Constructor类 (4)Field类 (5)Method类 (6)用反射方 ...
- java的反射机制浅谈(转)
原文链接:java的反射机制浅谈 一.java的反射机制浅谈 1.何谓反射机制 根据网文,java中的反射机制可以如此定义: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性 ...
- 【转】Java利用反射机制访问私有化构造器
Java利用反射机制访问私有化构造器 博客分类: java 我们都知道,当一个类的构造方法被设为私有的时候(private),在其他类中是无法用new来实例化一个对象的. 但是有一种方法可以把带有 ...
随机推荐
- 配置httpd虚拟主机
轻松配置httpd的虚拟主机 httpd使用VirtualHost指令进行虚拟主机的定义.支持三种虚拟主机:基于ip,基于端口和基于名称.其中基于端口的虚拟主机在httpd的术语上(例如官方手册)也属 ...
- thinkcmf常用标签
1.图片地址:{:cmf_get_image_url($vo.icon)} 2.模板控件 模板变量调用:$theme_vars.title <widget name="aboutUs& ...
- 中国电信物联网平台入门学习笔记7:NB-IOT信号如何检测
NB-IOT设备会因为信号的原因,数据发不出.但数据发不出的原因有很多,这么排除是NB-IOT信号的问题呢?那就需要NB-IOT信号检测装置. 网上的信号检测设备 作为一个常年蜗居在实验室的穷屌丝而言 ...
- CentOS 7 安装 配置 Nginx + PHP
. CentOS 7 下配置 yum 安装 Nginx. 进入/etc/yum.repos.d/目录下创建一个源配置文件nginx.repo: cd /etc/yum.repos.d/ vim ngi ...
- 水题:51Nod1095-Anigram单词
1095 Anigram单词 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 Description 一个单词a如果通过交换单词中字母的顺序可以得到另外的单词b,那 ...
- Monkeyrunner 简介及其环境搭建
Monkeyrunner是通过坐标.控件ID和控件上的文字操作应用的界面元素,其测试用例是用python写的,这样就弥补了monkey只有简单命令无法执行复杂用例的缺陷.Monkeyrunner采用的 ...
- Setting title-center on "< h1> " element on Android does not work, fix
app.scss: h1.title-center{ text-align: center!important; }
- body标签相关
03-body标签中相关标签 今日主要内容: 列表标签 <ul>.<ol>.<dl> 表格标签 <table> 表单标签 <fom> 一 ...
- loj2276 「HAOI2017」新型城市化
给出的图是一个二分图(显然--吗),一个图的最大团=其补图的最大独立集,因此二分图的最大独立集就是补图的最大团. 欲使补图最大团变大,则要最大独立集变大.二分图最大独立集=点数-最小点覆盖.最小点覆盖 ...
- Java 程序动态替换 docx 模板中定制值的实现例子
项目系统中打印功能,导出 word 文档功能是挺常用的,本文介绍自定文档模板,程序实现模板内容中值替代的功能. 模板文件 template.docx 执行 main public static v ...