学习了反射后,对其作用有个大致的理解:
1. 如果知道一个类的名称或者是它的实例对象,那么通过反射就可以把这个类中的方法和变量都获取到
2. 如果还知道这个类中的某个变量名,那么就可以把这个变量的当前值获取到
3. 如果明确知道这个类中的某个方法,那么也可以通过反射来调用这个方法
package demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/*
* java类用于描述一类事物的共性,该类事物有什么属性,没有什么属性
* 至于属性是什么值,则由这个类的实例对象来确定,不同的实例对象有不同的属性值。
*
* 而反射就是把java类中的各种成分映射成相应的Java类,
* 一个类中的每一成员都可以用相应的反射API类的实例对象来表示,通过调用Class类的方法可以得到这些实例对象
*/
public class ReflectDemo {
public static void main(String[] args) {
try {
// reflect();
// refConstructor();
// refField();
refMethod();
} catch (Exception e) {
e.printStackTrace();
}
}
//简单的反射类
private static void reflect() throws Exception{
String s = "abc";
//<? extends String>是泛型,表示该反射类的类型是String的子类,不写编译会有警告
Class<? extends String> clazz = s.getClass();
Class<String> clazz2 = String.class;//这个指定类型String
Class clazz3 = Class.forName("java.lang.String");//这个就没有用泛型,会有警告,但不报错
//通过比较可以看出,反射的对象其实是一个
System.out.println(clazz==clazz2);
System.out.println(clazz==clazz3);
//判断反射的类是否为基本类型
System.out.println("s 的反射类是否为基本类型"+clazz.isPrimitive());//String不是基本类型,所以它的实例对象反射类也不是基本类型
System.out.println("int 的反射类是否为基本类型"+int.class.isPrimitive());//int是基本类型
System.out.println("Integer 的反射类是否为基本类型"+Integer.class.isPrimitive());//Integer是int的封装对象,不是基本类型
//判断反射类是否为数组
System.out.println("int[] 的反射类是否为基本类型"+int[].class.isPrimitive());//int[]不是基本类型
System.out.println("int[] 的反射类是否为数组"+int[].class.isArray());//int[]是基本类型的数组
}
//构造函数的反射
private static void refConstructor() throws Exception{
//使用反射获得String中带有StringBuffer参数的构造方法
Constructor<String> cons = String.class.getConstructor(StringBuffer.class);
String s = cons.newInstance(new StringBuffer("abc"));
System.out.println(s+"中第二个字符是"+s.charAt(1));
}
//类中属性的反射
private static void refField() throws Exception{
ReflectPoint rp = new ReflectPoint(3, 5);
//通过反射获取ReflectPoint中的属性"a"
Field f_a = ReflectPoint.class.getDeclaredField("a");
Field f_b = ReflectPoint.class.getDeclaredField("b");
//因为"a"在ReflectPoint类中是私有的,所以这里需要"暴力反射"一下,强行获取私有属性的值
f_a.setAccessible(true);
//Field的get()方法,参数是某类的实例对象,返回值就是那个实例中该属性的值(注意:因为是用反射获取的值,所以返回类型是Object)
String a = f_a.get(rp).toString();
String b = f_b.get(rp).toString();
System.out.println("ReflectPoint中属性a的值是"+a);
System.out.println("ReflectPoint中属性b的值是"+b);
//Field的set()方法,参数一个是某类的实例对象,一个是修改的值
f_b.set(rp,0);
b = f_b.get(rp).toString();
System.out.println("ReflectPoint中属性b修改后的值是"+b);
}
//类中方法的反射
private static void refMethod() throws Exception{
String s = "abc";
//使用反射获得String中CharAt()方法,参数第一个是方法名,第二个是反射方法参数类型的class(如下也可以是int.class)
Method m_charAt = String.class.getMethod("charAt", Integer.TYPE);
//使用通过反射获得的方法,通过invoke()方法调用,第一个参数是带有反射方法的实例,第二个对象是方法
char c = (Character) m_charAt.invoke(s, 1);
System.out.println(s+"中第二个字符是"+c);
//反射调用main()方法
Method m_main = ReflectPoint.class.getMethod("main",String[].class);
//因为main()方法是静态的,所以第一个参数为空
m_main.invoke(null, (Object)new String[]{});
}
}
//为演示反射提供的简单测试类
class ReflectPoint{
private static int a;
public static int b;
public ReflectPoint(int a,int b){
this.a = a;
this.b = b;
}
public static void main(String[] args) {
System.out.println("ReflectPoint");
}
}
下面应用反射技术,来感受一下框架是怎样运行的
package demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Properties;
/*
* 反射的应用:这里利用反射模拟框架的效果
* 框架就是根据配置文件中获取的类的信息,然后通过反射来使用配置进来的类
*/
public class ReflectDemo2 {
public static void main(String[] args) {
InputStream in = null;
try {
// 获取配置文件的流有多种途径,问题主要集中在配置文件路径的选择上(假设配置文件和类在一个目录下)
// 第一种就是获取类的加载器的位置,然后再写上相对路径,获取配置文件
// in = ReflectDemo2.class.getClassLoader().getResourceAsStream("demo/config.properties");
// 第二种就是获取类所在目录,然后写入相对路径,获取配置文件
// in = ReflectDemo2.class.getResourceAsStream("config.properties");
//加载配置文件,这就相当于框架的配置文件
//这种获取类的方式使用的相对于工程的相对路径
in = new FileInputStream(new File("src/demo/config.properties"));
Properties prop = new Properties();
prop.load(in);
//根据配置的类名加载类
String conllectionClass = prop.getProperty("conllectionClass");
Collection<String> coll = (Collection<String>)Class.forName(conllectionClass).newInstance();
//使用生成的类
coll.add("A");
coll.add("B");
coll.add("A");
coll.add("C");
System.out.println(coll.toString());
} catch (Exception e) {
e.printStackTrace();
}finally{
if(in!=null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
配置文件内容:config.properties(和类放在一个文件夹下)
conllectionClass=java.util.HashSet