JavaBean 内省API BeanUtils工具 泛型 xml xml约束

1 什么是JavaBean?有何特征?


   1)符合特定规则的类
   2)JavaBean分二类:
    a)侠义的JavaBean
        .私有的字段(Field)
        .对私有字段提供存取方法(读写方法)
    b)广义的JavaBean
        .私有的字段(Field)
        .对私有字段提供存取方法(读写方法)
        .数量任意的业务方法

2 内省API(SUN公司开发)站在反射角度


   1)在操作JavaBean时,即对JavaBean进入setter和getter操作时
   2)属性和getXxxxx()有关,同时必须有返回值
   3)任何一个JavaBean都有一个class属性,来自于Object类。

3 访问JavaBean属性的两种方式:
   1)直接调用bean的setXXX或getXXX方法。
   2)通过内省技术访问(java.beans包提供了内省的API),内省技术访问也提供了两种方式。
    ·通过PropertyDescriptor类操作Bean的属性
    ·通过Introspector类获得Bean对象的 BeanInfo,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后通过反射机制来调用这些方法。

    Apache组织开发了一套用于操作JavaBean的API,这套API考虑到了很多实际开发中的应用场景,因此在实际开发中很多程序员使用这套API操作JavaBean,以简化程序代码的编写。
    Beanutils工具包的常用类:
        BeanUtils
        ConvertUtils.register(Converter convert, Class clazz)
        自定义转换器
        内置转换器

//用SUN提供内省API操作JavaBean属性
public class Demo1 extends Object{
    @Test
    public void test1() throws Exception{
        Student s = new Student();
        //pd引用Student的name属性
        PropertyDescriptor pd = new PropertyDescriptor("name",Student.class);
        //m = setName()
        Method m = pd.getWriteMethod();
        //s.setName("berry")
        m.invoke(s,"berry");
        //s.getName()
        m = pd.getReadMethod();
        String returnValue = (String) m.invoke(s,null);
        System.out.println("returnValue="+returnValue);
    }
    @Test
    public void test2() throws Exception{
        //BeanInfo表示该Student对象所有的属性情况
        BeanInfo bi = Introspector.getBeanInfo(Student.class);
        //取得Student对象所有属性集合,属性和get 有关系 
        PropertyDescriptor[] pds = bi.getPropertyDescriptors();
        for(PropertyDescriptor pd : pds){
            System.out.println(pd.getName());    
        }
    }
}
package cn.itcast.java.introspector;

//侠义JavaBean 
    public class Student {
    private String name;
    public void setName(String name) {
        this.name = name;
    }
    
    public String getName() {
        return name;
    }

    public int getAge() {
        return 31;
    }
    public String getWC(){
        return "WC";
    }
}

*3 BeanUtils框架/工具(APACHE开源组织开发)
   1)BeanUtils框架能够完成内省的一切功能,而且优化
   2)BeanUtils框架能够对String<->基本类型自动转化
   3)BeanUtils框架自定义转换器: ConvertUtils.register( 转换规则 ,目标对象的Class)
   4)向BeanUtils框架注册自定义转换器必须放在bu.setProperty()代码之前   
   5)使用BeanUtils内置String->Date的转换器: ConvertUtils.register(new DateLocaleConverter(),java.util.Date.class);

//用APACHE提供Bean工具API操作JavaBean类属性
public class Demo1 {
    @Test
    public void test1() throws Exception{
        Student s = new Student();
        BeanUtils bu = new BeanUtils();
        /*
        //向BeanUtils框架注册自定义的转换器(String->java.util.Date)
        ConvertUtils.register(new Converter(){
            public Object convert(Class clazz, Object type) {
                //参数一:java.util.Date.class(目标类型)
                //参数二:是传入的参数类型,即java.lang.String
                String strBirthday = (String) type;
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                try {
                    return sdf.parse(strBirthday);
                } catch (ParseException e) {
                    e.printStackTrace();
                    return null;
                }
            }
        },java.util.Date.class);
        */
        ConvertUtils.register(new DateLocaleConverter(),java.util.Date.class);
        
        bu.setProperty(s,"name","张三");
        bu.setProperty(s,"age","31");
        bu.setProperty(s,"birthday","2011-10-09");
        
        String name = bu.getProperty(s,"name");
        String age = bu.getProperty(s,"age");
        String birthday = bu.getProperty(s,"birthday");
        
        System.out.println("name="+name);
        System.out.println("age="+age);
        System.out.println("birthday="+new Date(birthday).toLocaleString());
    }
}

