- 浏览: 176015 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
yinvent:
谢谢,终于找到一个可以用的例子!
struts2学习之一简单范例 -
锅巴49:
学习了,不错.
使用 Spring 2.5 注释驱动的 IoC 功能 -
fooky:
你好,今天在配置spring secutiry3,想让系统先从 ...
spring security 配置文件小结(逐步深化到url级别) -
lj508:
你好啊 请教你个问题
我用那个纯jsp上传时
怎么运行时根本没 ...
Sturt2学习之十二---文件上传 -
641216927:
我还是一个struts2新手。
有个问题请教一下:
同时在t ...
struts2学习之一简单范例
java语言反射与动态代理学习笔记(反射部分)。(学习材料张龙的“反射机制与动态代理”)
一、Java 语言的反射机制:
在运行时判断任意一个对象所属的类。
在运行时构造任意一个类的对象。
在运行时判断任意一个类所具有的成员变量和方法。
在运行时调用任意一个对象的方法
二、在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中
Class类:代表一个类。
Field 类:代表类的成员变量(成员变量也称为类的属性)。
Method类:代表类的方法。
Constructor 类:代表类的构造方法。
Array类:提供了动态创建数组,以及访问数组的元素的静态方法
三、例程DumpMethods类演示了Reflection API的基本作用,它读取命令行参数指定的类名,然后打印这个类所具有的方法信息
package com.langsin.reflection; import java.lang.reflect.Method; public class DumpMethods { public static void main(String args[]) throws Exception { // 加载并初始化命令行参数指定的类 (如java.util.Date) Class<?> classType = Class.forName(args[0]); // 获得类的所有方法 Method methods[] = classType.getDeclaredMethods(); for (int i = 0; i < methods.length; i++) { System.out.println(methods[i].toString()); } } }
四、例程ReflectTester 类进一步演示了Reflection API的基本使用方法。ReflectTester类有一个copy(Object object)方法,这个方法能够创建一个和参数object 同样类型的对象,然后把object对象中的所有属性拷贝到新建的对象中,并将它返回
这个例子只能复制简单的JavaBean,假定JavaBean 的每个属性都有public 类型的getXXX()和setXXX()方法。
package com.langsin.reflection; import java.lang.reflect.Field; import java.lang.reflect.Method; public class ReflectTester { public Object copy(Object object) throws Exception { // 获得对象的类型 Class<?> classType = object.getClass(); System.out.println("Class:" + classType.getName()); // 通过默认构造方法创建一个新的对象 Object objectCopy = classType.getConstructor(new Class[] {}).newInstance(new Object[] {}); // 获得对象的所有属性 Field fields[] = classType.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; String fieldName = field.getName(); String firstLetter = fieldName.substring(0, 1).toUpperCase(); // 获得和属性对应的getXXX()方法的名字 String getMethodName = "get" + firstLetter + fieldName.substring(1); // 获得和属性对应的setXXX()方法的名字 String setMethodName = "set" + firstLetter + fieldName.substring(1); // 获得和属性对应的getXXX()方法 Method getMethod = classType.getMethod(getMethodName, new Class[] {}); // 获得和属性对应的setXXX()方法 Method setMethod = classType.getMethod(setMethodName, new Class[] { field.getType() }); // 调用原对象的getXXX()方法 Object value = getMethod.invoke(object, new Object[] {}); System.out.println(fieldName + ":" + value); // 调用拷贝对象的setXXX()方法 setMethod.invoke(objectCopy, new Object[] { value }); } return objectCopy; } public static void main(String[] args) throws Exception { Customer customer = new Customer("Tom", 21); customer.setId(new Long(1)); Customer customerCopy = (Customer) new ReflectTester().copy(customer); System.out.println("Copy information:" + customerCopy.getId() + " " + customerCopy.getName() + " " + customerCopy.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; } }
说明:ReflectTester 类的copy(Object object)方法依次执行以下步骤
(1)获得对象的类型:
Class classType=object.getClass();
System.out.println("Class:"+classType.getName());
在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():通过类的不带参数的构造方法创建这个类的一个对象。
(2)通过默认构造方法创建一个新对象:
Object objectCopy=classType.getConstructor(new Class[]{}).newInstance(new Object[]{});
以上代码先调用Class类的getConstructor()方法获得一个Constructor 对象,它代表默认的构造方法,然后调用Constructor对象的newInstance()方法构造一个实例。
(3)获得对象的所有属性:
Field fields[]=classType.getDeclaredFields();
Class 类的getDeclaredFields()方法返回类的所有属性,包括public、protected、默认和private访问级别的属性
(4)获得每个属性相应的getXXX()和setXXX()方法,然后执行这些方法,把原来对象的属性拷贝到新的对象中。
五、在例程InvokeTester类的main()方法中,运用反射机制调用一个InvokeTester对象的add()和echo()方法
package com.langsin.reflection; import java.lang.reflect.Method; public class InvokeTester { public int add(int param1, int param2) { return param1 + param2; } public String echo(String msg) { return "echo: " + msg; } public static void main(String[] args) throws Exception { Class<?> classType = InvokeTester.class; Object invokeTester = classType.newInstance(); // Object invokeTester = classType.getConstructor(new // Class[]{}).newInstance(new Object[]{}); // 调用InvokeTester对象的add()方法 Method addMethod = classType.getMethod("add", new Class[] { int.class, int.class }); Object result = addMethod.invoke(invokeTester, new Object[] { new Integer(100), new Integer(200) }); System.out.println((Integer) result); // 调用InvokeTester对象的echo()方法 Method echoMethod = classType.getMethod("echo", new Class[] { String.class }); result = echoMethod.invoke(invokeTester, new Object[] { "Hello" }); System.out.println((String) result); } }
说明:add()方法的两个参数为int 类型,获得表示add()方法的Method对象的代码如下:
Method addMethod=classType.getMethod("add",new Class[]{int.class,int.class});
Method类的invoke(Object obj,Object args[])方法接收的参数必须为对象,如果参数为基本类型数据,必须转换为相应的包装类型的对象。invoke()方法的返回值总是对象,如果实际被调用的方法的返回类型是基本类型数据,那么invoke()方法会把它转换为相应的包装类型的对象,再将其返回。
在本例中,尽管InvokeTester 类的add()方法的两个参数以及返回值都是int类型,调用add Method 对象的invoke()方法时,只能传递Integer 类型的参数,并且invoke()方法的返回类型也是Integer 类型,Integer 类是int 基本类型的包装类:
Object result=addMethod.invoke(invokeTester,
new Object[]{new Integer(100),new Integer(200)});
System.out.println((Integer)result); //result 为Integer类型
六:java.lang.Array 类提供了动态创建和访问数组元素的各种静态方法。例程
ArrayTester1 类的main()方法创建了一个长度为10 的字符串数组,接着把索引位置为5 的元素设为“hello”,然后再读取索引位置为5 的元素的值
package com.langsin.reflection; import java.lang.reflect.Array; public class ArrayTester1 { public static void main(String args[]) throws Exception { Class<?> classType = Class.forName("java.lang.String"); // 创建一个长度为10的字符串数组 Object array = Array.newInstance(classType, 10); // 把索引位置为5的元素设为"hello" Array.set(array, 5, "he"); Array.set(array, 6, "h"); // 获得索引位置为5的元素的值 String s = (String) Array.get(array, 5); System.out.println(s); } } //注:java中一个数组中只能有一个数据类型。
七、例程ArrayTester2 类的main()方法创建了一个 5 x 10 x 15 的三维整型数组,并把索引位置为[3][5][10] 的元素的值为设37
package com.langsin.reflection; import java.lang.reflect.Array; public class ArrayTester2 { public static void main(String args[]) { int[] dims = new int[] { 5, 10, 15 };//此处的dims等一下当参数传入,将决定该数据是几维的。 //Integer.TYPE的含义:是表示Integer类对应的Class对象。相当于Class<?> classType = Class.forName("java.lang.Integer"); Object array = Array.newInstance(Integer.TYPE, dims);//接上面一行“相当于”,此行相当于Object array = Array.newInstance(classType , dims); Object arrayObj = Array.get(array, 3);//java的多维数组,实际上是数组的数组,此处返回的arrayObj其实返回的是二维数组的对象) Class<?> cls = arrayObj.getClass().getComponentType(); System.out.println(cls); arrayObj = Array.get(arrayObj, 5); Array.setInt(arrayObj, 10, 37); int[][][] arrayCast = (int[][][]) array; System.out.println(arrayCast[3][5][10]); } }
八、众所周知Java有个Object类,是所有Java类的继承根源,其内声明了数个应该在所有Java class中被改写的methods:hashCode()、equals()、clone()、toString()、getClass()等。其中getClass()返回一个Class object。 而Class类也继承了Object对象。但是Class类没有Pulic函数,我们没有办法通过程序去改写java的Class类,他是由JVM在运行时动态生成的。
顺便说明:==和equals的区别: (误区:有的书上说==比较地址,equals比较内容,这么说不完全正确)
从Object层次来说,他们是相同的,都是比较两个引用是否指向同一个对象,是则返回true,否则返回false。
但是为什么有的书上会说成equals是比较内容,那是因为很多方法继承Object对象后重写了这个方法,最典型的类是String类(它也重写了这个方法),它比较的就是内容,所以那些书上会写错。
九:Java允许我们从多种途径为一个class生成对应的Class object
Class Object诞生管道 | 示例
——————————————————————————————————————————————
运用getClass() | String str="abc";
注:每个class都有此函数 | Class c1=str.getClass();
——————————————————————————————————————————————
运用 | Button b=new Button();
Class.getSuperclass() | Class c1=b.getClass();//c1是button所对应的Class实例
| Class c2=c1.getSuperclass();//c2是button父类所对应的Class实例
——————————————————————————————————————————————
运用static method | Class c1=Class.forName("java.lang.String");
Class.forName() | Class c2=Class.forName("java.awt.Button");
(最常被使用) | Class c3=Class.forName("java.util.LinkedList$Entry")
| Class c4=Class.forName("I");
| Class c5=Class.forName("[I");
——————————————————————————————————————————————
| Class c1=String.class;
运用 | Class c2=java.awt.Button.class;
.Class语法 | Class c3=Main.InnerClass.class;
| Class c4=int.class;//原生数据类型
| Class c5=int[].class;//数组
——————————————————————————————————————————————
| Class c1=Boolean.TYPE;
运用 | Class c2=Byte.TYPE;
primitive wrapper classes | Class c3=Character.TYPE;
语法 | Class c4=Short.TYPE;
| Class c5=Integer.TYPE;
| Class c6=Long.TYPE;
| Class c7=Float.TYPE;
| Class c8=Double.TYPE;
| Class c9=Void.TYPE;
——————————————————————————————————————————————
十、调用构造方法和普通方法的比较
1、构造方法调用的三种方法:
(1)调用无参的构造方法用newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
例如对类DynTest进行操作如下:
Class<?> c1=Class.forName("com.langsin.reflection.DynTest");
Object obj=c1.newInstance();
System.out.println(obj);
(2)通过默认构造方法创建一个新对象:
Class<?> classType = Class.forName("com.langsin.reflection.DynTest");
Object objectCopy=classType.getConstructor(new Class[]{}).newInstance(new Object[]{});
(3)通过带参数的构造函数来创建一个新对象:
Object objectCopy=classType.getConstructor(new Class[]{double.class,int.class}).newInstance(new Object[]{3.14159,125});
2、运行时调用普通的方法methods
假设类Test有普通方法 public String func(String s, Hashtable ht)
{System.out.pringtln("func invoked"); retuen s }
现在运行时调运该方法类似上面构造函数调用的第(3)中方法,需要以下几步
Class<?> c = Class.forName("com.langsin.reflection.Test");
Method m = c.getMethod("func", new Class[] {Class.forName("java.lang.String"),Class.forName("java.util.Hashtable") }); //通过new Class[]和函数名才能获得相应的方法类。
Test obj = new Test();
Object r = m.invoke(obj, new Object[] { "HelloWorld", null }); //通过new Object[]和对象名才能执行方法。
String rval = (String) r;
附:反射的例子程序
import java.util.*; /** 反射机制例子程序。 */ public class ClassTest { public static void main(String[] args) { System.out.println("===========获取Class的第三种方法"); Class c1=Date.class; Class c2=int.class; Class c3=Date[].class; System.out.println("Class=" + c1); System.out.println("Class=" + c2); System.out.println("Class=" + c3); System.out.println("============获取Class的第一种方法"); Employee e=new Employee("zhangsan") ; Class c4=e.getClass(); try {Employee e3=e.getClass().newInstance(); String name=e3.getname(); System.out.println("Employee Name:"+name); } catch(Exception ex1){ex1.printStackTrace();} System.out.println(e.getClass().getName()); try { System.out.println("============获取Class的第二种方法"); String className="java.util.Date"; Class c5=Class.forName(className); System.out.println(c5); } catch (Exception ex) { ex.printStackTrace(); } } } /** A minimalist employee class for testing purposes. */ class Employee { /** Constructs an employee with $0 salary. @param n the employee name */ public Employee() { name ="test"; salary = 0; } public Employee(String n) { name = n; salary = 0; } public String getname() {return name;} public void setname(String name) {this.name=name;} private String name; private double salary; }
发表评论
-
浅克隆和深克隆及序列化
2009-09-17 13:45 1475一、相关概念: 1、浅复制与深复制概念浅复制(浅克隆):被复 ... -
java访问权限修饰符(表格)
2009-09-17 13:29 1245做个表格以免忘记,程序中不写访问权限时默认为friendly ... -
关于排序方法的选择
2009-09-15 09:13 927package com.softeem.jbs.lesson4 ... -
java中注意点总结(二)
2009-09-14 14:11 9341、两线程程序对初始为零的非负整数,一增一减, 同时每次对变量 ... -
java中注意点总结(一)
2009-09-11 22:15 11321、关于String 语句:String s=new S ... -
java(内存、异常)2-异常机制及throw与throws的区别
2009-09-02 09:49 1583异常机制及throw与throw ... -
java编码处理
2009-04-27 16:59 1231java编码处理:(java在内存中使用的是uniocode编 ... -
java5.0新特性总结--Annotation系统学习整理笔记
2009-03-25 16:04 2749Java Annotation特性与使用 ... -
java5、0新特性学习总结
2009-03-25 13:29 1443一泛型编译时类型安全运行时更小抛出ClassCastExcep ... -
java(日期处理)
2009-03-20 17:39 2570第一部分关于JAVA的Date (参考关于JAVA的Date总 ... -
log4j
2009-03-20 11:42 894文章一 Log4j由三个重要的组件构成:日志信息的优先级,日 ... -
java(Annotation)转自quguilai
2009-03-20 11:07 1044什么是Annotation?(转自quguilai)2007- ... -
java(IO)第二部分
2009-03-20 09:26 987java(IO)第二部分 一、合并流SequenceI ... -
java(IO操作)第一部分
2009-03-19 21:19 1898java(IO操作)第一部分 --------I/O流 一、 ... -
java(内存、异常)
2009-03-19 15:17 967... -
jdk、jre、jvm及j2se安装
2009-03-05 14:03 3436jdk、jre、jvm及j2se安装 ... -
java语言反射与动态代理学习笔记2(动态代理部分)
2009-03-05 13:44 1402java语言反射与动态代理学习笔记(动态代理部分)。(学习材料 ...
相关推荐
这篇学习笔记主要关注动态代理部分,虽然没有提供具体的压缩包文件内容,但根据标题和描述,我们可以深入探讨这两个概念。 **反射(Reflection)** 反射是Java语言的一个强大工具,它允许程序在运行时检查类、接口...
### Java语言反射与动态代理深度解析 #### 一、Java反射机制详解 Java反射机制是Java编程语言的一个强大特性,允许程序在运行时检查和修改自身结构与行为。这一机制为开发人员提供了高度的灵活性,尤其是在框架...
java注解和反射的个人学习笔记
本学习笔记主要涵盖了Java的基础知识,包括面向对象、集合、IO流、多线程、反射与动态代理以及Java 8的新特性等方面,旨在帮助初学者或有经验的开发者巩固和提升Java编程技能。 1. 面向对象(OOP):Java的核心是...
基于java的开发源码-java多线程反射泛型及正则表达式学习笔记和源码.zip 基于java的开发源码-java多线程反射泛型及正则表达式学习笔记和源码.zip 基于java的开发源码-java多线程反射泛型及正则表达式学习笔记和源码....
《JAVA学习笔记》是林信良先生的一部深入浅出的Java编程教程,旨在帮助初学者和有一定经验的开发者巩固和提升Java编程技能。这本书涵盖了Java语言的基础到高级概念,是一份宝贵的自学资料。 首先,从基础部分开始,...
Java语言程序设计学习笔记是为初学者和有一定基础的开发者准备的一份详尽教程,它涵盖了从基础到进阶的各个重要知识点。这份笔记以Markdown(md)文件的形式组织,便于阅读和检索,使得学习过程更为高效。 首先,...
8. **反射机制**:探讨Java反射API的使用,包括动态获取类信息、创建对象、调用方法等功能,这对于理解和调试程序有很大的帮助。 9. **JVM内部机制**:简述Java虚拟机的工作原理,包括类加载、内存管理、垃圾回收...
java学习笔记java反射机制
本笔记主要涵盖了四个核心知识点:Java反射机制、流(I/O流)、内存管理和Java学习的基础。以下是对这些主题的详细阐述: 一、Java反射机制 Java反射机制是Java语言的一个强大特性,允许程序在运行时检查类、接口、...
Java反射是Java编程语言中的一个强大特性,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。在“java反射笔记”这个主题中,我们将深入探讨反射的基础知识和常见用法。 首先,我们需要了解...
学习笔记会讲解如何使用反射进行元编程,以及其在插件系统、序列化和动态代理中的应用。 9. **Java API和库**:Java标准库提供了大量的预定义类和接口,如JDBC(Java数据库连接)用于数据库操作,Swing和JavaFX用于...
Java反射是Java编程语言中的一种强大机制,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。在Java中,反射是通过java.lang.Class类和java.lang.reflect包中的类来实现的。本篇笔记将深入探讨...
笔记的第一部分是"Java入门第一季学习笔记",它可能包括Java的基础概念和语法。这部分可能会讲解如何安装Java开发工具包(JDK),创建第一个Java程序——经典的"Hello, World!",理解变量、数据类型、运算符、流程...
7. **高级特性**:这可能包括反射、动态代理、注解、JVM内存模型、垃圾回收机制、设计模式等。这些内容可以帮助开发者更好地理解和优化Java程序的性能。 每个PDF部分都应包含详细的实例和练习,以帮助读者巩固理论...
1. **反射**:Java反射机制允许在运行时检查类的信息(如类名、方法、字段等),并能动态调用方法和修改字段值,增强了代码的灵活性。 2. **泛型**:泛型提供了一种在编译时检查类型安全的方法,允许在类、接口和...
Java反射机制是Java编程语言中的一个强大特性,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。这个特性使得Java具有了高度的灵活性和动态性,尤其是在处理对象、类、接口以及它们之间的关系...
根据提供的资料,“Java李兴华学习笔记之Java常用类库”这份文档来源于北京MLDN软件实训中心的教学资料,主要涵盖了Java编程语言中常用类库的基础知识与实践技巧。课程内容分为两大部分: 1. **上次课程的主要知识...
Java反射机制是Java编程语言的一项重要特性,它允许程序在运行时动态地获取类的信息,并且能够对类的属性和方法进行操作。反射机制的核心在于Java的`java.lang.reflect`包,其中包含了`Class`、`Constructor`、`...