黑马程序员_Java基础加强(2)

来源:互联网 发布:淘宝返利网是怎么回事 编辑:程序博客网 时间:2024/06/03 15:56

android培训、java培训、期待与您交流!


Java基础加强-2

*******************************************************************************

反射与框架

l       框架与框架要解决的核心问题

Ø       我做房子卖给用户住,由用户自己安装门窗和空调,我做的房子就是框架,用户需要使用我的框架,把门窗插入进我提供的框架中。框架与工具类有区别,工具类被用户的类调用,而框架则是调用用户提供的类。

l       框架要解决的核心问题

Ø       因为在写才程序时无法知道要被调用的类名,所以,在程序中无法直接new 某个类的实例对象了,而要用反射方式来做。

l       综合案例

Ø       采用配置文件加反射的方式创建ArrayList和HashSet的实例对象,比较观察运行结果差异。

Ø       引入了elipse对资源文件的管理方式的讲解。

import java.io.*;

import java.util.*;

/  *利用反射技术使用运行时的类,反射技术开发框架原理 *  /

public class ReflectTest2 {

       public static void main(String[] args) throwsException{

            

              //一定要记住用完整的路径,但完整的路径不是硬编码。而是通过运算得出来的。

              //InputStream in= new FileInputStream("config.properties");

            

              //使用类加载器的方式管理配置和资源文件。

              //InputStream in =ReflectTest2.class.getClassLoader().getResourceAsStream("cn\\itcast\\day2\\config.properties");

            

              //相对主类所在的包的相对路径

              InputStream in =ReflectTest2.class.getResourceAsStream("config.properties");

              //如果是放在cn.itcast.resource包里,则就要使用该包的相对路径"resourse\\config.properties"

              //【总结】:加载配置和资源文件时,总会默认加载classpath里的路径,然后再其路径下在根据相对路径寻找文件

              //因此,资源文件一般放在eclipse的src目录或者子目录下。

            

              Properties props= new Properties();

              props.load(in);

              String className= props.getProperty("className");

 

              //要将泛型实例指定为Collection对象

              Collection coll= (Collection)Class.forName(className).newInstance();

              coll.add("java01");

             coll.add("java02");

             coll.add("java03");

             coll.add("java01");

            

             System.out.println(coll.toString());

       }

}

*******************************************************************************

内省——>了解JavaBean

l       JavaBean是一种特殊的Java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的字段,且方法名符合某种命名规则。

l       如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object,简称VO)。这些信息在类中用私有字段来存储,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问,大家觉得这些方法的名称叫什么好呢?JavaBean的属性是根据其中的setter和getter方法来确定的,而不是根据其中的成员变量。如果方法名为setId,中文意思即为设置id,至于你把它存到哪个变量上,用管吗?如果方法名为getId,中文意思即为获取id,至于你从哪个变量上取,用管吗?去掉set前缀,剩余部分就是属性名,如果剩余部分的第二个字母是小写的,则把剩余部分的首字母改成小的。

Ø       setId()的属性名àid

Ø       isLast()的属性名àlast

Ø       setCPU的属性名是什么?àCPU

Ø       getUPS的属性名是什么?àUPS

总之,一个类被当作javaBean使用时,JavaBean的属性是根据方法名推断出来的,它根本看不到java类内部的成员变量。

l       一个符合JavaBean特点的类可以当作普通类一样进行使用,但把它当JavaBean用肯定需要带来一些额外的好处,我们才会去了解和应用JavaBean!好处如下:

Ø       在Java EE开发中,经常要使用到JavaBean。很多环境就要求按JavaBean方式进行操作,别人都这么用和要求这么做,那你就没什么挑选的余地!

Ø       JDK中提供了对JavaBean进行操作的一些API,这套API就称为内省。如果要你自己去通过getX方法来访问私有的x,怎么做,有一定难度吧?用内省这套api操作JavaBean比用普通类的方式更方便。

综合案例:

l       用eclipse自动生成ReflectPoint类的setter和getter方法。

l       直接new一个PropertyDescriptor对象的方式体现JavaBean API的价值。

l       用eclipse将读取属性和设置属性的直接代码分别抽取成方法:

Ø       只要调用这个方法,并给这个方法传递了一个对象、属性名和设置值,它就能完成属性修改的功能。

Ø       得到BeanInfo最好采用“obj.getClass()”方式,而不要采用“类名.class”方式,这样程序更通用。

l       采用遍历BeanInfo的所有属性方式来查找和设置某个RefectPoint对象的x属性。在程序中把一个类当作JavaBean来看,就是调用IntroSpector.getBeanInfo方法, 得到的BeanInfo对象封装了把这个类当作JavaBean看的结果信息。

