黑马程序员 泛型,javaBean

来源:互联网 发布:淘宝直通车出价技巧 编辑:程序博客网 时间:2024/06/11 10:34

 

 ----------android培训、java培训、java学习型技术博客、期待与您交流! -----------

1,泛型

          泛型是1.5之后的新特性,主要目的是为了解决安全问题,向下转型以及将运行时的错误提前到编译时。

          泛型的使用标识“<>”,只要在类的声明后面加上“<>”标识,泛型就可以使用了。

          泛型中在“<>”中的内容称为泛型参数。泛型参数只能是引用数据类型,不能是基本数据类型。

2,泛型类

          在泛型出现之前,为了提高程序的扩展性,使用多态来实现。

class cat{}class dog{}class Tool{    private Object animal;public Object getAnimal() {return animal;}public void setAnimal(Object animal) {this.animal = animal;}    /*     * 采用所有类的父类     * Object作为方法     * 的参数以提高程序扩展性     */} class TestII{    public static void main(String[] args) {        Tool t =new Tool();        t.setAnimal(new cat());        dog w =(dog)t.getAnimal();        /**         * 如果不小心写成了new cat()          * 那么dog w =(dog)t.getAnimal();就会出现         * java.lang.ClassCastException:catcannot be cast to dog         */    }}

总结:从上面可以看出,多态在一定条件下优化了程序,但是存在很多不方便的地方,

            1,多态需要向下转型

             2,多态容易出现类型转换错误

       泛型出现之后,可以用泛型来升华和简化多态操作带来的扩展性

class cat{}class dog{}class Tool<T>{    private T animal;public T getAnimal() {return animal;}public void setAnimal(T animal) {this.animal = animal;}} class TestII{    public static void main(String[] args) {        Tool<cat> t =new Tool<cat>();        t.setAnimal(new cat());        cat c = t.getAnimal();    }}

看下编译器的提示:

从上面可以看出,编译器在编译阶段就检测出类型的限定了,一旦限定了类型,那么一些不安全的操作都没有办法在绕过编译阶段了。

定义泛型类的最佳时机是在多态方面,父类引用子类对象时,这时候用泛型很有帮助。

3,泛型方法

          泛型类的弊端也是有的,假如泛型类限定的数据类型,那么里面非静态方法想要操作其他类型的数据,那么就是很麻烦的事情了。因此引入的泛型方法。

class Tool<T>{public void print(T obj) {System.out.println("the value is "+ obj);}} class TestII{    public static void main(String[] args) {        Tool<Integer> t =new Tool<Integer>();        t.print(3);        t.print("a");    }}

查看编译提示信息:

从提示信息中可以看出,print方法被限定死了,操作其他数据就不行了。

改进方法如下:

class Tool<T>{public <E> void print(E obj) {System.out.println("the value is "+ obj);}} class TestII{    public static void main(String[] args) {        Tool<Integer> t =new Tool<Integer>();        t.print(3);        t.print("a");    }}

查看编译提示信息;


这样t就可以打印所有Object的类型数据了。
        静态方法可以引用类的类型码?

答案是否定的,不能使用类定义的类型,因为定义在类上的泛型是在使用这个类的对象的时候才能使用的。

class Tool<T>{public static void print(T obj) {System.out.println("static method :: the value is "+ obj);}}

查看编译提示信息:

所以如果静态方法想要在泛型类中生存,那么就必须自己定义自己的泛型静态方法
代码如下:

class Tool<T>{public static void print(T obj) {System.out.println("static method :: the value is "+ obj);}}

查看编译提示信息:


总结:使用泛型方法的好出显示出来了,泛型方法是在语句输入后才确定的,这样有效的提高程序的扩展性了。

4,泛型限定

           有时候程序为特别需要,使用泛型的话会出现编译无法通过,例如想打印Arraylist<Srtring>和Arraylist<Integer>类型的数据,那么就不能写在一个类中,只能重写定义类,这样以来就很麻烦。那么泛型限定就解决了这个问题。

泛型的使用:

向下限定: 格式:<? extends T>:表示?取值的类型只能是T本身或者其子类。

List<? extends Number> array1 = new ArrayList<Integer>();        List<? extends Number> array2 = new ArrayList<String>();

第二句编译不通过:


向上限定: 格式:<? super T>:展表示?取值的类型只能是T本身或者其父类。

List<? super Integer> array1 = new ArrayList<Number>();        List<? extends Integer> array2 = new ArrayList<Byte>();

编译提示:


            泛型在方法中的使用

向下限定:E extends 类型:表示E只能是类型的子类或者类型本身。

class Tool<T>{public <E extends Number> void print(E obj) {System.out.println("static method :: the value is "+ obj);}}

调用函数:

class TestII{    public static void main(String[] args) {        Tool<Integer> t =new Tool<Integer>();        t.print(3);        t.print("a");    }}

编译查看;

说明:此时参数类型只能是Number的子类型或者Number本身。

向上限定: 注意向上限定不能应用与方法,也不能应用于类。

5,JavaBean

          javaBean的定义:一个Java类中,如果含有某些方法以get/set开头,并且访问权限是public,则这样的Java类成为JavaBean类。
          javaBean方法名有要求,如果方法名称中属性名的第二个值是小写,那么属性第一个必须要小写,如name,如果第二个是大写,属性的第一个值必须是大写如CPU

          注意:boolean类型的getXXX被替换成isXXX了,更容易理解了,一看就知道是博哦了按类型的。

          PropertyDescriptor类:

class PropertyTest{private int num = 1;private String name = "mingren";public int getNum() {return num;}public void setNum(int num) {this.num = num;}public String getName() {return name;}public void setName(String name) {this.name = name;}} class TestII{    public static void main(String[] args) throws Exception {    PropertyTest pt = new PropertyTest();    PropertyDescriptor pd = new PropertyDescriptor("num",pt.getClass());    //获取属性名称    System.out.println(pd.getDisplayName());    //获取读方法    System.out.println(pd.getReadMethod());    //获取写方法    System.out.println(pd.getWriteMethod());    //设置属性值    pd.setValue("num", 2);    //获取属性值    System.out.println(pd.getValue("num"));    }}

验证结果:


          javaBean结合Method,或者Field就可以操作字段了,

class TestII{    public static void main(String[] args) throws Exception {    PropertyTest pt = new PropertyTest();    PropertyDescriptor pd = new PropertyDescriptor("num",pt.getClass());    Field field = pt.getClass().getDeclaredField(pd.getName());    field.setAccessible(true);    field.setInt(pt, 3);    System.out.println(field.get(pt));        Method method = pd.getWriteMethod();    method.invoke(pt, 4);    method = pd.getReadMethod();    System.out.println(method.invoke(pt, null));    }}

验证结果:

总结:尽量不要用field的暴力反射操作javaBean,这样很容易造成数据安全问题。用method还是比较好,这样不容易破坏封装性。

 

----------android培训、java培训、java学习型技术博客、期待与您交流! -----------