//侠义JavaBean
public class Student {
    private String name;
    private int age;
    private Date birthday;
    public Student(){}
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}
*4 泛型
   1)在编译时,由编译器约束放入集合中的类型
   2)在运行时,编译器会擦除原泛型类型
   3)泛型二边要么都不使用约束,要么二边约束一致类型,同时二边必须使用引用类型
   4)为了与JDK1.4兼容,泛型可以一边有约束,一边无约束
   思考:不利用中间变量,将二个数交互
   5)当一个类中出大量的泛型方式或属性/字段,此时可以将该类作成泛型类
   6)如果使用泛型通配符,只能获取与泛型具体类型无关的信息,例如:长度。
   7)有二个类,初学者一定要注意:Collections和Arrays

泛型(Generic) —泛形的作用
    JDK5中的泛形允许程序员在编写集合代码时,就限制集合的处理类型,从而把原来程序运行时可能发生问题,转变为编译时的问题,以此提高程序的可读性和稳定性(尤其在大型程序中更为突出)。
    注意:泛型是提供给javac编译器使用的,它用于限定集合的输入类型,让编译器在源代码级别上,即挡住向集合中插入非法数据。但编译器编译完带有泛形的java程后,生成的class文件中将不再带有泛形信息,以此使程序运行效率不受到影响,这个过程称之为“擦除”。
    泛形的基本术语,以ArrayList<E>为例:<>念着typeof
    ArrayList<E>中的E称为类型参数变量
    ArrayList<Integer>中的Integer称为实际类型参数
    整个称为ArrayList<E>泛型类型
    整个ArrayList<Integer>称为参数化的类型ParameterizedType

    Java程序中的普通方法、构造方法和静态方法中都可以使用泛型。方法使用泛形前,必须对泛形进行声明,语法:<T> ,T可以是任意字母,但通常必须要大写。<T>通常需放在方法的返回值声明之前。例如:
    public static <T> void doxx(T t);
注意:
    只有对象类型才能作为泛型方法的实际参数。
    在泛型中可以同时有多个类型,例如:

public static <K,V> V getValue(K key) { return map.get(key);}

public void show(Double money){
System.out.println("苹果单价:" + money);
}
public void show(Integer money){
System.out.println("苹果数量:" + money);
}
public <T> void show(T info){
System.out.println("苹果信息:" + info);
}

    自定义泛形——泛型类
    如果一个类多处都要用到同一个泛型,这时可以把泛形定义在类上(即类级别的泛型),语法格式如下:
 

public class BaseDao<T> {
        private T field1;
        public void save(T obj){}
        public T getId(int id){}
    }

    注意,静态方法不能使用类定义的泛形,而应单独定义泛形。
    泛形的典型应用:BaseDao和反射泛型(Java基础加强下讲)

    定义一个方法,接收一个集合,并打印出集合中的所有元素,如下所示:
 

void print (Collection<String> c) {
           for (String e : c) {
                 System.out.println(e);
           }
}

     问题:该方法只能打印保存了Object对象的集合,不能打印其它集合。通配符用于解决此类问题,方法的定义可改写为如下形式:
 

void print (Collection<?> c)  {   //Collection<?>(发音为:"collection of unknown") 
for (Object e : c) {
    System.out.println(e);
}
}

     此种形式下需要注意的是:由于print方法c参数的类型为Collection<?>,即表示一种不确定的类型,因此在方法体内不能调用与类型相关的方法,例如add()方法。
    总结:使用?通配符主要用于引用对象,使用了?通配符,就只能调对象与类型无关的方法,不能调用对象与类型有关的方法。

    限定通配符的上边界:
        正确:Vector<? extends Number> x = new Vector<Integer>();
        错误:Vector<? extends Number> x = new Vector<String>();
    限定通配符的下边界:
        正确:Vector<? super Integer> x = new Vector<Number>();
        错误:Vector<? super Integer> x = new Vector<Byte>();