import java.beans.PropertyDescriptor;

import java.lang.reflect.*;;

/  *内省的简单应用方式*  /

public class IntroSpectorTest1 {

       public static voidmain(String[] args) throws Exception{         

              ReflectPoint rp= new ReflectPoint(3,5);

            

              //利用给定的属性名对getter和setter进行调用

              //利用PropertyDescriptor设置属性描述,构造方法参数为属性名及所在类

              String prop ="x";

             PropertyDescriptor pd = new PropertyDescriptor(prop,rp.getClass());

            

              //以下get/setProperty方法利用Refactor进行重构,导出方法-->Extract methood

              Object retValue= getProperty(rp, pd);

             System.out.println(retValue);

            

              Object setValue= 7;

              setProperty(rp,pd, setValue);

             System.out.println(getProperty(rp,pd));

       }

     

       / *PropertyDescriptor的getReadMethod以及getWriteMethod方法返回一个Method类型对象

       / *需要用invoke方法进行对应setter getter方法的调用

        ** /

       public static voidsetProperty(Object rp, PropertyDescriptor pd,

                     ObjectsetValue) throws IllegalAccessException,

                    InvocationTargetException {

            

              MethodsetMethod  = pd.getWriteMethod();

             setMethod.invoke(rp, setValue);

       }

 

       public static ObjectgetProperty(Object rp, PropertyDescriptor pd)

                     throwsIllegalAccessException, InvocationTargetException {

            

              MethodgetMethod  = pd.getReadMethod();

              Object retValue= getMethod.invoke(rp);

              return retValue;

       }

 

}

    / *使用BeanInfo方法

     *

     * * /

    public static ObjectgetProperty(Object rp, String prop)

throws IllegalAccessException, InvocationTargetException,IntrospectionException {

         

       BeanInfo beanInfo =Introspector.getBeanInfo(rp.getClass());

       PropertyDescriptor[]pds = beanInfo.getPropertyDescriptors();

       Object refValue =null;;

       for (PropertyDescriptorpd_x : pds) {

           if(pd_x.getName().equals(prop)) {

              Method getMethod= pd_x.getReadMethod();

              refValue =getMethod.invoke(rp);

              break;

           }

       }

       return refValue;

    }

*******************************************************************************

BeanUtils工具包

l       用eclipse如何加入jar包,先只是引入beanutils包不行,还需引入logging包。

(建立一个lib)

l       在前面内省例子的基础上,用BeanUtils类先get原来设置好的属性,再将其set为一个新值。

Ø       get属性时返回的结果为字符串,set属性时可以接受任意类型的对象,通常使用字符串。

l       用PropertyUtils类先get原来设置好的属性,再将其set为一个新值。

Ø       get属性时返回的结果为该属性本来的类型,set属性时只接受该属性本来的类型。

l       去掉JavaBean(ReflectPoint)的public修饰符时,BeanUtils工具包访问javabean属性时出现的问题。

 

/ *使用BeanUtils方法(自己下载包:beanutils和logging):

        *System.out.println(BeanUtils.getProperty(rp,prop));

        * BeanUtils.setProperty(rp,prop,"9");  //以String类型进行设置

        *System.out.println(BeanUtils.getProperty(rp,prop));

        *

        * 当存在对象类型的属性:private Date birthday = new Date();

        * 则需要用属性链进行设置,用属性链进行查看

        *BeanUtils.setProperty(rp,"birthday.time","12000");

        *System.out.println(BeanUtils.getProperty(rp,"birthday.time"));

        *

        * BeanUtils是以字符串String类型对属性值进行操作,PropertyUtils是以属性值本身类型进行操作

        *PropertyUtils.setProperty(rp,prop,9);

        *System.out.println(BeanUtils.getProperty(rp,prop));

* //返回Integer值

        *

        * java7的新特性:Map定义

        * Map map ={name:"yun",age:20};

        * 通过describe和populate两个方法,在bean对象和map对象时间进行转换。

        * * /

*******************************************************************************

Java注解(java.lang.annotation)

l       通过@SuppressWarnings的方法忽略某个区域内的warnings:

Ø         指示应该在注释元素(以及包含在该注释元素中的所有程序元素)中取消显示指定的编译器警告。注意,在给定元素中取消显示的警告集是所有包含元素中取消显示的警告的超集。例如,如果注释一个类来取消显示某个警告,同时注释一个方法来取消显示另一个警告,那么将在此方法中同时取消显示这两个警告。

l       @Deprecated:

