Java反射机制

    |     2015年3月30日   |   Java面向对象高级特性   |     0 条评论   |    1092

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

反射(背景):

什么是反射?有什么用?
先了解一些基本的概念:运行时,编译时,编译型,解释型,类加载器,动态加载类
什么是编译?
将原程序翻译成计算机语言,就是二进制代码,在java中是将.java文件也就是源程序翻译成.class的字节码
什么是编译时?
将原程序翻译成计算机语言的过程中,将.java翻译为.class文件的过程
什么是运行时?
就是在启动这个程序的时候,在java中是,类加载器加载.class文件,并交给jvm处理
什么是编译型语言?
将原程序一次性全部转换为二进制代码,然后执行程序
什么是解释型语言?
转换一句,执行一句,java是既编译又解释的语言
编译型语言和解释型语言的区别:编译型语言效率高,依赖于编译器,但是跨平台差,解释型的效率低,依赖于解释器,但跨平台强
什么是类加载器?
类加载器就是JVM中的类装载器,作用就是将编译好的.class字节码运到检查器进行安全检查的,检查通过后开始解释执行
什么是运行时动态加载类?
反射就是可以将一个程序(类)在运行的时候获得该程序(类)的信息的机制,也就是获得在编译期不可能获得的类的信息,因为这些信息是保存在Class对象中的,而这个Class对象是在程序运行时动态加载的
它就是可以在程序运行的时候动态装载类,查看类的信息,生成对象,或操作生成对象。类在运行的时候,可以得到该类的信息,并且 可以动态的修改这些信息,自己能看到自己,跟照镜子一样,class对象是在运行的时候产生的,通过class对象操作类的信息是在运行时进行的,当运行 程序的时候,类加载器会加载真正需要的类,什么是真正需要的呢?就是该类真正起作用,如:有该类的对象实例,或该类调用了静态方法属性等
反射的作用第一,远程方法调用,第二,通过容器得到组件的对象

理解Class类

1.在面向对象的世界里,万事万物皆对象。
java语言中,静态的成员、普通数据类型类是不是对象呢?
类是不是对象呢?类如果是对象又是谁的对象?
类是对象,类是java.lang.Class类的实例对象。
2.这个对象如何表示?
得到Class对象有三种方法如下:

如何实现反射呢?

得到Class对象
三种方式得到Class对象:

1.调用对象的getClass方法,返回该对象的Class对象; Class c=Object.getClass();
2.Class.forName(“类的名字”);  Class c=Class.forName (“…”);
3.Class c=类名.class;  Class c=String.class;

java.lang.reflect包下的类

Method类:提供一个类的方法的信息以及访问类的方法的接口。

Constructor类:提供一个类的构造函数的信息以及访问类的构造函数的接口。

Field类:提供一个类的域的信息以及访问类的域的接口。

使用Class创建对象

Class c= Class.forName("类的全名");

Object o=c.newInstance();

Test1 t = Test1.class.newInstance();

找出class属于那个包

Class c=Test1.class;

Package p;

p=c.getPackage();

 

调用方法

Class c = Class.forName(“类的全名”);//获得访问类的对象

Object obj=c.newInstance();//获得被访问类的实例对象

Class[] cs=new Class[]{String.class};//设置参数类型

Method ff=c.getMethod(“setName”,cs);//得到参数匹配的方法

Object[] values=new Object[]{“你好”};//设置需要传递的值 ff.invoke(obj,values);//映射

ff=c.getMethod("getName");

Object uuu= ff.invoke(obj);

 

动态调用有参数静态方法

Class c = Class.forName("类的全名");

Class[] cs=new Class[]{String.class};

Method m=c.getMethod("setName",cs);

Object[] o=new Object[]{"aaa"};

m.invoke(c,o);

 

得到属性和构造器及函数

Field[] ff = c.getDeclaredFields(); //无论静态还实体还私有皆可得到属性

Constructor[] ccc= c.getDeclaredConstructors(); //得到构造

Method[] mm=c.getDeclaredMethods();//无论静态还实体还私有皆可得到函数

 

调用构造器

