黑马程序员_高新技术3(JavaBean复杂操作,注解Annotation,泛型应用Generic)

时间:2023-02-18 13:55:03

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

一.JavaBean


1.内省:英文是Intorspector ,它主要用于对JavaBean进行操作。
2.JavaBean:
1)JavaBean是一种特殊的java类,主要用于传递数据信息,这种java类中的方法主要用于访问私有的
  字段,且方法名符合某种命名规则。
2)如果要在两个模块之间传递多个信息,可以将这些信息封装到一个JavaBean中,这种JavaBean的实例对象
     通常称之为值对象(Value Object,简称VO)。这些信息在类中用私有字段来存储,用set()和get()
  方法来设置和获取。
 3)通过提供的set和get方法就知道属性名,一个类被当作JavaBean使用时,JavaBean的属性是根据方法名
  推断出来的,它根本看不到java类内部的成员变量。如果第二个字母是小写的,则把第一个字母变成小写的。
4)符合JavaBean特点的类可以当做一个JavaBean来使用,比普通类操作更方便,快捷。


3.对JavaBean的简单内省操作

代码示例:  
[java] view plaincopy
  1. <span style="font-size:18px;">ReflectPoint pt1 = new ReflectPoint(3,5);  
  2. String propertyName = "x";  
  3. PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass());  
  4. Method methodGetX =pd.getReadMethod();  
  5. methodGetX.invoke(pt1);</span>  


4对JavaBean的复杂内省操作
代码示例:  
[java] view plaincopy
  1. <span style="font-size:18px;">ReflectPoint pt1 = new ReflectPoint(3,5);  
  2. String propertyName = "x";  
  3. BeanInfo  beanInfo = Introspector.getBeanInfo(pt1.getClass());  
  4.   PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();  
  5.   for(PropertyDescriptor pd : pds)  
  6.   {  
  7.         if(pd.getName().equals(propertyName){  
  8.     Method methodGetX = pd.getReadMethod();  
  9.                 methodGetX.invoke(pt1);  
  10.         }  
  11.     }</span>  


5.PropertyUtils和BeanUtils的区别;

  BeanUtils接收返回的都是String类型,可自动完成属性的类型转换。

  PropertyUtils是以属性本身的类型进行操作。


6.java7的新特性:
  Map map = {name:"lisi",age:18};
  BeanUtils.setProperty(map,"name","zhangsan");



二.注解Annotation


1.注解的定义和作用
   1)注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记。java编译器,开发工具,
  和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应
  的事。标记可以加在包,类,字段,方法,方法的参数以及局部变量上。
   2)一个注解就是一个类,使用一个注解就相当于创建了一个注解类的实例对象。

2.java提供的几个基本注解
  1)@SuppressWarnings压制警告注解
   使提示不再出现。如:@SuppressWarnings("deprecation")//不再提示过时
  2)@Deprecated使过时注解
   标识某个方法或类等已过时,以告诉新人以后尽量不要再使用该方法,同时又 不会影响以前的老程序。
  3)@Override覆盖注解
   在子类覆盖父类方法时,将非法的覆盖标识出来(或使不正确的覆盖报错),以便修正。

3.注解的应用结构图
  注解类
  @interface A
  {
  }

  应用了"注解类"的类
  @A
  class B
  {
  }

  对"应用了注解类的类"进行反射操作的类
  class C
  {
   B.class.isAnnotionPresent(A.class);
   A a = B.class.getAnnotion(A.class);

  }


4.注解的生命周期
   java源文件--->class文件--->内存中的字节码

   @Retention元注解可定义注解的存在阶段。其取值有三个:
   RetetionPolicy.SOURCE,RetetionPolicy.CLASS,Retetionpolicy.RUNTIME(保留到运行期间)
   
   几个基本注解对应的阶段:
   SuppressWarnings --- SOURCE
   Override --- SOURCE
   Deprecated --- RUNTIME  (RUNTIME的类型为:Enum RetentionPolicy的字段)

5.JDK1.5以后出现的类型TYPE定义包括:class,interface,@interface,Enum等
 Type比class更加精准 Class的父类是interface Type(java.lang.reflect包)。


6.枚举ElementType(java.lang.annotation )

  1)程序元素类型。此枚举类型的常量提供了 Java 程序中声明的元素的简单分类。 
  这些常量与Target 元注释类型一起使用,以指定在什么情况下使用注释类型是合法的
  2)枚举常量摘要 
  ANNOTATION_TYPE 
      注释类型声明 
  CONSTRUCTOR 
      构造方法声明 
  FIELD 
      字段声明(包括枚举常量) 
  LOCAL_VARIABLE 
      局部变量声明 
  METHOD 
      方法声明 
  PACKAGE 
      包声明 
  PARAMETER 
      参数声明 
  TYPE 
      类、接口(包括注释类型)或枚举声明 
