黑马程序员------java 反射Reflection
2014-09-24 21:58
423 查看
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
java反射是java中相对重要的知识,是java很多框架的基石,没有反射就没有了很多框架。
在java运行时环境中,对于任意一个类,我们都能知道这个类有哪些方法和属性,对于任意一个对象我们也都能调用它的任意一个
方法。这种动态获取类信息以及动态调用对象的方法的功能就来自于java语言的反射(Reflection).
java反射机制主要提供了以下功能:
在运行时判断任意一个对象所属的类。
在运行时构造任意一个类的对象。
在运行时判断任意一个类所具有的成员变量和方法。
在运行时调用任意一个对象的方法。
Reflection是java被视为动态语言的一个关键性质。这个机制允许程序再运行时透过Reflectiion API取得任何一个已知名称的class的
内部信息,包括其modifiers(public,static 等)、superclass、实现之interfaces,也包括fields和methods的所有信息,并可运行时改变fields和methods的所有信息,
也可于运行时改变fields内容或调用methods。
通过reflection我们可以打破java语言的封装性,既可以访问似有的变量方法。
在java中,主要由一下类来实现java反射机制,这些类都位于java.lang.reflect包中:
- Class类:代表一个类。
- Field类:代表类的成员变量(类的属性)。
- Method类: 代表类的方法。
- Constructor类:代表类的构造方法。
-Array类:提供了动态创建数组,以及访问数据的元素的静态方法。
例如如下获得一个字符串所对应的类的Class对象以及这个类中的所有的方法:
输入 java.lang.String
输出:
public int java.lang.String.hashCode()
public boolean java.lang.String.equals(java.lang.Object)
public java.lang.String java.lang.String.toString()
public char java.lang.String.charAt(int)
private static void java.lang.String.checkBounds(byte[],int,int)
public int java.lang.String.codePointAt(int)
public int java.lang.String.codePointBefore(int)
public int java.lang.String.codePointCount(int,int) ...... java.lang.String类中所有的方法
下面展示了如何简单的获取一个类的Class,获取到类中特定的方法,调用获取的Method对应的方法:
下面这个例子使用反射实现类的拷贝:
解读:
1、要想使用反射,首先要获得待处理类或对象所对应的Class对象。
获取某个类或某个对象所对应的Class的常用的3中方式:
a、使用Class的静态方法forName Class.forName("java.lang.String");
b、使用类的.class语法 String.class
c、使用对象的getclass()方法 Class<?> clazz = "aa".getClass();
2、若想通过类的不带参数的构造方法来生成对象,我们有两种方法:
a、通过Class对象的newInstance()方法直接生成:
Class<?> clazz = String.class;
Object obj = clazz.newInstance();
b、先获得Class对象,然后通过该对象获得对应的Constructor对象,再通过Contructor对象的newInstance(方法生成
Class<?> clazz = Customer.class;
Constructor cons = clazz.getConstructor(new Class[]{});
Object obj = cons.newInstance(new Object[]{});
3、若想通过类的带参数的构造方法生成对象,只能使用下面一种方法:
Class<?> clazz = Customer.class;
Constructor cons = clazz.getConstructor(new Class[]{String.class,int.class});
Object obj = cons.newInstance(new Object[]{"hello",3});
3、Class<T>类提供了几个获取Method的几种方法
getMethod(String name, Class<?>... parameterTypes) 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法
public Method[] getMethods() 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继 承的那些的类或接口)的公共 member 方法
public Method getDeclaredMethod(String name,Class<?>... parameterTypes)返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法
public Method[] getDeclaredMethods() 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私 有方法,但不包括继承的方法
java.lang.Array类提供了动态创建和访问数组元素的各种静态方法。例如:下面的例子中
创建了一个长度为10的字符串数组,接着把索引位置为5的元素设为“hello”,然后再读取索引位置为5的元素的值
反射机制中打破java封装的 setAccessible(boolean f)方法
在java中我们不能再类的外部访问类中的private方法和属性,这是java封装机制。但是通过反射我们可以打破这种常规的机制。
Method 和Field类的SetAccessible(boolean b) 方法可以压制java对访问修饰符的检查.
例如以下连个例子:
总的来说java的反射机制灵活的为我们提供了许多看似不能实现的功能,用它可以解决许多死的机制问题。
java反射是java中相对重要的知识,是java很多框架的基石,没有反射就没有了很多框架。
在java运行时环境中,对于任意一个类,我们都能知道这个类有哪些方法和属性,对于任意一个对象我们也都能调用它的任意一个
方法。这种动态获取类信息以及动态调用对象的方法的功能就来自于java语言的反射(Reflection).
java反射机制主要提供了以下功能:
在运行时判断任意一个对象所属的类。
在运行时构造任意一个类的对象。
在运行时判断任意一个类所具有的成员变量和方法。
在运行时调用任意一个对象的方法。
Reflection是java被视为动态语言的一个关键性质。这个机制允许程序再运行时透过Reflectiion API取得任何一个已知名称的class的
内部信息,包括其modifiers(public,static 等)、superclass、实现之interfaces,也包括fields和methods的所有信息,并可运行时改变fields和methods的所有信息,
也可于运行时改变fields内容或调用methods。
通过reflection我们可以打破java语言的封装性,既可以访问似有的变量方法。
在java中,主要由一下类来实现java反射机制,这些类都位于java.lang.reflect包中:
- Class类:代表一个类。
- Field类:代表类的成员变量(类的属性)。
- Method类: 代表类的方法。
- Constructor类:代表类的构造方法。
-Array类:提供了动态创建数组,以及访问数据的元素的静态方法。
例如如下获得一个字符串所对应的类的Class对象以及这个类中的所有的方法:
package reflect; import java.lang.reflect.Method; public class DumpMethods { public static void main(String[] args) throws Exception { // Class<?> classType = Class.forName("java.lang.String");//将获得字符串所标示的类的Class对象 Class<?> classType = Class.forName(args[0]);//将获得传入的字符串对象所标示的类的Class对象 Method[] methods = classType.getDeclaredMethods();//获得Class对象中的所有方法 for(Method me:methods) { System.out.println(me); } } }
输入 java.lang.String
输出:
public int java.lang.String.hashCode()
public boolean java.lang.String.equals(java.lang.Object)
public java.lang.String java.lang.String.toString()
public char java.lang.String.charAt(int)
private static void java.lang.String.checkBounds(byte[],int,int)
public int java.lang.String.codePointAt(int)
public int java.lang.String.codePointBefore(int)
public int java.lang.String.codePointCount(int,int) ...... java.lang.String类中所有的方法
下面展示了如何简单的获取一个类的Class,获取到类中特定的方法,调用获取的Method对应的方法:
package reflect; import java.lang.reflect.Method; public class InvokeTester { public int add(int param1,int param2) { return param1+param2; } public String echo(String message) { return "hello :" +message; } public static void main(String[] args) throws Exception { // InvokeTester test = new InvokeTester(); // System.out.println(test.add(4,8)); // System.out.println(test.echo("123321")); 常规调用方法的写法 /* * 先获取Class对象 */ //Class<?> classType= Class.forName();//通过Class类的静态方法forname() 传入类的全称可以获取这个类对应的Class对象 Class<?> classType=InvokeTester.class;//通过java内置的语法 类名.class Object invokeTester = classType.newInstance(); //生成对应的类的实例 /* * 通过与这个类所对应的Class对象.getMethod("方法名",参数对应Class对象对应的Claa【】数组) */ Method addMethod = classType.getMethod("add",new Class[]{int.class,int.class}); /* * invoke 表示调用了Method对象对应的目标方法 * 参数:第一个Object 对象 标示在那个类上调用 * 第二个数组的方式传具体的参数 或者可变参数的方式 */ Object result = addMethod.invoke(invokeTester,new Object[]{1,2}); System.out.println((Integer)result); //总是返回原生类型的包装类 也可以不转换 System.out.println("============================="); Method echoMethod = classType.getMethod("echo",new Class[]{String.class}); Object result1 = echoMethod.invoke(invokeTester,new String[]{"TOM"}); System.out.println((String)result1); } }
下面这个例子使用反射实现类的拷贝:
package reflect; import java.lang.reflect.Field; import java.lang.reflect.Method; public class ReflectTester { public Object ReflectCopy(Object obj) throws Exception { Class<?> classType = Customer.class; // Class<?> classType1 = Class.forName("Customer"); // Class<?> classType2 = new Customer().getClass();//三种获取类的Class方式 Object obj1 = classType.newInstance(); //不带参数的生成实例 Class.newInstance() // Constructor con = classType.getConstructor(new Class[]{}); // Object obj2 = con.newInstance(); // 通过先生成constructor类的不带参数的实例 在调用其newInstance()方法生成实例 // Constructor con1 = classType.getConstructor(new Class[]{String.class,int.class}); //生成带参数的构造方法的实例 // Object obj3 = con1.newInstance(new Object[]{"TOM",13}); //传入Object类的数组 里面的额值为与类的构造方法对应的参数 Field[] field = classType.getDeclaredFields(); for(Field fie: field) { String name =fie.getName(); String firstLetter = name.substring(0,1).toUpperCase(); String getMethodName ="get"+firstLetter+name.substring(1);//substring(1)截取 String setMethodName ="set"+firstLetter+name.substring(1); Method getMethod = classType.getMethod(getMethodName,new Class[]{}); Method setMethod = classType.getMethod(setMethodName,new Class[]{fie.getType()}); Object value = getMethod.invoke(obj,new Object[]{}); setMethod.invoke(obj1,new Object[]{value}); } return obj1; } public static void main(String[] args) throws Exception { ReflectTester test =new ReflectTester(); Customer cus =new Customer("tom",13); cus.setId(1L); Customer co =(Customer) test.ReflectCopy(cus); System.out.println(co.getAge() +" "+co.getName()+" "+co.getId()); } } class Customer { private String name; private int age; public Long getId() { return id; } public void setId(Long id) { this.id = id; } private Long id; public Customer() { } public Customer(String name,int age) { this.name = name; this.age = age; } 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; } }
解读:
1、要想使用反射,首先要获得待处理类或对象所对应的Class对象。
获取某个类或某个对象所对应的Class的常用的3中方式:
a、使用Class的静态方法forName Class.forName("java.lang.String");
b、使用类的.class语法 String.class
c、使用对象的getclass()方法 Class<?> clazz = "aa".getClass();
2、若想通过类的不带参数的构造方法来生成对象,我们有两种方法:
a、通过Class对象的newInstance()方法直接生成:
Class<?> clazz = String.class;
Object obj = clazz.newInstance();
b、先获得Class对象,然后通过该对象获得对应的Constructor对象,再通过Contructor对象的newInstance(方法生成
Class<?> clazz = Customer.class;
Constructor cons = clazz.getConstructor(new Class[]{});
Object obj = cons.newInstance(new Object[]{});
3、若想通过类的带参数的构造方法生成对象,只能使用下面一种方法:
Class<?> clazz = Customer.class;
Constructor cons = clazz.getConstructor(new Class[]{String.class,int.class});
Object obj = cons.newInstance(new Object[]{"hello",3});
3、Class<T>类提供了几个获取Method的几种方法
getMethod(String name, Class<?>... parameterTypes) 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法
public Method[] getMethods() 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继 承的那些的类或接口)的公共 member 方法
public Method getDeclaredMethod(String name,Class<?>... parameterTypes)返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法
public Method[] getDeclaredMethods() 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私 有方法,但不包括继承的方法
java.lang.Array类提供了动态创建和访问数组元素的各种静态方法。例如:下面的例子中
创建了一个长度为10的字符串数组,接着把索引位置为5的元素设为“hello”,然后再读取索引位置为5的元素的值
package reflect; import java.lang.reflect.Array; public class ArrayTest { public static void main(String[] args) throws Exception { Class<?> classType = Class.forName("java.lang.String"); System.out.println(classType); Object array = Array.newInstance(classType,10); Array.set(array,5,"hello"); String str = (String) Array.get(array,5); System.out.println(str); } }
反射机制中打破java封装的 setAccessible(boolean f)方法
在java中我们不能再类的外部访问类中的private方法和属性,这是java封装机制。但是通过反射我们可以打破这种常规的机制。
Method 和Field类的SetAccessible(boolean b) 方法可以压制java对访问修饰符的检查.
例如以下连个例子:
package reflect; public class PrivateTest { private String sayHello(String name) { return "hello"+name; } //反射可以打破类的封装 } package reflect; import java.lang.reflect.Method; public class PrivateTest2 { public static void main(String[] args) throws Exception { PrivateTest p = new PrivateTest(); Class<?> classType = p.getClass(); Method method = classType.getDeclaredMethod("sayHello",new Class[]{String.class}); method.setAccessible(true);//...压制java对访问修饰符的检查 String str = (String) method.invoke(p,new Object[]{"zhangsan"}); System.out.println(str); } }
package reflect; public class Private2 { private String name = "zhangsan"; public String getName() { return name; } } package reflect; import java.lang.reflect.Field; import java.lang.reflect.Method; public class Reprivate { public static void main(String[] args) throws Exception { Private2 p1 =new Private2(); Class<?> classTy = p1.getClass(); Field field = classTy.getDeclaredField("name"); field.setAccessible(true); //压制JAVA对访问修饰符的检查 field.set(p1,"lisi"); Method method = classTy.getMethod("getName",new Class[]{}); String str = (String) method.invoke(p1,new Object[]{}); System.out.println(str); } }
总的来说java的反射机制灵活的为我们提供了许多看似不能实现的功能,用它可以解决许多死的机制问题。
相关文章推荐
- 黑马程序员-->Java基础加强-->反射(Reflection)
- 黑马程序员_Java基础:反射机制(Reflection)总结
- 黑马程序员--------------学习JAVA反射(Reflection)
- 黑马程序员---------Java反射(Reflection)笔记
- 黑马程序员_Java基础:反射机制(Reflection)总结
- Java Reflection (JAVA反射)
- JAVA反射 java reflection
- Java Reflection (JAVA反射)
- Java Reflection (JAVA反射)
- Java反射经典实例 Java Reflection Cookbook
- Java反射经典实例 Java Reflection Cookbook
- Java Reflection (JAVA反射)
- Java Reflection (JAVA反射)
- Java Reflection (JAVA反射)
- Java反射经典实例 Java Reflection Cookbook
- Java反射经典实例 Java Reflection Cookbook (转)
- java-Java Reflection (JAVA反射)
- 利用Java Reflection(反射)原理,在hibernate里面实现对单表、视图的动态组合查询
- Java Reflection (JAVA反射)
- 【转】JAVA的内省(introspector)与反射(reflection)