JAVA反射
了解:
反射的概念:在java中,反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动态调用对象方法的功能称为JAVA的反射机制。
通过这些动态性质,JAVA反射可以在程序运行时获取对象和类的真实信息。
什么情况下运用JAVA反射呢?如果编译时根本无法预知对象和类可能属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息,此时就必须使用反射。
Class类 |
反射的核心类,可以获取类的属性、方法等内容信息 |
Field类 |
Field和Method和Constructor类都定义于Java.lang.reflect包下 Field表示类的属性,可以获取和设置类中属性的值 |
Method类 |
表示类的方法,它可以用来获取类中方法的信息,或者执行方法 |
Constructor类 |
表示类的构造方法 |
--------------------- Product类 --------------------- package com.hp.entity;
public class Product { private int proId; private String proName; private int getProId() { return proId; } private void setProId(int proId) { this.proId = proId; } public String getProName() { return proName; } public void setProName(String proName) { this.proName = proName; } public String toString(){ return "产品编号:"+this.proId+",名称:"+this.proName; } }
--------------------- 反射测试类类 --------------------- package com.hp.test; import java.lang.reflect.Field; import java.lang.reflect.Method; /* * 通过类的全路径,来获得该类的成员方法和成员属性 */ public class Test { public static void main(String[] args) { try { //根据类的全路径进行类加载,返回该类的Class对象 Class ca = Class.forName("com.hp.entity.Product"); //利用Class对象ca的自审,返回方法对象集合 Method[] methods = ca.getDeclaredMethods(); //遍历method数组,并输入方法信息 System.out.println("***** 获取方法信息 *****"); for(Method method : methods){ System.out.println(method.toString()); } System.out.println("***** 获取方法信息结束 *****");
//利用Class对象ca的自审,返回成员属性对象信息 Field[] fileds = ca.getDeclaredFields(); System.out.println("***** 获取属性信息 *****"); for(Field filed : fileds){ System.out.println(filed.toString()); } System.out.println("***** 获取属性信息结束 *****"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
|
结果如下:
***** 获取方法信息 ***** public java.lang.String com.hp.entity.Product.toString() private int com.hp.entity.Product.getProId() private void com.hp.entity.Product.setProId(int) public java.lang.String com.hp.entity.Product.getProName() public void com.hp.entity.Product.setProName(java.lang.String) ***** 获取方法信息结束 ***** ***** 获取属性信息 ***** private int com.hp.entity.Product.proId private java.lang.String com.hp.entity.Product.proName ***** 获取属性信息结束 ***** |
注意:这上面这些步骤之前,首先当然要导入java.lang.reflect包下要用到的类
例:Class ca = Class.forName("com.hp.entity.Product");
例:Product product=new Product(); Class ca = product.getClass();
例:Class ca=Product.class; |
--------------------- Product类 --------------------- package com.hp.entity; @Deprecated public class public Product(){
} public Product(int proId){ this.proId=proId; } private Product(int proId,String proName){ this.proId=proId; this.proName=proName; }
private int proId; private String proName; private int getProId() { return proId; } private void setProId(int proId) { this.proId = proId; } public String getProName() { return proName; } public void setProName(String proName) { this.proName = proName; } public String toString(){ return "产品编号:"+this.proId+",名称:"+this.proName; } public void showInfo(){ System.out.println("产品编号:"); } class Price{ } } --------------------- 反射示例类 --------------------- package com.hp.test;
import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Method;
import com.hp.entity.Product;
public class Test2 { public static void main(String[] args) { /*获取Product类的Class对象*/ Class System.out.println("******* 获得指定构造 *******");
try { Constructor con= ca.getConstructor(int.class); System.out.println(con.toString()); } catch (SecurityException e1) { e1.printStackTrace(); } catch (NoSuchMethodException e1) { e1.printStackTrace(); }
/*获取Product类的全部的构造方法*/ Constructor[] cstr = ca.getDeclaredConstructors(); System.out.println("******* Product的全部构造方法********"); for(Constructor c : cstr){ System.out.println(c.toString()); } /*获取Product类的public构造方法*/ Constructor[] cstr_pub = ca.getConstructors();
System.out.println("******* Product的全部public构造方法********"); for(Constructor c : cstr_pub){ System.out.println(c.toString()); } /*获取Product类的public方法*/ Method[] methods=ca.getMethods(); System.out.println("******* Product的全部public方法********"); for(Method m : methods){ System.out.println(m.toString()); } /*获取Product类的名为指定方法*/ try { System.out.println("****** Product不带参数的名为showInfo方法 *****"); Method method = ca.getMethod("showInfo", null); System.out.println(method.toString()); } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } /*获取Product类的全部注解*/ Annotation[] anno=ca.getAnnotations(); System.out.println("****** Product的全部注解 *****"); for(Annotation an : anno){ System.out.println(an.toString()); } /*获取Product类的包信息*/ Package pack=ca.getPackage(); System.out.println("**** Product类的包信息 *****"); System.out.println(pack.toString()); /*获取Product类的内部类*/ Class[] prices = ca.getDeclaredClasses();//返回内部类 System.out.println("******* Product的内部类 ******"); for(Class c : prices){ System.out.println(c.toString()); } /*也可以通过内部类获取它的Class对象*/ try { Class cla=Class.forName("com.hp.entity.Product$Price"); System.out.println("******* Product的内部类具体信息 *****"); System.out.println("cla对应类的外部类是:"+cla.getDeclaringClass()); System.out.println("cla对应类的包:"+cla.getPackage()); System.out.println("cla对应类的父类:"+cla.getSuperclass()); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } |
package com.hp.test;
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException;
import com.hp.entity.Product;
public class Test3 {
public static void main(String[] args) { /* * 通过反射来生成对象有两种方式: * 1.使用newInstance()创建对象:利用默认构造方法创建实例 * 2.使用Constructor对象创建对象:使用指定构造方法创建实例 * */ Class ca=Product.class; try { ********************使用newInstance创建对象***************** Product p = (Product)ca.newInstance(); p.setProName("华为mate9"); System.out.println(p.getProName()); /* * 通常我们不使用反射创建对象,毕竟通过反射创建对象时性能稍微低一些, * 实际上,只有当程序需要动态创建某个类的对象时才会考虑使用反射,通常在开发通用性比较广的框架, * 基础平台时可能会大量使用反射;因为在许多JAVAEE框架中,都需要根据配置文件信息来创建JAVA对象, * 从配置文件读取的只是某个类的字符串类名,程序想通过字符串来创建对象的实例,就必须使用反射,比如spring框架就应用了反射技术 * */ } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } ********************使用构造方法的newInstance创建对象*****************
try { Constructor cu = ca.getConstructor(int.class); Product p2=(Product)cu.newInstance(1008); System.out.println(p2.getProId()); } catch (Exception e) { e.printStackTrace(); } } } |
package com.hp.test;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method;
import com.hp.entity.Product;
public class Test4 { public static void main(String[] args) { /*** 使用反射调用方法 ***/ Class ca=Product.class; try { Product p = (Product)ca.newInstance(); Method m = ca.getMethod("setProName", String.class); //invlke可以调用Method对象对应的方法 m.invoke(p, "华为nova手机"); System.out.println(p.getProName()); /* * 注意:如果setProId为私有的 * */ //注意:这里要使用getDeclaredMethod才能访问到私有的方法 Method m2=ca.getDeclaredMethod("setProId", int.class); m2.setAccessible(true);//setAccessible为true则表示取消JAVA语言访问权限检查 m2.invoke(p, 108); System.out.println(p.getProId());
} catch (Exception e) { e.printStackTrace(); } } } |
package com.hp.test; import java.lang.reflect.Field; import com.hp.entity.Product; public class Test5 { public static void main(String[] args) { Product p = new Product(); Class ca = p.getClass(); try { //获取Product类的各种访问级别的proName属性 Field field= ca.getDeclaredField("proName"); //设置通过反射访问Field时取消权限检查,就可以访问私有属性 field.setAccessible(true); field.set(p, "三星note5"); System.out.println(p.getProName()); } catch (Exception e) { e.printStackTrace(); } } } |
package com.hp.test;
import java.lang.reflect.Array;
public class Test6 { public static void main(String[] args) { //创建一个元素类型为String,长度为3的数组 Object arr = Array.newInstance(String.class, 3); //依次为arr数组中index为0,1,2的元素赋值 Array.set(arr, 0, "荣耀盒子"); Array.set(arr, 1, "荣耀8手机"); Array.set(arr, 2, "华为mate9保时捷版"); //取出arr数组中index为0,1,2的元素的值 Object o1= Array.get(arr, 0); Object o2= Array.get(arr, 1); Object o3= Array.get(arr, 2);
System.out.println(o1); System.out.println(o2); System.out.println(o3); } } |