亲宝软件园·资讯

展开

Java学习_泛型

桐君过客 人气:0
  • 什么是泛型。
      • Java标准库提供的ArrayList内部就是一个Object[]数组,配合存储一个当前分配的长度,就可以充当“可变数组”。
        public class ArrayList {
            private Object[] array;
            private int size;
            public void add(Object e) {...}
            public void remove(int index) {...}
            public Object get(int index) {...}
        }
      • 如果用上述ArrayList存储String类型,会有这么几个缺点:

        • 需要强制转型;

        • 不方便,易出错。

        • 代码必须这么写:
          ArrayList list = new ArrayList();
          list.add("Hello");
          // 获取到Object,必须强制转型为String:
          String first = (String) list.get(0);

          很容易出现ClassCastException,因为容易“误转型”。

          list.add(new Integer(123));
          // ERROR: ClassCastException:
          String second = (String) list.get(1);

          要解决上述问题,我们可以为String单独编写一种ArrayList。

          public class StringArrayList {
              private String[] array;
              private int size;
              public void add(String e) {...}
              public void remove(int index) {...}
              public String get(int index) {...}
          }

          这样一来,存入的必须是String,取出的也一定是String,不需要强制转型,因为编译器会强制检查放入的类型。

          StringArrayList list = new StringArrayList();
          list.add("Hello");
          String first = list.get(0);
          // 编译错误: 不允许放入非String类型:
          list.add(new Integer(123));

          问题暂时解决。然而,新的问题是,如果要存储Integer,还需要为Integer单独编写一种ArrayList。实际上,还需要为其他所有class单独编写一种ArrayList。

          这是不可能的,JDK的class就有上千个,而且它还不知道其他人编写的class。

          为了解决新的问题,我们必须把ArrayList变成一种模板:ArrayList<T>

          public class ArrayList<T> {
              private T[] array;
              private int size;
              public void add(T e) {...}
              public void remove(int index) {...}
              public T get(int index) {...}
          }

          T可以是任何class。这样一来,我们就实现了:编写一次模版,可以创建任意类型的ArrayList。

          // 创建可以存储String的ArrayList:
          ArrayList<String> strList = new ArrayList<String>();
          // 创建可以存储Float的ArrayList:
          ArrayList<Float> floatList = new ArrayList<Float>();
          // 创建可以存储Person的ArrayList:
          ArrayList<Person> personList = new ArrayList<Person>();

          这样一来,既实现了编写一次,万能匹配,又通过编译器保证了类型安全:这就是泛型。

    向上转型

      • 在Java标准库中的ArrayList<T>实现了List<T>接口,它可以向上转型为List<T>。
        public class ArrayList<T> implements List<T> {
            ...
        }
        
        List<String> list = new ArrayList<String>();

        类型ArrayList<T>可以向上转型为List<T>。不能把ArrayList<Integer>向上转型为ArrayList<Number>List<Number>。ArrayList<Integer>和ArrayList<Number>两者完全没有继承关系。

  • 使用泛型

    • 使用ArrayList时,如果不定义泛型类型时,泛型类型实际上就是Object

    • 编译器如果能自动推断出泛型类型,就可以省略后面的泛型类型。

      // 可以省略后面的Number,编译器可以自动推断泛型类型:
      List<Number> list = new ArrayList<>();
    • 泛型接口

      • 除了ArrayList<T>使用了泛型,还可以在接口中使用泛型。例如,Arrays.sort(Object[])可以对任意数组进行排序,但待排序的元素必须实现Comparable<T>这个泛型接口。

        public interface Comparable<T> {
            /**
             * 返回负数: 当前实例比参数o小
             * 返回0: 当前实例与参数o相等
             * 返回正数: 当前实例比参数o大
             */
            int compareTo(T o);
        }

        可以直接对String数组进行排序。

        // sort
        import java.util.Arrays;
        
        public class Main {
            public static void main(String[] args) {
                    String[] ss = new String[] { "Orange", "Apple", "Pear" };
                    Arrays.sort(ss);
                    System.out.println(Arrays.toString(ss));    
                    }
        }

        这是因为String本身已经实现了Comparable<String>接口。如果换成我们自定义的Person类型试试。

         1 // sort
         2 import java.util.Arrays;
         3 
         4 public class Main {
         5     public static void main(String[] args) {
         6         Person[] ps = new Person[] {
         7             new Person("Bob", 61),
         8             new Person("Alice", 88),
         9             new Person("Lily", 75),
        10         };
        11         Arrays.sort(ps);
        12         System.out.println(Arrays.toString(ps));
        13 
        14     }
        15 }
        16 
        17 class Person {
        18     String name;
        19     int score;
        20     Person(String name, int score) {
        21         this.name = name;
        22         this.score = score;
        23     }
        24     public String toString() {
        25         return this.name + "," + this.score;
        26     }
        27 }

        运行程序,我们会得到ClassCastException,即无法将Person转型为Comparable。我们修改代码,让Person实现Comparable<T>接口。

         1 // sort
         2 import java.util.Arrays;
         3 
         4 public class Main {
         5     public static void main(String[] args) {
         6         Person[] ps = new Person[] {
         7             new Person("Bob", 61),
         8             new Person("Alice", 88),
         9             new Person("Lily", 75),
        10         };
        11         Arrays.sort(ps);
        12         System.out.println(Arrays.toString(ps));
        13     }
        14 }
        15 class Person implements Comparable<Person> {
        16     String name;
        17     int score;
        18     Person(String name, int score) {
        19         this.name = name;
        20         this.score = score;
        21     }
        22     public int compareTo(Person other) {
        23         return this.name.compareTo(other.name);
        24     }
        25     public String toString() {
        26         return this.name + "," + this.score;
        27     }
        28 }

        运行上述代码,可以正确实现按name进行排序。

      

 

                                      未完待续

加载全部内容

相关教程
猜你喜欢
用户评论