Class c = Class.forName(“类的全名");

Class[] cs=new Class[]{String.class};

Constructor cc= c.getConstructor(cs);

Object[] o=new Object[]{"ssssssssssssss"};

cc.newInstance(o);
Method[] methods = classObj1.getMethods(); //获取所有成员方法包含 父类成员方法
Method[] methods = calze.getDeclaredMethods(); //获取类里所有成员方法
Field[] fields = claze.getDeclaredFields();//得到所有属性
Constructor[] constructors = claze.getConstructors();//得到所有构造方法

反射优缺点

优点:反射提高了程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创建和控制任何类的对象,无需提前硬编码目标类;

缺点: (1)性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用。 (2)使用反射会模糊程序内内部逻辑:程序员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术,因而会带来维护问题。 反射代码比相应的直接代码更复杂。

java中利用反射实现工厂模式

package com.scxh.java.factory;
interface Fruit { //水果接口
    public void eat() //吃水果
}
class Apple implements Fruit{ //定义苹果
    public void eat() {
       System.out.println("**吃苹果。");
    }
}
class Orange implements Fruit{
    public void eat() {
        System.out.println("**吃橘子。");
    }
}
class Factory{
   public static Fruit getInstance(String className){
      Fruit fruit = null
      try{
         fruit = (Fruit) Class.forName(className).newInstance()
      }catch(Exception e ){
         e.printStackTrace()
       }
      return fruit
   }
}
public class FactoryDemo{
   public static void main(String args[]){ //通过工厂类取得接口实例,传入完整的包.类名称
      Fruit f = Factory.getInstance("com.scxh.java.factorydemo.Apple")
         if(f!=null){ //判断是否取得接口实例
            f.eat()
         }
      }
}

反射工具类获取指定类的属性、方法,构造方法

/**
* 反射机制实现: 打印指定类的属性、方法,构造方法
*
*
* @author zhou.sir
*
*/

public class ReflectUtil {
/**

输出结果:
String name
int age
int id
String sex
Student()
Student(String int int String )
String toString()
void playeGame()
void makeFriend()
void learn()

*/
public static void main(String[] args) throws ClassNotFoundException {
showDeclaredParameter(getClaze());
showConstruction(getClaze());
showDeclaredMethods(getClaze());
}
/**
* 获取类对象
* @throws ClassNotFoundException
*/
public static Class<?> getClaze() throws ClassNotFoundException{
Class<?> classObj1 = Student.class;
// Class classObj2 = new Dog().getClass();
// Class classObj3 = Class.forName("com.scxh.java1601.object.ex01.test.Student");

// Log.d(classObj1.getName());

return classObj1;
}

/**
* 显示成员方法头
* @param calze
*/
public static void showDeclaredMethods(Class calze){
// Method[] methods = classObj1.getMethods(); //获取所有成员方法包含 父类成员方法
Method[] methods = calze.getDeclaredMethods(); //获取类里所有成员方法
for (int i = 0, n = methods.length; i < n; i++) {
String methodName = methods[i].getName();
Class returnType = methods[i].getReturnType();
Class[] parameterType = methods[i].getParameterTypes();

Log.v(subString(returnType.getName()) + " " + methodName + "(");
for (Class p : parameterType) {
Log.v(subString(p.getName()) + " ");
}
Log.d(")");
}
}

public static void showDeclaredParameter(Class claze){
Field[] fields = claze.getDeclaredFields();//得到所有属性
for(Field f : fields){
String fieldName = f.getName();
Class parameterType = f.getType();

String ptName = subString(parameterType.getName());
Log.d(ptName+ "\t"+fieldName);
}
}

public static void showConstruction(Class claze){
Constructor[] constructors = claze.getConstructors();//得到所有构造方法
for(Constructor c : constructors){
String constructorName = c.getName();

Class[] parameterType = c.getParameterTypes();
Log.v(subString(constructorName) + "(");
for (Class p : parameterType) {
Log.v(subString(p.getName()) + " ");
}
Log.d(")");
}
}

public static String subString(String str){
String ptName = str;
if(ptName.contains(".")){
int lastIndex = ptName.lastIndexOf(".");
ptName = ptName.substring(lastIndex+1);
}
return ptName;
}

}
转载请注明来源:Java反射机制
回复 取消