//传统方式下运行时对集合内容安全检查,统计各类型变量的数量
public class Demo1 {
    public static void main(String[] args) {
        List<Boolean> list = new ArrayList<Boolean>();
        list.add(true);
        list.add(false);
        for(Boolean b : list){
            System.out.println(b);
        }
        
        /*
        int stringNum = 0,integerNum=0,booleanNum = 0;
        List list = new ArrayList();
        list.add("jack");
        list.add("marry");
        list.add("sisi");
        list.add(100);
        list.add(200);
        list.add(true);
        Iterator it = list.iterator();
        while(it.hasNext()){
            Object obj = it.next();
            if(obj instanceof String){
                stringNum++;
            }else if(obj instanceof Integer){
                integerNum++;
            }else if(obj instanceof Boolean){
                booleanNum++;
            }
        }
        System.out.println("stringNum="+stringNum);
        System.out.println("integerNum="+integerNum);
        System.out.println("booleanNum="+booleanNum);
        */
    }
}
//自定义泛型方法,类
public class Demo2 {
    //JDK5.0
    public static void main(String[] args) {
        List<String> stringList = new ArrayList<String>();
        stringList.add("tom");
        stringList.add("haha");
        show(stringList);
    }
    //JDK1.4
    public static void show(List list) {
        for(Object obj : list){
            String s = (String) obj;
            System.out.print(s+"	");
        }
    }
}
//使用泛型方法交换二元素
public class Demo3 {
    public static void main(String[] args) {
        Boolean numA = false;
        Boolean numB = true;
        System.out.println("numA" + numA);
        System.out.println("numB" + numB);
        swap(numA,numB);
    }
    //泛型方法-通用性
    public static <T> void swap(T numA,T numB) {
        T temp = numA;
        numA = numB;
        numB = temp;
        System.out.println("numA" + numA);
        System.out.println("numB" + numB);
    }
}
//泛型通配符
public class Demo4 {
    public static void main(String[] args) {
        /*
        Apple a1 = new Apple();
        a1.buy(10);
        a1.buy(5.5);
        */
        Apple<Integer> a1 = new Apple<Integer>();
        a1.buy(10);
        Apple<Double> a2 = new Apple<Double>();
        a2.buy(5.5);
        
    }
}
package cn.itcast.java.generic;

public class Apple<T> {
    /*
    public void buy(Integer num){
        System.out.println("苹果:" + num  + "个");
    }
    public void buy(Double price){
        System.out.println("苹果:" + price  + "元");
    }
    */
    //泛型方式
    public void buy(T t){
        System.out.println("苹果:" + t  + "信息");
    }
}
//有限制的通配符
public class Demo5 {
    public static void main(String[] args) {
        List<Boolean> booleanList = new ArrayList<Boolean>();
        booleanList.add(true);
        booleanList.add(false);
        show(booleanList);
    }
    public static void show(List<?> list) {
        System.out.println("集合长度为:" + list.size());
        for(Object o : list){
            System.out.println(o);
        }
    }
}
//将集合中的元素倒序后输出
public class Demo6 {
    public static void main(String[] args) {
        List<String> stringList = new ArrayList<String>();
        stringList.add("one");
        stringList.add("two");
        stringList.add("three");
        System.out.println("倒序前:");
        for(String s : stringList){
            System.out.print(s+"	");
        }
        reverse(stringList);
        System.out.println("
倒序后:");
        for(String s : stringList){
            System.out.print(s+"	");
        }
    }
    //倒序集合
    public static void reverse(List<String> stringList) {
        //集合非空且至少有2个值
        if(stringList!=null && stringList.size()>=2){
            Collections.reverse(stringList);
        }
    }
}
5 什么是xml?为什么使用xml?常见应用?


   1)允许用户按照w3c组件的规定去定义无数个自定义标签
   2)需要使用XML技述通知计算机程序去处理关系数据
   3)保存XML文件时,一定要确保XML文件保存的编码和encoding声明的编码方式一致或兼容
   4)XML可以用来描述关系结构的数据,还可以作配置文件,当作一个小型的数据库或数据载体 
   5)在一个软件系统中,为提高系统的灵活性,它所启动的模块通常由其配置文件决定。

