一、反射的基石(class类)
Java类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,则是由这个类的实例对象来确定的,不同的实例对象有不同的属性值。Java程序中的各个Java类,它们是否属于同一类事物,是不是可以用一个类来描述这类事物呢?这个类的名字就是Class。
Class类代表Java所有的类,它的各个实例对象又分别对应各个类在内存中的字节码(一个类在虚拟机中通常只有一份字节码);一个类被类加载器加载到内存中,占用一片存储空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以它们在内存中的内容是不同的。
获得各个字节码自己对应的实例对象( Class类型)的方式:
- 类名.class,例如,Person.class
- 对象.getClass(),例如,new Date().getClass()
- Class.forName("类名"),例如,Class.forName("java.util.Date");
二、反射的概念
反射就是把Java类中的各种成分映射成相应的java类
一个类中的每个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象后,来获得其中的变量,方法,构造方法,修饰符,包等信息。
三、反射的应用
1、
Constructor类( 代表某个类中的一个构造方法)
- 得到某个类所有的构造方法:
- 得到某一个构造方法
Constructor
constructor
=
Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);
//获得方法时要用到类型
- 创建实例对象
通常方式:String
str
= new String(new
StringBuffer("abc"));
反射方式:Constructor
ctt= String.class.getConstructor(StringBuffer.class);
String str = (String) ctt.newInstance(new
StringBuffer("abc"
));
//调用获得的方法时要用到上面相同类型的实例对象
- Class.newInstance()方法:
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。
2、
Field
类(代表某个类中的一个成员变量)
//定义一个类public class ReflectPoint {
private int x;
public int y;
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
}
ReflectPoint pt1 = new ReflectPoint(3,5);//创建一个对象指向ReflectPoint中的成员变量y;//fieldY不是对象身上的变量,而是类上,字段fieldY 代表的是y的定义Field fieldY = pt1.getClass().getField( "y");System. out.println(fieldY.get(pt1));//取私有变量Field fieldX = pt1.getClass().getDeclaredField("x" );fieldX.setAccessible( true);//暴力破解System. out.println(fieldX.get(pt1));
//设置y的值fieldY.set( pt1 , 6);
3、Method类(代表某个类中的一个成员方法)
- 得到类中的某一个方法:
Method charAt = Class.forName("java.lang.String").getMethod("charAt", int.class);
-
调用方法:
通常方式:System.out.println(str.charAt(1));
反射方式://getMethod 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
Method methodCharAt = String. class .getMethod( "charAt" , int . class );
System. out .println(methodCharAt.invoke(str1, 1));
如果传递给
Method
对象的
invoke()
方法的第一个参数为
null
,说明该
Method
对象对应的是一个静态方法!
调用main方法://运行时要带com.itcast.day1.TestArguments参数,通过字符串,得到类的字节码,得到main方法
String startingClassName = args[0];//Class.forName返回与带有给定字符串名的类或接口相关联的 Class 对象Method mainMethod = Class.forName(startingClassName ).getMethod( "main" , String[]. class );mainMethod.invoke( null , new Object[]{ new String[]{ "aaa" , "bbb" , "ccc" }});mainMethod.invoke( null ,(Object) new String[]{ "aaa" , "bbb" , "ccc" });
4、反射的作用à实现框架功能
- 框架与框架要解决的核心问题:
框架与工具类有区别,工具类被用户的类调用,而框架则是调用用户提供的类。
- 框架要解决的核心问题:
在程序中无法直接new
某个类的实例对象了,而要用反射方式来做。
config.properties
className=
java.util.HashSet
import
java.io.*;
import
java.util.Collection;
import
java.util.Properties;
import
com.itcast.day1.ReflectPoint;
public
class
ReflectTest {
public
static
void
main(String []args)
throws
Exception{
//加载配置文件(放在包下或者子包中),类加载器
//getRealPath();//***/*内部
//一定要记住用完整的路径,完整的路径不是硬编码,而是运算出来的。
//InputStream ips = new FileInputStream("config.properties");
//InputStream ips = ReflectTest.class.getClassLoader().getResourceAsStream("config.properties");
//InputStream ips = ReflectTest.class.getResourceAsStream("config.properties");
InputStream ips = ReflectTest.
class
.getResourceAsStream(
"/config.properties"
);
Properties props =
new
Properties();
//创建一个无默认值得空属性列表。
props.load(ips);
ips.close();
//用指定的键在此属性列表中搜索属性
String className = props.getProperty(
"className"
);
Class clas = Class.forName (className);
Collection collections = (Collection) clas.newInstance();
//Collection collections = new HashSet();
ReflectPoint p1 =
new
ReflectPoint(3,3);
ReflectPoint p2 =
new
ReflectPoint(5,5);
ReflectPoint p3 =
new
ReflectPoint(3,3);
collections.add(p1);
collections.add(p2);
collections.add(p3);
System.
out
.println(collections.size());
}
}
|