黑马程序员_java高级篇初识框架+Beanutil Day12

 

   ----------------------ASP.Net+Android+IOS开发.Net培训、期待与您交流! --------


                                                        黑马程序员_java高级篇初识框架+Beanutil Day12

 

 

#用反射机制做框架#


当我们写好一个类,给别人用时,不一定能用,我们怎样才能保证别人用我们类的方便性呢?

看一个例子:

还是上一篇文章的例子,不过这回我们改了。


这个config.properties文件里放了className=’java.lang.ArrayList’

 
       Properties prop=new Properties();
       BufferedInputStream br=new BufferedInputStream(new FileInputStream("config.properties"));
       prop.load(br);
       //告诉window关闭资源这个对象的关联的资源,自己再被回收
       br.close();
       String className=(String)prop.get("className");
       System.out.println(className);
       Collection coll=(Collection)Class.forName(className).newInstance();
       Reflectpointrp=new Reflectpoint(3,3);
       coll.add(rp);
       coll.add(new Reflectpoint(3,4));
       coll.add(new Reflectpoint(3,5));
       coll.add(rp);
       coll.add(new Reflectpoint(3,5));
       System.out.println(coll.size());
 


当我们这样做的时候,我们就可以只需要改配置文件里的值,不需要修改代码了,String className=(String)prop.get("className");这个语句就是来获得我们在文件里放的java.lang.ArrayList,我们将它改为java.lang.HashSet,当获得以后,我们通过Class.forName(className).newInstance()反射得到一个对象,这样使用,比我们写死方便,同时框架中有很多也是这样写的。

 

#对于配置文件的纠结#


这个问题都是有这个语句引用出来的!

BufferedInputStream br=newBufferedInputStream(new FileInputStream("config.properties"));
 


其中文件路径我们要用绝对路径,因为我们拷贝工程给某人时,只是class文件,我们可以把文件放在src目录下,这样才能使它与类在一起。同时里也可以建立一个包resource

下面有三种方案,都可以,第三种最方便。

 

 (一)

这样用相对路径可能找不到,但是绝对路劲也有问题,要getrealpath

BufferedInputStream br=newBufferedInputStream(new FileInputStream("config.properties"));


 (二)

千万要注意路径问题,如果cn/itcast/day1/confi改为/cn/itcast也会出错

 

这种只可以读,因为只有返回InputStream ,上面(一)的可以写因为他有OutputStream,

 

br=ReflectFile.class.getClassLoader().getResourceAsStream("cn/itcast/day1/config.properties");


(三)

其实直接提供了一套方法可以使用,因为我们按上面那种要先找到那个class在加载,加载后再调用,那还不如直接用提供一个方法,这方法聪明,只需要提供文件名

      

 InputStream br=ReflectFile.class.getResourceAsStream("config.properties");
      
 prop.load(br);

 //告诉window关闭资源这个对象的关联的资源,自己再被回收

   br.close();

 

#内省对类的值进行设置于操作(主要对javabean进行操作)#

如下:

       String propertyName="x";
       Reflectpoint rp=new Reflectpoint(3,4);
       PropertyDescriptor p=new PropertyDescriptor(propertyName,rp.getClass());
       //Method m=;
       Object retVal=p.getReadMethod().invoke(rp);
       System.out.println(retVal);


 

x是Reflectpoint类中定义的一个属性,int x,通过PropertyDescriptor

我们可以得到操作这个对象的对象,再通过这个对象找到set(),get()方法,这样就可以完成对类的值进行设置了。

上面只是调用了getReadMethod()读方法,同时我们也要注意写方法  Methodmx=p.getWriteMethod();mx.invoke(rp,7);大家注意invoke没有,当我们调用read时,invoke只要一个参数,因为读是调用了getX(),不需要传入参数,但是写方法是调用的

SetX(),要传入一个参数。

 

对javabean也来了解一下,他是一个满足规则特殊的java类。

满足如下的有一个Y属性,有set与get方法的特殊类。

public int getY() {
       return y;
    }
 
    public void setY(int y) {
       this.y = y;
    }
 


#BeauUtils的使用#

 

首先要下载两个类BeanUtils 与logging

 

初识Bean

BeanUtil工具更加方便的来操作对象的属性