*6 xml文件的语法

   1)文档声明
    <?xml version="1.0" 指明XML文件的版本号,XML解析器就会采用对应的版本进行解析 
    encoding="UTF-8" 指明XML文件中的中文采用UTF-8编码,在IDE工具中,指明该文件的保存编码方式。standalone="yes或no" 指明XML文件需要初其它文件DTD约束的话,就是no,如果单独的XML文件,就是yes> 
    各浏览器中的XML解析器只对XML文件的语法检测

   2)元素
    1)通常元素都有开始和结束标签,但也可以使用空标签,即<a></a>=<a/>
    2)XML中标签嵌入顺序必须一致,且字符大小写不一致
    3)程序会将标签内的空白字符当作有效字符对待
   

   3)属性(附加信息的描述)
    1)属性由属性名和属性值组成,属性值由定界符""或'组合
    2)当一个事务必须与对象绑定在一起,没有该对象,该事务就没有意义,此时该事务就应成为对象的属性。
   

   4)注释(不能随意嵌套) 
    1)给程序员看的
    2)不能嵌套使用

   5)CDATA区 、特殊字符
    1)Character Data(字符数据区/段)
    2)CDATA段中的数据不会被XML解析器所解析
    3)不能嵌套使用
    4)XML内置5种转义字符
        < > & " '
    5)其它字符:
        &#x2605;   

   6)处理指令(processing instruction)
    1)可以使用CSS装饰XML文件中的内容
    2)CSS目前版本只能支持英文标签

<?xml version="1.0" encoding="GBK"?>
<!-- 手工和工具方式编写XML配置文件演示中文乱码的原理和解决方案 -->
<root>
    <country>
        <city>
            北京            
        </city>
        <city>
            上海    
        </city>
        <city>
            广州    
        </city>
    </country>
</root>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- 描述中国主要城市北上广三座城市别名 -->
<root>
    <country>
        <city>
            <真实名>北京</真实名>
            <别名>首都</别名>
        </city>
        <city>
            <真实名>上海</真实名>
            <别名>金城</别名>
        </city>
        <city>
            <真实名>广州</真实名>
            <别名>羊城</别名>
        </city>
    </country>
</root>
<?xml version="1.0" encoding="UTF-8"?>
<!-- 描述一个家庭的编号,地址,邮编等相关信息 -->
<root>
    <!-- XML的注释 -->
    <family id="2011100901">
        <address>GZ</address>
        <zipcode>&lt;510520&gt;</zipcode>
        <price>&#x2605;</price>         
    </family>
    
    <!-- 以下代码不想让XML解析器解析 -->
    <![CDATA[
        <family id="2011100902">
            <address>BJ</address>
            <zipcode>110120</zipcode>
        </family>
    ]]>
</root>
<?xml version="1.0" encoding="UTF-8"?>
<!-- <h1>使用CSS控制XML文件内容样式</h1> -->
<?xml-stylesheet type="text/css" href="pi.css"?>
<root>
    <h1>使用CSS将字符样式</h1>
</root>
------------------------------------------------------------------------------
@CHARSET "UTF-8";

h1{约束
    color:red;
    font-size:66px
}
*7 xml约束

     1)类是对象的约束
    2)DTD是XML文件的约束   
        3)浏览器对XML和DTD进行语法的检测
        4)浏览器不会检测XML是否符合DTD规则
    5)正确的XML和有效的XML文件
        正确的XML文件是指语法正确,而有效的XML文件是指语法和规则都正确
    6)XML中书写DTD有二种方式:
        a)DTD和XML分离
        b)XML中嵌入DTD
    6)XML引用DTD有二种方式:
        a)SYSTEM:个人或组织,小范围内使用
        b)PUBLIC:大范围内使用,例如:struts框架。。。
    7)EMPTY和ANY,项目中尽量使用EMPTY,少用ANY
        8)在DTD中,必须将所有的标签全部都声明完才行
    9)在DTD中,定义元素时,可以使用如下符号:
        a)+:有且只能出现1次或N次
        b)*:有且只能出现0次或N次
        c)?:有且只能出现0次或1次
        d)无:有且只能出现1次
            注意:以上符号用在()里面       
    10)DTD属性的设置值情况有四种:
        a)#REQURIED:该属性必须出现
        b)#IMPLIED:该属性可有可无
        c)#FIXED "固定值":该属性可有可无,如果有的话,必须是"固定值"
        d)"默认值":该属性可有可无,如果没有的话,用默认值补充,如果有的话,用新值替代旧值
         11)当页面出现多个相同的字符串,此时可以使用引用实体来解决,在DTD中定义,在XML中使用
     12)当定义DTD时,出个相同的子元素,此时可以使用参数实体来解决,在DTD中定义,在DTD中使用,
         使用%标识,通过%参数实体名;来引用     
   

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root SYSTEM "class.dtd">
<!-- 描述班上所有学员的姓名和年龄信息 -->
<root>
    <student>
        <name>张三</name>
        <age>30</age>    
    </student>
    <student>
        <name>李四</name>
        <age>31</age>    
    </student>
