• 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)>
  • 相关阅读:
    IDEA 创建Spring项目后org.springframework.boot报错
    启动Tomcat失败 命令框一闪而过
    Tomcat(解压版)下载和配置
    启动Tomcat控制台显示乱码
    Android Studio 连接mumu模拟器
    CentOS7 修改主机名
    使用IDEA运行项目时提示:Warning:java: 源值1.5已过时, 将在未来所有发行版中删除
    mariadb远程授权问题
    idea中log4j的简单使用
    InfluxDB从原理到实战
  • 原文地址:https://www.cnblogs.com/sunhan/p/3542148.html
Copyright © 2020-2023  润新知