BeanUtils.setProperty(rp,"x","9");这一个语句就可以完成上面三个语句的功能,我们注意x是int型的,为什么可以用字符串给它赋值呢,这个就是BeanUtils给我们在内部自动置换的,其实也就是将String转为int。对于另一个也可以实现同样的功能,但用这个与setProperty不一样,他的格式是非常明确的,不进行类型转换PropertyUtils.setProperty(rp,"x",9);

 Beanutil+logging下载

 

Bean对复杂属性的操作如下:

BeanUtils.setProperty(rp,"birth.time","999");

Birth是对象rp对应类中的一个属性,当我们用想要设定birth的值时,我们要注意,

Date是不是一个简单的类型,他也是一个类,要想set时间,我们必须得到Date的方法,

Date有一个setTime()方法,根据规则对应的属性是time,所以我们在使用时先找到birth属性,再一次找到类型的方法对应的属性time。

 

#注解(重要的JDK1.5新特性,反射不是)#

 

1,  简单了解注解

注解有三种,第一是当我们想要过时的方法照样能用,还要编译器不提醒,我们加上注解@SuppressWarnings(value={""}),第二种是这个方法已经过时,但是可以用,如果直接删掉,以前的人就会报错,所以我们用这种方法比较好,这时我们用@Deprecated。第三种重载@Override。

 

回顾前面有一点我们要注意,就是那个hashcode与equal,我们不能把equal里面的

 * Object不能改成我们的类名,如果我们改了,他就不会调用我们的方法。因为他接受的是object

 * 当你以为别人或你写代码会覆盖父类的代码,怎样呢,用注解。

 *

 * sun公司提供的基本注解:过时deprecate,覆盖override,已过时但不要提醒supresswarning

 

 

我觉得如果把两个使用类粘贴出来,构成注解分析更好。这里面有了注释,同时我们也可以更加清晰的看到各个类的配合。

 

 

注解接口:

package JavaBean;
 
importjava.lang.annotation.ElementType;
importjava.lang.annotation.Retention;
importjava.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
//在注解上加的注解叫元注解。
@Retention(RetentionPolicy.RUNTIME)
/*
 * 分为三个阶段java源文件RetentionPolicy.SOURCE-->class文件RetentionPolicy.CLASS-->内存中的字节码RetentionPolicy.RUNTIME
 * 在每一个阶段都有可能丢失
 */
 
//用于说明我们的注解用于哪里
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface Swaring1_1{
 
    public String color() default "bule";
    public String value();
    int[] a() default {23};
    test enumt() default test.MON;
    MetaAnction an() default @MetaAnction(val="ds");
//  WeekDay l() default WeekDay.SUN;
 
}


 

注解使用

package JavaBean;
 
import sun.util.calendar.BaseCalendar.Date;
@Swaring1_1(color="red",value="green",a={1})
public class SWarning {
 
    /**
     * @param args
     * jdk的新特性枚举,注解,记住反射不是
     */
    //这就是注解,一个注解也是一个类,我们用了就像新建一个对象
    @SuppressWarnings(value={""})
    @Swaring1_1("green")
    public static void main(String[] args) {
       // TODO Auto-generatedmethod stub
 
       //当我们有这种情况,提醒过时时,我们可以用注解来消除,我就是要用
       //过时的
       System.runFinalizersOnExit(true);
      
       //加入元注解
       if(SWarning.class.isAnnotationPresent(Swaring1_1.class))
       {
           Swaring1_1 sw=SWarning.class.getAnnotation(Swaring1_1.class);
           System.out.println(sw.color());
       }
      
    }
    //这个注解代表过时了,当我们用这个的时候,就是告诉用我们jar包的人
    //这个方法已经过时,但是可以用,如果直接删掉,以前的人就会报错,所以我们
    //用这种方法比较好
    @Deprecated
    public void show()
    {
       System.out.println("hihello");
    }
 
    /*
     * 回顾前面有一点我们要注意,就是那个hashcode与equal,我们不能把equal里面的
     * Object不能改成我们的类名,如果我们改了,他就不会调用我们的方法。因为他接受的是object
     * 当你以为别人或你写代码会覆盖父类的代码,怎样呢,用注解。
     *
     * sun公司提供的基本注解:过时deprecate,覆盖override,已过时但不要提醒supresswarning
     */
}
 


 

   ----------------------ASP.Net+Android+IOS开发.Net培训、期待与您交流! --------

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值