如:
   @Target(ElementType.METHOD):应用在方法上
   @Target({ElementType.METHOD,ElementType.TYPE}):应用在方法和类上

7.注释的各种属性:
1)定义基本属性和应用属性
  String color();---->@MyAnnotation(color="red");
  2)数组类型的属性
  int[] arrayAttr() default {1,5,2};--->@MyAnnotation(arrayAttr={5,8,9});
  若数组属性中只有一个元素,属性值部分可以省略大括号
  3)枚举类型的属性
  EnumTest.TrafficLamp lamp();--->@MyAnnotation(lamp=EnumTest.TrafficLamp.GREEN);
  4)注解类型的属性:
  MetaAnnotation annotationAttr() default @MetaAnnotation("xxxx");--->
  @MyAnnotation(annotationAttr=@MetaAnnotation("yyy"));
 5)value属性:
  String value() default "zxx";
  如果注解中有一个名称为value的属性,且你只想设置value属性(即其他属性都采用默认值或者你
  只有一个value属性),那么可以省略value=部分,如:@MyAnnotation("1hm");


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

  MyAnnotation a = (MyAnnotation)AnnotationTest.class.getAnnotation(MyAnnotation.class);
  System.out.println(a.color());     可以认为@MyAnnotation是MyAnnotation类的一个实例对象

7)枚举和注解都是特殊的类,不能用new创建它们的实例对象,创建枚举的实例对象就是在其中增加元素。
  在程序中创建注解的实例对象,就是直接用@放上一个标记即可。



三.泛型Generic


1.理解泛型

   没有使用泛型时,只要是对象,不管是什么类型的对象,都可以存储进同一个集合中。使用泛型集合,可以将   一个集合中的元素限定为一个特定类型,集合中只能存储同一个类型的对象,这样更安全,并且当从集合获到     一个对象时,编译器也可以知道这个对象的类型,不需要对对象进行强制类型转换,这样更方便。
   注:在JDK1.5中,若按原来的方式将各种不同类型的数据装到一个集合中,编译器会报告unchecked警告。 
          泛型中,只有“引用类型”才能做为泛型方法的实际参数。

 深解泛型
   泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,
   编译器编译带类型说明的集合时会去除掉“类型”信息,使程序运行效率不受影响,对于参数化的
   泛型类型,getClass()方法的返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的类型
   信息,只要能跳过编译器,就可以往某个泛型集合中加入其它类型的数据。
 例如:用反射得到集合的add就读,再调用其add方法就可以添加一个其它类型的元素。


2.泛型内部原理及更深应该

  1)参数化类型与原始类型的兼容性:
  参数化类型可以引用一个原始类型的对象,编译报告警告,如:
  Collection<String> c = new Vector();//可不可以,就是编译器一句话的事。
  原始类型可以引用一个参数化类型的对象,编译报告警告,如:
  Collection c = new Vector<String>();//原来的方法接受一个集合参数,新的类型也要能传进去。
  2)参数化类型不考虑类型参数的继承关系:
  Vector<String> v = new Vector<Object>();//错误//不写<Object>没错,写了就是明知故犯
  Vector<Object> v = new Vector<String>();//也错误观点
  3)思考题:下面的代码会报错吗?  不会报错。
  Vector v1 = new Vector<String>();
  Vector<Object> v = v1;


3.泛型中的?通配符的扩展

  1)限定通配符的上边界:------Number及其子类
  Vector<? extends Number> x = new Vector<Integer>();//正确//Number指八种基本类型类
  Vector<? extends Number> x = new Vector<String>();//错误//String不属于基本类型
  2)限定通配符的下边界:-------Integer及其父类
  Vector<? super Integer> x = new Vector<Number>();//正确
  Vector<? super Integer> x = new Vector<Byte>();//错误


4.代码示例:

[java] view plaincopy
  1. <span style="font-size:18px;">HashMap<String,Integer> maps = new HashMap<String,Integer>();  
  2.   maps.put("zxx"28);  
  3.   maps.put("1hm"35);  
  4.   maps.put("flx"30);  
  5.     
  6.   Set<Map.Entry<String,Integer>> entrySet = maps.entrySet();  
  7.   for(Map.Entry<String, Integer> entry : entrySet)  
  8.   {  
  9.    System.out.println(entry.getKey()+":"+entry.getValue());  
  10.   }</span>  



5.自定义泛型方法及其应用

