传智播客Java培训---反射、注解

反射机制

特点:动态获取类以及类中成员。

通常在程序扩展时,会使用父类或者接口完成,其实就是多态。

在这种情况,运行时,还是需要给其传递一个自定义的子类对象。需要自己new来完成。

虽然修改动作已经很少了,但还是需要修改部分细节。

  interface Inter{void show();}

  class Demo{

   void function(Inter in){

    in.show();

   }

  }

  main(){

   Demo d = new Demo();

   d.function(new InterImpl());//这里需要传入一个新的后期子类对象。

  }

  class InterImpl implements Inter{

   public void show(){}

  }

  能不能完全不改动源程序,就可以运行后期子类内容呢?

  我们可以对外暴露一个配置文件,该配置文件可以是键值对形式的.ini文件、xml文件。

  通过反射机制动态获取子类字节码文件,并动态创建其对象。

  main(){

   Demo d = new Demo();

   BufferdReader bufr = new BufferedReader(new FileReader("config.txt"));

   String className = bufr.readLine();

   Class clazz = Class.forName(className);

   Inter in = (Inter)clazz.newInstance();

   d.function(in);

  }

  通过上面示例,可以看到反射进一步增强了程序的扩展性。

 

Class 类的实例表示正在运行的 Java 应用程序中的类和接口,它将字节码文件封装成了对象,类字段,方法,构造函数也被封装为对象,我们可以通过对象效用获取类中的字段方法和构造函数。

例:

package cn.itcast.test;

public class Person {

    private String name;

    private int age;

    private String address;

    public Person(String name, int age, String address) {

       super();

       this.name = name;

       this.age = age;

       this.address = address;

    }

    public void show(String name,int age){

       System.out.println(name+age+address+"---");

    }

}

 

package cn.itcast.reflect;

import java.lang.reflect.Constructor;

import java.lang.reflect.Method;

import cn.itcast.test.Person;

public class ReflectDemo {

public static void main(String[] args) throws Exception{

//获取指定类对象

       Class clazz = Class.forName("cn.itcast.test.Person");

       //Person类中没有无参构造函数,必须获取带参数构造函数进行初始化

       Constructor cons = clazz.getConstructor(String.class,int.class,String.class);

       //使用带参数的构造函数进行初始化

       Person p = (Person)cons.newInstance("zhangsan",22,"shandong");

       //获取Person类中的方法对象

       Method method = clazz.getMethod("show",String.class,int.class);

       /*

       Method[] methods = clazz.getDeclaredMethods();//可以获得所有声明过的方法,包括私有和静态方法

       methods = clazz.getMethods(); //不能获得私有和静态方法,但可获取从父类继承来的方法

       */

       //调用方法对象的invoke()方法

       method.invoke(p,"zhang",25);

    }

}

 

 

注解:定义标记简化书写。
 特点:
 将运行时出现问题体现编译时期:@Override
 它就是程序中的一个标记。
 定义格式:
 @interface 注解名称{
  //注解属性。
  属性类型 属性名();
  属性类型  属性名() default 类型对应的值;
 }
 注解内部有一个默认的属性value。
 属性类型:8种基本数据类型,String ,Class,数组,enum,Annotation
 注解可以加载包,类,成员,局部。
 
 注解有一个声明周期:
 是通过一个注解来体现的。
 @Retention(RetentionPolicy.RUNTIME)
 RetentionPolicy是一个枚举类型。
 有三个值:
 CLASS:默认的。编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释
 RUNTIME:编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取
 SOURCE:编译器要丢弃的注释
 注解如何来获取:
 通过反射的形式。类的注解获取类所属Class对象。
 方法注解要获取Method对象。    
 什么时候用注解呢?
 配置信息较为简单可以将其配置在注解上。
 方便于类在反射的是使用该配置信息。这样就不用在对配置信息文件进行读写操作。
 注解也有一定义的局限性。
 将值直接定义在程序内部。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值