能够分析能力的程序成为反射,通俗的来讲就是能够通过运行时的类名获取类的全部信息。反射机制可以用来干以下的事情:
1、在运行时分析类的能力
2、在运行时查看对象,例如,编写一个toString()方法供所有类使用
3、实现通用的数组操作代码
4、利用Method对象,这个对象很像C++中的函数指针
下面来说一说他的底层实现原理:
在程序运行期间,JVM始终对所有的对象都有跟踪,并且将其所有信息存入一个类型为Class的对象中,选择对应的方法进行执行,即在程序运行时自动分析需要使用的类,并且通过newInstance()的方法动态的加载类。
反射的应用:
先看一下如下例子:
在没有使用反射时,每次增加一个水果都需要修改Factory中的代码,这样会很麻烦的
interface fruit{
public abstract void eat();
}
class Apple implements fruit{
public void eat(){
System.out.println("Apple");
}
}
class Orange implements fruit{
public void eat(){
System.out.println("Orange");
}
}
// 构造工厂类
// 也就是说以后如果我们在添加其他的实例的时候只需要修改工厂类就行了
class Factory{
public static fruit getInstance(String fruitName){
fruit f=null;
if("Apple".equals(fruitName)){
f=new Apple();
}
if("Orange".equals(fruitName)){
f=new Orange();
}
return f;
}
}
class hello{
public static void main(String[] a){
fruit f=Factory.getInstance("Orange");
f.eat();
}
}
使用反射:
interface fruit{
public abstract void eat();
}
class Apple implements fruit{
public void eat(){
System.out.println("Apple");
}
}
class Orange implements fruit{
public void eat(){
System.out.println("Orange");
}
}
class Factory{
public static fruit getInstance(String ClassName){
fruit f=null;
try{
f=(fruit)Class.forName(ClassName).newInstance();
}catch (Exception e) {
e.printStackTrace();
}
return f;
}
}
class hello{
public static void main(String[] a){
fruit f=Factory.getInstance("Reflect.Apple");
if(f!=null){
f.eat();
}
}
}
这样一来,我们就不用在每一次增加水果种类时修改Factory类,由此可以看到反射的好处,那么问题来了,为什么不在任何地方都使用反射呢,这是因为,反射虽然节省了操作,但是他所占用的资源开销是很大的,因此我们要根据实际情况使用反射。
下面来说一下反射的具体使用方法:
java.lang.reflect包中有三个类Filed、Method、Constructor分别用于描述类的域、方法、构造器。这三个类都有一个getName()的方法,用来返回项目的名称。此外三个类中都有一个getModifiers()方法,用来分析访问修饰符使用情况。
获得构造函数的方法
Constructor getConstructor(Class[] params)//根据指定参数获得public构造器
Constructor[] getConstructors()//获得public的所有构造器
Constructor getDeclaredConstructor(Class[] params)//根据指定参数获得public和非public的构造器
Constructor[] getDeclaredConstructors()//获得public的所有构造器
获得类方法的方法
Method getMethod(String name, Class[] params),根据方法名,参数类型获得方法
Method[] getMethods()//获得所有的public方法
Method getDeclaredMethod(String name, Class[] params)//根据方法名和参数类型,获得public和非public的方法
Method[] getDeclaredMethods()//获得所以的public和非public方法
获得类中属性的方法
Field getField(String name)//根据变量名得到相应的public变量
Field[] getFields()//获得类中所以public的方法
Field getDeclaredField(String name)//根据方法名获得public和非public变量
Field[] getDeclaredFields()//获得类中所有的public和非public方法