1).java的泛型是由C++借鉴而来的
  1)结构相似,类型不同的函数:
  int add(int x,int y)
  {
   return x+y;
  }
  float add(float x,float y)
  {
   return x+y;
  }
  double add(double x,double y)
  {
   return x+y;
  }
  用C++用模板函数解决,只写一个通用的方法,以适应各种类型:
  template<class T>
  <T>T add(T x,T y)
  {
   return(T)(x+y);
  }


2)java中的泛型没有C++强大的原因分析:

  java语言中的泛型基本上完全是在编译器中实现,用于编译器执行类型检查和类型推断,然后生成普通的非
  泛型的字节码,这种实现技术叫擦除(erasure)(编译器使用泛型类型信息保证类型安全,然后在生成
  字节码之前将其清除)。这是因为扩展虚拟机指令集来支持泛型被认为是无法接受的,这会为java厂商
  升级其JVM造成难以逾越的障碍,所以,java的泛型采用了可以完全在编译器中实现的擦除方法。
3)泛型的位置规范:
  用于放置泛型的类型参数的尖括号应出现在方法的其他所有修饰符之后和在方法的返回类型之前,
  也就是紧邻返回值之前。按照惯例,类型参数通常用单个大写字母表示。
4)泛型要点:
  <1>普通方法,构造方法和静态方法中都可以使用泛型。编译器不允许创建类型变量的数组。
   <2>只有引用类型才能作为泛型方法的实际参数,对于add方法,使用基本类型的数据进行测试没问题,是因为
  自动装箱和拆箱了。而swap(new int[3],3,5);报告编译错误,是因为编译器不会对new int[3]中的int
  自动拆箱和装箱了,new int[3]本身已经是对象了,也许你想要的就是int数组呢,它装箱便会弄巧成拙。
  <3>也可以用类型变量表示异常,称为参数化的异常,可以用于方法的throws列表中, 但是不能用于catch子句中。
     异常中采用泛型
    private static <T extends Exception> sayHello() throws T
   {
        try
   {
   }
       catch(Exception e)
   {
       throw (T)e;
    }
    }

6.自定义泛型类的应用
  1)如果类的实例对象中的多处都要用到同一个泛型参数,即这些地方引用的泛型类型
  要保持同一个实际类型时,这时候就要采用泛型类型的方式进行定义,也就是类级别
  的泛型,语法格式如下:
   public class GenericDao<T>
   {
    private T field1;
    public void save(T obj){}
    public T getById(int id){}
   }
2) 注意:
   <1>在对泛型进行参数化时,类型参数的实例必须是引用类型,不能是基本类型。
   <2>当一个变量被声明为泛型时,只能被实例变量和方法调用(还有内嵌类型),而不能
       被静态变量和静态方法调用,因为静态成员是被所有参数化的类所共享的,所以静态成员不应该有类级别的类型参数。

7.通过反射获得泛型的实际类型参数
1)Type[] getGenericParameterTypes() 
    按照声明顺序返回 Type 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型的.JDK1.5  
    Class<?>[] getParameterTypes() 
          按照声明顺序返回 Class 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型。 
2)>ParameterizedType
  Type[] getActualTypeArguments() 
      返回表示此类型实际类型参数的 Type 对象的数组。 实际类型参数
   Type getRawType() 
      返回 Type 对象,表示声明此类型的类或接口。 原始类型
 
3) Map<String,Integer> map = new Map<String,Integer>();   如何知道Map中的泛型参数类型?
  
 代码:
   [java] view plaincopy
  1. <span style="font-size:18px;">// 只能把Map放到一个方法中的参数中,获取方法的参数。  
  2.    public static void applyVector(Map<String,Integer> vector){  }  
  3.   
  4.   
  5.     Method applyMethod =   
  6.             GenericTest.class.getMethod("applyVector", Map.class);  
  7.    Type[] types = applyMethod.getGenericParameterTypes();   
  8.   
  9.   
  10.    //ParameterizedType是Type的子类。  
  11.    ParameterizedType pType = (ParameterizedType) types[0];  
  12.   
  13.   
  14.    System.out.println(pType.getRawType());  //得到Map类型。  
  15.                 methodGetX.invoke(pt1);  
  16.         }  
  17.    }  
  18. 5.PropertyUtils和BeanUtils的区别;  
  19.   BeanUtils接收返回的都是String类型,可自动完成属性的类型转换。  
  20.   PropertyUtils是以属性本身的类型进行操作。  
  21.   
  22. 6.java7的新特性:  
  23.   Map map = {name:"lisi",age:18};  
  24.   BeanUtils.setProperty(map,"name","zhangsan");  
  25. </span>