——- android培训、java培训、期待与您交流! ———-
反射的基石->Class类
*JAVA程序中的和个JAVA类属于同一类事物,描述这类事物的JAVA类名就是Class.
*对比提问:众多的人用一个什么类表示?从多JAVA类用一个什么类表示?
-人->Person
-Java->Class
*对比提问:Person类代表人.它的实例张三,李四这样一个具体的人,Class代表Java类,它的实例分别对应什么?
-对应各个类在内存中的字节码,例如,Person类的字节码,ArryList类的字节码,等等
-一个加载到内存中,占用一片存储空间,这个空间内容就是字节码,
不同的类字节码是不同的,所以它们在内存中的内容是不同的,
这一个个的空间分别用一个个对象来表示,
这些对象显然具有想同的类型,它的类型又是什么呢?
*如何得到各个字节码对应的实例对象?
-类名class:如System.class
-对象getClass()例如 new Date().getClass()
-Class.forName("类名")如:Class.forName("java.lang.String");
*九个预定义Class实例对象
-查看Class.isPrimitive()
-int.class==Integer.Type
*数组类型的Class对象
-Class.isArray()
总之在源程序中出现的类型,都有各自Class对象,如int[],void.....
反射的概念:
*反射就是把JAVA类中各种成分映射成相应的JAVA类,
例如一个JAVA类用一个CLASS类的对象来表示,一个类中的组成部分,
成员变量,方法,构造方法,包等等信息也用一个个的JAVA类来表示,
像汽车的发动机,变速箱等等也是一个个的类.
表示JAAV类的CLASS显然要提供一系列的方法,来获得其中的变量,
方法,构造方法,修饰符,包等信息,
这些信息就是用相应类的实例对象来表示,
它们是Field,Method,Constructor,Package等
*一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,
通过调用Class类的方法可以得到这些实例对象后,
得到这些实例有什么用呢?怎么用呢?这正是我们学习和应用反射的要点
Constructor类
*Constructor类代表某个类的一人上构造方法
*得到某个所有构造方法:
-例子:Constructor []constructors = Class.forName("java.lang.String").getConstructors();
得到某一构造方法:
-例子:Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.clss);//获得方法要用到的类型
*创建对象
-通常方式:String str = new String("abc");
-反射方式:String str = (String)constructor.getInstanece(new StringBuffer());
//调用获得的方法时要乃至上面相同类型的实例对象
*Class.newInstance()方法
-例子String str = (String)Class.forName("java.lang.String").newInstance();
_该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象
_该方法的具体代码是怎么写成的呢?用到了缓存机制保存默认构造方法实例对象
示例:通过反射来创建String对象,并打印出字符串”abcde”
import java.lang.reflect.Constructor;
public class TestReflect1 {
/**
* @param args
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
//三种拿到类字节码方法
Class str1 = Class.forName("java.lang.String");
Class str2 = String.class;
Class str3 = "abc".getClass();
//判断它们是不都拿到同一字节码
System.out.println(str1==str2);
System.out.println(str1==str3);
System.out.println(str3==str2);
//获取指定类型的构造器
Constructor struct = str1.getConstructor(StringBuffer.class);
//实例化
String str = (String)struct.newInstance(new StringBuffer("abcd"));
//输出结果
System.out.println(str);
}
}
Field类:
Field类代表某个类中成员变量
示例:定义一个类,里面有两个参数,私有和公有然后通过反射取出这个两个变量的值.
package com.myreflect;
public class TetsPoint {
private int x;
public int y;
public TetsPoint(int x, int y) {
this.x = x;
this.y = y;
}
}
package com.myreflect;
import java.lang.reflect.Field;
public class TestReflect1 {
/**
* @param args
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
//创建自定义点的对象
TetsPoint test= new TetsPoint(8, 10);
//通过对象拿到通过getField("参数")方法来实例化Field,里面的参数表示要拿的变量名
Field field = test.getClass().getField("y");
//通过该方法可以获得私有变量的值
Field field1 = test.getClass().getDeclaredField("x");
System.out.println(field.get(test));
field1.setAccessible(true);
System.out.println(field1.get(test));
}
}
做到这里我想了一下如果我想把某个类中的成员变量的所有字符串的a改成b可以吗?如果有以前的方法那是不行的但是反射却可以做到
示例:把某个类的成员变量的字符的a全改为b
package com.myreflect;
public class TetsPoint {
private int x;
public int y;
public String str1 ="apple";
public String str2 = "ball";
public String str3 = "football";
public TetsPoint(int x, int y) {
this.x = x;
this.y = y;
}
public String toString(){
return str1+":"+str2+":"+str3;
}
}
package com.myreflect;
import java.lang.reflect.Field;
public class TestReflect1 {
/**
* @param args
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
//创建自定义点的对象
TetsPoint test= new TetsPoint(8, 10);
Field []fields = test.getClass().getFields();
for(Field field : fields){
if(field.getType()==String.class){
String oldStr = (String)field.get(test);
String newStr = oldStr.replace('a', 'b');
field.set(test, newStr);
}
}
System.out.println(test.toString());
}
}
Method类
*Method类代表某个类的成员方法
*得到类中的某个方法
例子:Method method = Class.forName("java.lang.String").getMethod("charAt",int.class);
*调用方法:
通常方法System.out.println(str.charAt(2));
反射方法System.out.println(method.invoke(str,1));
下面用一个小例子来展示具体用法
示例:把”abcd”的字符串的第二个字符输出要求使用反射方法
import java.lang.reflect.Method;
public class TestReflect1 {
/**
* @param args
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
//创建自定义点的对象
String str ="abcd";
//实例化方法传入的参数为要调用的方法名,后缀方法名要用到的参数类型
Method method = str.getClass().getMethod("charAt", int.class);
//调用方法输出结果
System.out.println(method.invoke(str, 1));
}
}
反射的作用->实现框架功能
*框架与框架要解决的核心问题
比如我做房子卖给用度住.由用户自己安装门窗和空调我做的就是框架,
用户需要我的框架,把门窗插入我提供的框架中,框架与工具有区别,
工具类被用户的类调用,而框架则调用用户提供的类
*框架要解决核心的问题
我在写框架时,你这个用户可能还在上小学,还不会写程序叱?
我写的框架程序怎么能调用你写的类(门窗呢)?
因为我在写程序时无法知道要被调用的类名,
所以在程序中无法直接new某个类的实例对象了,而要用反射方法来做
示例:要求用户写一个配置文件,配置文件中有类名,用户根据配置文件中的类名,来实例化对象,如(ArryList)并输出元素的值
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Properties;
public class TestReflect {
/**
* @param args
*/
public static void main(String[] args) throws Exception{
//读取配置文件
InputStream fis = new FileInputStream("config.properties");
//实例化属性对象
Properties pp = new Properties();
//把文件加载到属性对象中
pp.load(fis);
//关闭文件流,释放系统调用资源
fis.close();
//获得要调用的类名
String className = pp.getProperty("className");
//通过类名实例化类
Collection<String> cc = (ArrayList)Class.forName(className).newInstance();
cc.add("1");
cc.add("2");
cc.add("3");
cc.add("4");
cc.add("5");
cc.add("6");
//打印结果
for(String str:cc){
System.out.println(str);
}
}