在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原来如此-反射机制的更多相关文章

  1. Java 类反射机制分析

    Java 类反射机制分析 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某 ...

  2. java的反射机制

    一.java的反射机制浅谈 最近研究java研究得很给力,主要以看博文为学习方式.以下是我对java的反射机制所产生的一些感悟,希望各位童鞋看到失误之处不吝指出.受到各位指教之处,如若让小生好好感动, ...

  3. Java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别

    一.Java的反射机制   每个Java程序执行前都必须经过编译.加载.连接.和初始化这几个阶段,后三个阶段如下图:   其中

  4. java笔记--反射机制之基础总结与详解

    一.反射之实例化Class类的5种方式: java的数据类型可以分为两类,即引用类型和原始类型(即基本数据类型). 对于每种类型的对象,java虚拟机会实例化不可变的java.lang.Class对象 ...

  5. JAVA的反射机制学习笔记(二)

    上次写JAVA的反射机制学习笔记(一)的时候,还是7月22号,这些天就瞎忙活了.自己的步伐全然被打乱了~不能继续被动下去.得又一次找到自己的节奏. 4.获取类的Constructor 通过反射机制得到 ...

  6. java笔录---反射机制(1)

    引言   为了方便记忆java的反射机制,在这里仔细的总结了一下.主要是怕以后忘记了,这样也方便回忆.因为最近利用空余时间深入的了解spring和Mybatis框架,   像spring中核心模块IO ...

  7. Java高新技术 反射机制

     Java高新技术 反射机制 知识概要:                   (1)反射的基石 (2)反射 (3)Constructor类 (4)Field类 (5)Method类 (6)用反射方 ...

  8. java的反射机制浅谈(转)

    原文链接:java的反射机制浅谈 一.java的反射机制浅谈 1.何谓反射机制 根据网文,java中的反射机制可以如此定义: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性 ...

  9. 【转】Java利用反射机制访问私有化构造器

    Java利用反射机制访问私有化构造器 博客分类: java   我们都知道,当一个类的构造方法被设为私有的时候(private),在其他类中是无法用new来实例化一个对象的. 但是有一种方法可以把带有 ...

随机推荐

  1. C#基础-数组

    数组定义 定义数组并赋值 int[] scores = { 45, 56, 78, 98, 100 }; //在定义数组时赋值 for(int i = 0; i < scores.Length; ...

  2. leetcode-19-merge

    88. Merge Sorted Array 解题思路: 需要注意,两个数组是排好序的,且nums1够大.所以从两个数组的尾端开始比较,大的那个放在nums1的尾部,并且放了之后就可以前进. 例如nu ...

  3. loj2014 「SCOI2016」萌萌哒

    神tm st表+并查集 #include <iostream> #include <cstdio> #include <cmath> using namespace ...

  4. 大咖分享 | 一文解锁首届云创大会干货——上篇(文末附演讲ppt文件免费下载)

    日,第一届网易云创大会在杭州国际博览中心举办,本次大会由杭州滨江区政府和网易主办,杭州市两创示范工作领导小组办公室协办,网易云承办,以"商业匠心.技术创新"为主题,致力于打通技术创 ...

  5. 豆邮windows客户端(第三方)开发详解

    “豆邮”,是社区网站“豆瓣”的一个类似私信的功能模块.在豆瓣官网,“豆邮”曾一度被改为“私信”,但在遭到众多豆瓣用户的强烈反对之后又改了回来.然而,在豆瓣的移动客户端上,仍称呼为“私信”. 豆邮的设定 ...

  6. mongodb的基本操作数据更新

    先启动服务器 查看数据库 选择数据库 删除数据库 插入信息 查看插入的表名 查看信息 修改表数据 修改指定信息,其他信息不改变 可以使不存在的命令进行修改并保存 修改多条数据 删除数据 删除表 查看集 ...

  7. TensorFlow batch normalize的使用

    TensorFlow batch normalize的使用 batch normalize 经常与CNN搭配使用,据一些研究表面,在RNN层数不是很深的时候使用batch normalize是会用损害 ...

  8. Leetcode 479.最大回文数乘积

    最大回文数乘积 你需要找到由两个 n 位数的乘积组成的最大回文数. 由于结果会很大,你只需返回最大回文数 mod 1337得到的结果. 示例: 输入: 2 输出: 987 解释: 99 x 91 = ...

  9. ASP.NET MVC下使用SWFUpload完成剪切头像功能

    首先介绍SWFUpload组件 SWFUpload是一个客户端文件上传工具,最初由Vinterwebb.se开发,它通过整合Flash与JavaScript技术 为WEB开发者提供了一个具有丰富功能继 ...

  10. KMP算法入门

    学一把看毛片算法我觉得自己才能变得更加出色 明明昨天的题我都知道怎么模拟了,但是还是不会改KMP,是我学丑了 KMP是Knuth-Morris-Pratt三人设计的线性时间字符串匹配算法 nxt数组的 ...