Ø         用 @Deprecated 注释的程序元素,不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择。在使用不被赞成的程序元素或在不被赞成的代码中执行重写时,编译器会发出警告。但不影响之前版本的使用

l       @Override

Ø       表示一个方法声明打算重写超类中的另一个方法声明。如果方法利用此注释类型进行注解但没有重写超类方法,则编译器会生成一条错误消息。

l       总结:

Ø       注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记,以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事。标记可以加在包,类,字段,方法,方法的参数以及局部变量上。

Ø       看java.lang包,可看到JDK中提供的最基本的annotation。

 

【自定义注解】:

l       定义一个最简单的注解:public @interface MyAnnotation {}

l       把它加在某个类上:@MyAnnotation public class AnnotationTest{}

l       用反射进行测试AnnotationTest的定义上是否有@MyAnnotation

l       根据反射测试的问题,引出@Retention元注解,其三种取值:RetetionPolicy.SOURCE、RetetionPolicy.CLASS、RetetionPolicy.RUNTIME;分别对应:

java源文件-->class文件-->内存中的字节码。

Ø       思考:@Override、@SuppressWarnings和@Deprecated这三个注解的属性值分别是什么?(SOURCE、SOURCE、RUNTIME)

l       @Target元注解

Ø       Target的默认值为任何元素。

Ø       设置Target等于ElementType.METHOD,原来加在类上的注解就报错了,改为用数组方式设置{ElementType.METHOD,ElementType.TYPE}就可以了。

l       元注解以及其枚举属性值不用记,只要会看jdk提供那几个基本注解的API帮助文档的定义或其源代码,按图索骥即可查到,或者直接看java.lang.annotation包下面的类。

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

importjava.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

/ *使用元注解对自定义注解进行标注

 * RetentionPolicy是一个枚举类,有三个枚举值常量SOURCE CLASS RUNTIME

 * * /

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.METHOD,ElementType.TYPE}) //表示任意类型的元素,不一定是注解在方法上

public @interface MyAnnotation {

}

---------------------------------------------------------------------

import com.sun.xml.internal.bind.v2.schemagen.xmlschema.Annotation;

@MyAnnotation

public class AnnotationTest {

    public static voidmain(String[] args) {

      if(AnnotationTest.class.isAnnotationPresent(MyAnnotation.class)){

           MyAnnotation myAnn= (MyAnnotation)AnnotationTest.class.getAnnotation(MyAnnotation.class);

          System.out.println(myAnn);

       } 

    }

}

 

【Type接口】:

Class类实现了该接口,并且如Enum、interface、@interface等,虽然不属于Class类,但都是java中的一种类型,因此都实现了接口Type。该接口的概念更宽泛。

 

【注解的基本属性和高级属性】:

l       定义基本类型的属性和应用属性:

Ø       在注解类中增加String color();

Ø      @MyAnnotation(color="red")

l       用反射方式获得注解对应的实例对象后,再通过该对象调用属性对应的方法

Ø       MyAnnotation a

Ø       =(MyAnnotation)AnnotationTest.class.getAnnotation(MyAnnotation.class);

Ø      System.out.println(a.color());

Ø       可以认为上面这个@MyAnnotation是MyAnnotaion类的一个实例对象

l       为属性指定缺省值:

Ø       String color() default"yellow";

l       value属性:

Ø       String value() default"zxx";

Ø       如果注解中有一个名称为value的属性,且你只想设置value属性(即其他属性都采用默认值或者你只有一个value属性),那么可以省略value=部分,例如:@MyAnnotation("lhm")。

 

l       数组类型的属性

Ø       int [] arrayAttr()default {1,2,3};

Ø      @MyAnnotation(arrayAttr={2,3,4})

Ø       如果数组属性中只有一个元素,这时候属性值部分可以省略大括号

l       枚举类型的属性

Ø       EnumTest.TrafficLamplamp() ;

Ø      @MyAnnotation(lamp=EnumTest.TrafficLamp.GREEN)

l       注解类型的属性:

Ø       MetaAnnotationannotationAttr() default @MetaAnnotation("xxxx");

Ø      @MyAnnotation(annotationAttr=@MetaAnnotation(“yyy”) )

Ø       可以认为上面这个@MyAnnotation是MyAnnotaion类的一个实例对象,同样的道理,可以认为上面这个@MetaAnnotation是MetaAnnotation类的一个实例对象,调用代码如下:

       MetaAnnotation ma=  myAnnotation.annotationAttr();

      System.out.println(ma.value());

l       注解的详细语法可以通过看java语言规范了解,即看java的language specification。

 

*******************************************************************************


0 0
原创粉丝点击