---------android培训、java培训、java学习型技术博客、期待与您交流!----
反射技术:
Java反射机制是在运行状态中,对应任意一个类,都能够知道这个类中的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性
这种动态获取信息以及动态调用对象的方法的功能称为:java的反射机制
反射:
反射就是把Java类中的各种成分(变量、方法、构造方法、包)映射成相应的java类。
获得这些信息的关键类是:Field、Method、Contructor、Package等。
一个类中的每个成员都可以用相应的方法API类的一个实例对象来表示,通过调用Class类的
方法可以得到这些实例对象后有什么用呢?这就是学习和应用反射的要点。
第一讲 反射的应用场所
- 1.Class概述
-
- .class文件加载到内存中就是一个Class对象
- 反射技术可以对类进行解剖
- 获取Class对象的方式有3种:
- Class.forName(类名);比如:Class.forName(“java.util.Date”)
- 类名.class比如:System.class
- 对象.getClass()比如:new person().getClass()
基本数据冷箱定义Clss是对象
参考:boolean class.isPrimitive()方法判断是否
比如:int.class==Integer.TYPE是对的
数组类型的Class实例对象
boolean Class.isArray():判断是否为数组
总之,只有在源程序出现的类型,都有各自的Class实例对象,例如:int[]、void
实例运用Constructor
1 // new String(new StringBuffer("abc")); 2 Constructorcon1= 3 String.class.getConstructor(StringBuffer.class); 4 Constructor con2= 5 Class.forName("java.lang.String").getConstructor(StringBuffer.class); 6 // 上述两种方法是一样的,注意参数调用的写法 7 8 String s1= con1.newInstance(new StringBuffer("abc")); 9 String s2= (String) con2.newInstance(new StringBuffer("abc")); 10 System.out.println(s1/*.charAt(2)*/); 11 // 调用获得的方法时要用到上面想要参数的实例对象
- Class类的newInstance()方法是使用该类无参的构造函数创建对象, 如果一个类没有无参的构造函数, 就不能这样创建了,可以调用Class类的getConstructor(String.class,int.class)方法获取一个指定的构造函数然后再调用Constructor类的newInstance("张三",20)方法创建对象
实例操作Field和暴力反射:
1 import java.lang.reflect.*; 2 public class ReliectDemo2 { 3 public static void main(String[] args) throws Exception{ 4 5 ReflectPoint pt1=new ReflectPoint(3, 5); 6 // 使用Field关键字 7 Field fielY=pt1.getClass().getField("y"); 8 // fielY的值是多少呢?不是5。fielY不是对象身上的变量,而是类上的,要用它去实例对象对应pt1的值的方法 9 System.out.println(fielY.get(pt1));//为5 10 Field fielX=pt1.getClass().getDeclaredField("x"); 11 // 由于x是被私有的,所以使用暴力反射 12 fielX.setAccessible(true); 13 System.out.println(fielX.get(pt1));//为3 14 } 15 } 16 class ReflectPoint { 17 private int x; 18 public int y; 19 public ReflectPoint(int x, int y) { 20 super(); 21 this.x = x; 22 this.y = y; 23 } 24 }
将类中的成员变量字符替换(替换的方法replaceAll)
changeString(pt1); System.out.println(pt1); } private static void changeString(Object obj)throws Exception { Field[] fields = obj.getClass().getFields();//得到全部的成分 for(Field field:fields){ // if(field.getType().equals(String.class)) if(field.getType()==String.class){//判断是否是String类型 String oldValue=(String)field.get(obj);//得到值并强转 String newValue=oldValue.replaceAll("a", "b"); field.set(obj, newValue); } } } } class ReflectPointx { private int x; public int y; public String aa="basbeasas"; public String bb="basdahfgeasas"; public String cc="baaxas"; public String dd="xxxxasasas"; public ReflectPointx(int x, int y) { super(); this.x = x; this.y = y; } public String toString(){ return aa+"--"+bb+"--"+cc+"--"+dd; } }
Mehod类是得到某个类的成员方法的类
1 String str="abc"; 2 Method methodCharAt = 3 String.class.getMethod("charAt", int.class);//得到String中charAt(int)方法 4 System.out.println(methodCharAt.invoke(str, 1));//给刚刚得到的方法赋予实际参数,答案是b 5 System.out.println(methodCharAt.invoke(str, new Object[]{2}));//旧的调用方法,答案是c
注:如果invoke(null,)的这里第一个参数数null。说明该Method对象的对应的是静态方法
Method方法:在用eclipse运行时,序Run as——RunConfigurations——Argument——Program arguments中添加执行的类名,在类名上按F2
1 import java.lang.reflect.*; 2 public class ReliectDemo2 { 3 public static void main(String[] args) throws Exception{ 4 // 普通方法 5 // TestArgument.main(new String[]{"aaa","bbb","ccc"}); 6 // 使用反射的方法:不需要知道main方法所在的类名 7 String className=args[0]; 8 Method mainMethod = Class.forName(className).getMethod("main", String[].class); 9 // 方法1:将数组打包,变压器拆包后就是String【】类型的整体 10 mainMethod.invoke(null,new Object[]{new String[]{"aaa","bbb","ccc"}}); 11 // 方法2:强转转换为超类Object,不用拆包 12 // mainMethod.invoke(null,(Object)new String[]{"aaa","bbb","ccc"}); 13 14 } 15 16 } 17 18 class TestArgument{ 19 public static void main(String[] args){ 20 for(String arg:args){ 21 System.out.println(arg); 22 } 23 } 24 }
反射获得数据的实例:
1 String[] a1=new String[]{"a","b","c"}; 2 // 打印集合数组 3 printObject(a1); 4 // 打印集合 5 printObject("abc"); 6 } 7 8 private static void printObject(Object obj) { 9 Class claz =obj.getClass(); 10 if(claz.isArray()){ 11 int len=Array.getLength(obj);//得到数组长度 12 for(int i=0;i) 13 { 14 System.out.println(Array.get(obj,i));//得到第i个数组 15 } 16 }else{ 17 System.out.println(obj); 18 }
一个集合类的实例:
Collection collection = new HashSet(); ReflectP p1 = new ReflectP(3,3); ReflectP p2 = new ReflectP(4,2); ReflectP p3 = new ReflectP(3,3); collection.add(p1); collection.add(p2); collection.add(p3); collection.add(p1); System.out.println(collection.size());//3个 // 复写了hashCode和equals之后 System.out.println(collection.size());//一般而言,2个 // 内存溢出:程序消失了,依然占用内存 p1.y=7; collection.remove(p1); System.out.println(collection.size());//移不走 } } class ReflectP{ private int x; public int y; public String str1 = "abc"; public String str2 = "basdsbd"; public String str3 = "afafsd"; public ReflectP(int x, int y) { super(); this.x = x; this.y = y; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + x; result = prime * result + y; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ReflectP other = (ReflectP) obj; if (x != other.x) return false; if (y != other.y) return false; return true; } }
反射存在的作用和意义:实现框架的功能
*框架与框架要解决的核心问题:
相对于做房子:搭建一个毛坯房(框架),固定好门、窗、等位子,用户根据这个基础上随意增添自己的喜好(类)
*框架要解决的核心问题:
我们在搭建框架的时候,你这个用户可能还在上小学,还不好写程序。那我写得框架程序怎么能条用你以后写得类呢?
因为在写框架程序时,无法知道被调用的类名的,所以,在程序中无法直接new某个类的实例对象i,而需要用反射。
*综合实例:
1)先用new语句创建ArrayList和HashSet的实例对象。演示用eclipse自动生成ReflectPoint类的equals和hashCode方法
,比较两个集合的运行结果;
简单框架程序的步骤:
1)右击项目File命名一个配置文件如:config:properties,写入配置信息:键值对形式:className = java.util.ArrayList
2)代码实现:
InputStream ips = new FileInputStream(“config:properties”);//读取配置文件
Properties props = new Properties();
Properties.load(ips);//加载这个配置信息;
ips.close();
String className = props.getProperty("className");//得到className对应的Valued就是ArrayList
主题程序就能通过反射创建newInstance()
执行主程序;
1 InputStream ips = new FileInputStream("config.properties"); 2 Properties props = new Properties(); 3 props.load(ips); 4 ips.close(); 5 6 String className = props.getProperty("className");//以后只要在配置文件改动就可以了 7 // 反射机制 8 Collection collections = 9 (Collection)Class.forName(className).newInstance(); 10 11 // Collection collection = new HashSet(); 12 ReflectP p1 = new ReflectP(3,3); 13 ReflectP p2 = new ReflectP(4,2); 14 ReflectP p3 = new ReflectP(3,3); 15 collections.add(p1); 16 collections.add(p2); 17 collections.add(p3); 18 collections.add(p1); 19 System.out.println(collections.size());
配置文件:
className=java.util.ArrayList
classname2=java.util.HashSet