</root>


用DTD语法约束上述XML文件
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT root      (student+)>   
<!ELEMENT student   (name,age)>
<!ELEMENT name      (#PCDATA)>
<!ELEMENT age       (#PCDATA)>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>自定义XML的检查器(语法+约束)</title>
    <!-- 使用XML检证器来验证XML的有效性 -->
  </head>
  <body>
    <script type="text/javascript">
        //创建IE内置解析器
        var xmldoc = new ActiveXObject("Microsoft.XMLDOM");
        //开启xml校验
        xmldoc.validateOnParse="true";
        //加载需要检查的XML文件
        xmldoc.load("arg_entity.xml");    
        //正确
        if(xmldoc.parseError.reason.length==0){
            window.alert("有效的XML文件(语法正确+DTD约束");
        //出错        
        }else{
            window.alert(xmldoc.parseError.reason);
        }
    </script>
  </body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<!-- 将上述XML和DTD内容写在同一个XML文件中 -->
<!DOCTYPE root[
    <!ELEMENT root      (student+)>   
    <!ELEMENT student   (name,age)>
    <!ELEMENT name      (#PCDATA)>
    <!ELEMENT age       (#PCDATA)>
]>
<root>
    <student>
        <name>张三</name>
        <age>30</age>    
    </student>
    <student>
        <name>李四</name>
        <age>31</age>    
    </student>
</root>
<?xml version="1.0" encoding="UTF-8"?>
<!-- 声明元素 -->
<!DOCTYPE root [
    <!ELEMENT root    (student)>
    <!ELEMENT student (name,age,alias)>
    <!ELEMENT name    (#PCDATA)>
    <!ELEMENT age     (real|virtual)>
    <!ELEMENT alias   ANY>
    <!ELEMENT real    (#PCDATA)>    
    <!ELEMENT virtual (#PCDATA)>    
]>    
<root>
    <student>
        <name>jack</name>
        <age>
            <virtual>11</virtual>
        </age>
        <alias/>
    </student>
</root>
<?xml version="1.0" encoding="UTF-8"?>
<!-- 声明属性 -->
<!DOCTYPE root [
    <!ELEMENT root (桌子+)>
    <!ELEMENT 桌子  EMPTY>
    <!ATTLIST 桌子
              id      ID    #REQUIRED    
              width   CDATA #REQUIRED
              height  (50|60|70) "60"
              make    CDATA #IMPLIED
              color   CDATA #FIXED "白色"
              weight  CDATA "20">
]>

<root>
    <桌子 
        id="t2011100901"
        width="60" 
        height="70"
        color="白色"
        weight="30"
        />
</root>
<?xml version="1.0" encoding="UTF-8"?>
<!-- 声明实体 -->
<!DOCTYPE root [
    <!ELEMENT root   (电视台+)>
    <!ELEMENT 电视台  (#PCDATA)>    
    <!ENTITY  CCTV   "中国中央电视台">
]>
<root>
    <电视台>
        &CCTV;
    </电视台>
    <电视台>
        &CCTV;
    </电视台>
</root>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root SYSTEM "arg_entity.dtd">
<root>
    <客户>
        <姓名>张三</姓名>
    </客户>
    <员工>
        <姓名>李四</姓名>
    </员工>
</root>
<!------------------------------------------------------------------>
<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY % TIP  "姓名">       
<!ELEMENT root (客户,员工)>
<!ELEMENT 客户  (%TIP;)>
<!ELEMENT 员工  (%TIP;)>
<!ELEMENT 姓名  (#PCDATA)>
原文地址:https://www.cnblogs.com/sunhan/p/3542148.html