精华内容
下载资源
问答
  • JAVA泛型集合

    2018-04-26 14:01:18
    java 泛型 集合java 泛型 集合java 泛型 集合java 泛型 集合
  • 展开全部泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以62616964757a686964616fe78988e69d8331333264656165按类型进行参数化的类。可以把类型参数看作是使用参数化类型时指定...

    展开全部

    泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以62616964757a686964616fe78988e69d8331333264656165按类型进行参数化的类。可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样。

    可以在集合框架(Collection framework)中看到泛型的动机。例如,Map 类允许您向一个 Map 添加任意类的对象,即使最常见的情况是在给定映射(map)中保存某个特定类型(比如 String)的对象。

    因为 Map.get() 被定义为返回 Object,所以一般必须将 Map.get() 的结果强制类型转换为期望的类型,如下面的代码所示:

    Map m = new HashMap();

    m.put("key", "blarg");

    String s = (String) m.get("key");

    要让程序通过编译,必须将 get() 的结果强制类型转换为 String,并且希望结果真的是一个 String。但是有可能某人已经在该映射中保存了不是 String 的东西,这样的话,上面的代码将会抛出 ClassCastException。

    理想情况下,您可能会得出这样一个观点,即 m 是一个 Map,它将 String 键映射到 String 值。这可以让您消除代码中的强制类型转换,同时获得一个附加的类型检查层,该检查层可以防止有人将错误类型的键或值保存在集合中。这就是泛型所做的工作。

    泛型的好处

    Java 语言中引入泛型是一个较大的功能增强。不仅语言、类型系统和编译器有了较大的变化,以支持泛型,而且类库也进行了大翻修,所以许多重要的类,比如集合框架,都已经成为泛型化的了。这带来了很多好处:

    类型安全。 泛型的主要目标是提高 Java 程序的类型安全。通过知道使用泛型定义的变量的类型限制,编译器可以在一个高得多的程度上验证类型假设。没有泛型,这些假设就只存在于程序员的头脑中(或者如果幸运的话,还存在于代码注释中)。

    Java 程序中的一种流行技术是定义这样的集合,即它的元素或键是公共类型的,比如“String 列表”或者“String 到 String 的映射”。通过在变量声明中捕获这一附加的类型信息,泛型允许编译器实施这些附加的类型约束。类型错误现在就可以在编译时被捕获了,而不是在运行时当作 ClassCastException 展示出来。将类型检查从运行时挪到编译时有助于您更容易找到错误,并可提高程序的可靠性。

    消除强制类型转换。 泛型的一个附带好处是,消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。

    尽管减少强制类型转换可以降低使用泛型类的代码的罗嗦程度,但是声明泛型变量会带来相应的罗嗦。比较下面两个代码例子。

    该代码不使用泛型:

    List li = new ArrayList();

    li.put(new Integer(3));

    Integer i = (Integer) li.get(0);

    该代码使用泛型:

    List li = new ArrayList();

    li.put(new Integer(3));

    Integer i = li.get(0);

    在简单的程序中使用一次泛型变量不会降低罗嗦程度。但是对于多次使用泛型变量的大型程序来说,则可以累积起来降低罗嗦程度。

    潜在的性能收益。 泛型为较大的优化带来可能。在泛型的初始实现中,编译器将强制类型转换(没有泛型的话,程序员会指定这些强制类型转换)插入生成的字节码中。但是更多类型信息可用于编译器这一事实,为未来版本的 JVM 的优化带来可能。

    由于泛型的实现方式,支持泛型(几乎)不需要 JVM 或类文件更改。所有工作都在编译器中完成,编译器生成类似于没有泛型(和强制类型转换)时所写的代码,只是更能确保类型安全而已。

    泛型用法的例子

    泛型的许多最佳例子都来自集合框架,因为泛型让您在保存在集合中的元素上指定类型约束。考虑这个使用 Map 类的例子,其中涉及一定程度的优化,即 Map.get() 返回的结果将确实是一个 String:

    Map m = new HashMap();

    m.put("key", "blarg");

    String s = (String) m.get("key");

    如果有人已经在映射中放置了不是 String 的其他东西,上面的代码将会抛出 ClassCastException。泛型允许您表达这样的类型约束,即 m 是一个将 String 键映射到 String 值的 Map。这可以消除代码中的强制类型转换,同时获得一个附加的类型检查层,这个检查层可以防止有人将错误类型的键或值保存在集合中。

    下面的代码示例展示了 JDK 5.0 中集合框架中的 Map 接口的定义的一部分:

    public interface Map {

    public void put(K key, V value);

    public V get(K key);

    }

    注意该接口的两个附加物:

    类型参数 K 和 V 在类级别的规格说明,表示在声明一个 Map 类型的变量时指定的类型的占位符。

    在 get()、put() 和其他方法的方法签名中使用的 K 和 V。

    为了赢得使用泛型的好处,必须在定义或实例化 Map 类型的变量时为 K 和 V 提供具体的值。以一种相对直观的方式做这件事:

    Map m = new HashMap();

    m.put("key", "blarg");

    String s = m.get("key");

    当使用 Map 的泛型化版本时,您不再需要将 Map.get() 的结果强制类型转换为 String,因为编译器知道 get() 将返回一个 String。

    在使用泛型的版本中并没有减少键盘录入;实际上,比使用强制类型转换的版本需要做更多键入。使用泛型只是带来了附加的类型安全。因为编译器知道关于您将放进 Map 中的键和值的类型的更多信息,所以类型检查从执行时挪到了编译时,这会提高可靠性并加快开发速度。

    向后兼容

    在 Java 语言中引入泛型的一个重要目标就是维护向后兼容。尽管 JDK 5.0 的标准类库中的许多类,比如集合框架,都已经泛型化了,但是使用集合类(比如 HashMap 和 ArrayList)的现有代码将继续不加修改地在 JDK 5.0 中工作。当然,没有利用泛型的现有代码将不会赢得泛型的类型安全好处。

    二 泛型基础

    类型参数

    在定义泛型类或声明泛型类的变量时,使用尖括号来指定形式类型参数。形式类型参数与实际类型参数之间的关系类似于形式方法参数与实际方法参数之间的关系,只是类型参数表示类型,而不是表示值。

    泛型类中的类型参数几乎可以用于任何可以使用类名的地方。例如,下面是 java.util.Map 接口的定义的摘录:

    public interface Map {

    public void put(K key, V value);

    public V get(K key);

    }

    Map 接口是由两个类型参数化的,这两个类型是键类型 K 和值类型 V。(不使用泛型)将会接受或返回 Object 的方法现在在它们的方法签名中使用 K 或 V,指示附加的类型约束位于 Map 的规格说明之下。

    当声明或者实例化一个泛型的对象时,必须指定类型参数的值:

    Map map = new HashMap();

    注意,在本例中,必须指定两次类型参数。一次是在声明变量 map 的类型时,另一次是在选择 HashMap 类的参数化以便可以实例化正确类型的一个实例时。

    编译器在遇到一个 Map 类型的变量时,知道 K 和 V 现在被绑定为 String,因此它知道在这样的变量上调用 Map.get() 将会得到 String 类型。

    除了异常类型、枚举或匿名内部类以外,任何类都可以具有类型参数。

    命名类型参数

    推荐的命名约定是使用大写的单个字母名称作为类型参数。这与 C++ 约定有所不同(参阅 附录 A:与 C++ 模板的比较),并反映了大多数泛型类将具有少量类型参数的假定。对于常见的泛型模式,推荐的名称是:

    K —— 键,比如映射的键。

    V —— 值,比如 List 和 Set 的内容,或者 Map 中的值。

    E —— 异常类。

    T —— 泛型。

    泛型不是协变的

    关于泛型的混淆,一个常见的来源就是假设它们像数组一样是协变的。其实它们不是协变的。List 不是 List 的父类型。

    如果 A 扩展 B,那么 A 的数组也是 B 的数组,并且完全可以在需要 B[] 的地方使用 A[]:

    Integer[] intArray = new Integer[10];

    Number[] numberArray = intArray;

    上面的代码是有效的,因为一个 Integer 是 一个 Number,因而一个 In。

    2Q==

    已赞过

    已踩过<

    你对这个回答的评价是?

    评论

    收起

    展开全文
  • Java 1.5 之前没有泛型,通常需要使用强制类型转换的方式将一种数据类型转换为另一种数据类型,这种转换要求开发者对实际参数的类型具有可预知性。对于强制类型转换错误的情况,编译器可能不会提示错误,但是在...

    Java 1.5 之前没有泛型,通常需要使用强制类型转换的方式将一种数据类型转换为另一种数据类型,这种转换要求开发者对实际参数的类型具有可预知性。对于强制类型转换错误的情况,编译器可能不会提示错误,但是在运行时会出现异常,这是一个安全隐患。

    为了解决这一隐患,从 Java 1.5 开始提供了泛型。泛型可以在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高了代码的重用率。本节将详细介绍 Java 中泛型的使用。

    泛型集合

    泛型本质上是提供类型的“类型参数”,也就是参数化类型。我们可以为类、接口或方法指定一个类型参数,通过这个参数限制操作的数据类型,从而保证类型转换的绝对安全。

    例 1

    下面将结合泛型与集合编写一个案例实现图书信息输出。

    (1) 首先需要创建一个表示图书的实体类 Book,其中包括的图书信息有图书编号、图书名称和价格。Book 类的具体代码如下:

     
    1. public class Book
    2. {
    3. private int Id; //图书编号
    4. private String Name; //图书名称
    5. private int Price; //图书价格
    6. public Book(int id,String name,int price)
    7. { //构造方法
    8. this.Id=id;
    9. this.Name=name;
    10. this.Price=price;
    11. }
    12. public String toString()
    13. { //重写 toString()方法
    14. return this.Id+", "+this.Name+","+this.Price;
    15. }
    16. }


    (2) 使用 Book 作为类型创建 Map 和 List 两个泛型集合,然后向集合中添加图书元素,最后输出集合中的内容。具体代码如下:

     
    1. import java.util.ArrayList;
    2. import java.util.HashMap;
    3. import java.util.List;
    4. import java.util.Map;
    5. public class Test14
    6. {
    7. public static void main(String[] args)
    8. {
    9. //创建3个Book对象
    10. Book book1=new Book(1,"唐诗三百首",8);
    11. Book book2=new Book(2,"小星星",12);
    12. Book book3=new Book(3,"成语大全",22);
    13. Map<Integer,Book> books=new HashMap<Integer,Book>(); //定义泛型 Map 集合
    14. books.put(1001,book1); //将第一个 Book 对象存储到 Map 中
    15. books.put(1002,book2); //将第二个 Book 对象存储到 Map 中
    16. books.put(1003,book3); //将第三个 Book 对象存储到 Map 中
    17. System.out.println("泛型Map存储的图书信息如下:");
    18. for(Integer id:books.keySet())
    19. {
    20. //遍历键
    21. System.out.print(id+"——");
    22. System.out.println(books.get(id)); //不需要类型转换
    23. }
    24. List<Book> bookList=new ArrayList<Book>(); //定义泛型的 List 集合
    25. bookList.add(book1);
    26. bookList.add(book2);
    27. bookList.add(book3);
    28. System.out.println("泛型List存储的图书信息如下:");
    29. for(int i=0;i<bookList.size();i++)
    30. {
    31. System.out.println(bookList.get(i)); //这里不需要类型转换
    32. }
    33. }
    34. }


    在该示例中,代码“Map<Integer,Book> books=new HashMap<Integer,Book>();”创建了一个键类型为 Integer、值类型为 Book 的泛型集合,即指明了该 Map 集合中存放的键必须是 Integer 类型、值必须为 Book 类型,否则编译出错。在获取 Map 集合中的元素时,不需要将"books.get(id);"获取的值强制转换为 Book 类型,程序会隐式转换。在创建 List 集合时,同样使用了泛型,因此在获取集合中的元素时也不需要将“bookList.get(i)”代码强制转换为 Book 类型,程序会隐式转换。

    执行结果如下:

    泛型Map存储的图书信息如下:
    1001——1, 唐诗三百首,8
    1003——3, 成语大全,22
    1002——2, 小星星,12
    泛型List存储的图书信息如下:
    1, 唐诗三百首,8
    2, 小星星,12
    3, 成语大全,22

    泛型类

    除了可以定义泛型集合之外,还可以直接限定泛型类的类型参数。语法格式如下:

    public class class_name<data_type1,data_type2,…>{}

    其中,class_name 表示类的名称,data_ type1 等表示类型参数。Java 泛型支持声明一个以上的类型参数,只需要将类型用逗号隔开即可。

    泛型类一般用于类中的属性类型不确定的情况下。在声明属性时,使用下面的语句:

     
    1. private data_type1 property_name1;
    2. private data_type2 property_name2;

    该语句中的 data_type1 与类声明中的 datajype1 表示的是同一种数据类型。

    例 2

    在实例化泛型类时,需要指明泛型类中的类型参数,并赋予泛型类属性相应类型的值。例如,下面的示例代码创建了一个表示学生的泛型类,该类中包括 3 个属性,分别是姓名、年龄和性别。

     
    1. public class Stu<N,A,S>
    2. {
    3. private N name; //姓名
    4. private A age; //年龄
    5. private S sex; //性别
    6. //创建类的构造函数
    7. public Stu(N name,A age,S sex)
    8. {
    9. this.name=name;
    10. this.age=age;
    11. this.sex=sex;
    12. }
    13. //下面是上面3个属性的setter/getter方法
    14. public N getName()
    15. {
    16. return name;
    17. }
    18. public void setName(N name)
    19. {
    20. this.name=name;
    21. }
    22. public A getAge()
    23. {
    24. return age;
    25. }
    26. public void setAge(A age)
    27. {
    28. this.age = age;
    29. }
    30. public S getSex()
    31. {
    32. return sex;
    33. }
    34. public void setSex(S sex)
    35. {
    36. this.sex=sex;
    37. }
    38. }


    接着创建测试类。在测试类中调用 Stu 类的构造方法实例化 Stu 对象,并给该类中的 3 个属性赋予初始值,最终需要输出学生信息。测试类的代码实现如下:

     
    1. public class Test14
    2. {
    3. public static void main(String[] args)
    4. {
    5. Stu<String,Integer,Character> stu=new Stu<String,Integer,Character>("张晓玲",28,'女');
    6. String name=stu.getName();
    7. Integer age=stu.getAge();
    8. Character sex=stu.getSex();
    9. System.out.println("学生信息如下:");
    10. System.out.println("学生姓名:"+name+",年龄:"+age+",性别:"+sex);
    11. }
    12. }


    该程序的运行结果如下:

    学生信息如下:
    学生姓名:张晓玲,年龄:28,性别:女


    在该程序的 Stu 类中,定义了 3 个类型参数,分别使用 N、A 和 S 来代替,同时实现了这 3 个属性的 setter/getter 方法。在主类中,调用 Stu 类的构造函数创建了 Stu 类的对象,同时指定 3 个类型参数,分别为 String、Integer 和 Character。在获取学生姓名、年龄和性别时,不需要类型转换,程序隐式地将 Object 类型的数据转换为相应的数据类型。

    泛型方法

    到目前为止,我们所使用的泛型都是应用于整个类上。泛型同样可以在类中包含参数化的方法,而方法所在的类可以是泛型类,也可以不是泛型类。也就是说,是否拥有泛型方法,与其所在的类是不是泛型没有关系。

    泛型方法使得该方法能够独立于类而产生变化。如果使用泛型方法可以取代类泛型化,那么就应该只使用泛型方法。另外,对一个 static 的方法而言,无法访问泛型类的类型参数。因此,如果 static 方法需要使用泛型能力,就必须使其成为泛型方法。

    定义泛型方法的语法格式如下:

    [访问权限修饰符][static][final]<类型参数列表>返回值类型方法名([形式参数列表])

    例如:

     
    1. public static List<T> find(Class<T>class,int userId){}


    一般来说编写 Java 泛型方法,其返回值类型至少有一个参数类型应该是泛型,而且类型应该是一致的,如果只有返回值类型或参数类型之一使用了泛型,那么这个泛型方法的使用就被限制了。下面就来定义一个泛型方法,具体介绍泛型方法的创建和使用。

    例 3

    使用泛型方法打印图书信息。定义泛型方法,参数类型使用“T”来代替。在方法的主体中打印出图书信息。代码的实现如下:

     
    1. public class Test16
    2. {
    3. public static<T> void List(T book)
    4. { //定义泛型方法
    5. if(book!=null)
    6. {
    7. System.out.println(book);
    8. }
    9. }
    10. public static void main(String[] args)
    11. {
    12. Book stu=new Book(1,"细学 Java 编程",28);
    13. List(stu); //调用泛型方法
    14. }
    15. }


    该程序中的 Book 类为前面示例中使用到的 Book 类。在该程序中定义了一个名称为 List 的方法,该方法的返回值类型为 void,类型参数使用“T”来代替。在调用该泛型方法时,将一个 Book 对象作为参数传递到该方法中,相当于指明了该泛型方法的参数类型为 Book。

    该程序的运行结果如下:

    1, 细学 Java 编程,28

    泛型的高级用法

    泛型的用法非常灵活,除在集合、类和方法中使用外,本节将从三个方面介绍泛型的高级用法,包括限制泛型可用类型、使用类型通配符、继承泛型类和实现泛型接口。

    1. 限制泛型可用类型

    在 Java 中默认可以使用任何类型来实例化一个泛型类对象。当然也可以对泛型类实例的类型进行限制,语法格式如下:

    class 类名称<T extends anyClass>


    其中,anyClass 指某个接口或类。使用泛型限制后,泛型类的类型必须实现或继承 anyClass 这个接口或类。无论 anyClass 是接口还是类,在进行泛型限制时都必须使用 extends 关键字。

    例如,在下面的示例代码中创建了一个 ListClass 类,并对该类的类型限制为只能是实现 List 接口的类。

     
    1. //限制ListClass的泛型类型必须实现List接口
    2. public class ListClass<T extends List>
    3. {
    4. public static void main(String[] args)
    5. {
    6. //实例化使用ArrayList的泛型类ListClass,正确
    7. ListClass<ArrayList> lc1=new ListClass<ArrayList>();
    8. //实例化使用LinkedList的泛型类LlstClass,正确
    9. ListClass<LinkedList> lc2=new ListClass<LinkedList>();
    10. //实例化使用HashMap的泛型类ListClass,错误,因为HasMap没有实现List接口
    11. //ListClass<HashMap> lc3=new ListClass<HashMap>();
    12. }
    13. }


    在上述代码中,定义 ListClass 类时设置泛型类型必须实现 List 接口。例如,ArrayList 和 LinkedList 都实现了 List 接口,所以可以实例化 ListClass 类。而 HashMap 没有实现 List 接口,所以在实例化 ListClass 类时会报错。

    当没有使用 extends 关键字限制泛型类型时,其实是默认使用 Object 类作为泛型类型。因此,Object 类下的所有子类都可以实例化泛型类对象,如图 1 所示的这两种情况。
     


    图1 两个等价的泛型类

    2. 使用类型通配符

    Java 中的泛型还支持使用类型通配符,它的作用是在创建一个泛型类对象时限制这个泛型类的类型必须实现或继承某个接口或类。

    使用泛型类型通配符的语法格式如下:

    泛型类名称<? extends List>a=null;

    其中,“<? extends List>”作为一个整体表示类型未知,当需要使用泛型对象时,可以单独实例化。

    例如,下面的示例代码演示了类型通配符的使用。

     
    1. A<? extends List>a=null;
    2. a=new A<ArrayList> (); //正确
    3. b=new A<LinkedList> (); //正确
    4. c=new A<HashMap> (); //错误

    在上述代码中,同样由于 HashMap 类没有实现 List 接口,所以在编译时会报错。

    3. 继承泛型类和实现泛型接口

    定义为泛型的类和接口也可以被继承和实现。例如下面的示例代码演示了如何继承泛型类。

     
    1. public class FatherClass<T1>{}
    2. public class SonClass<T1,T2,T3> extents FatherClass<T1>{}


    如果要在 SonClass 类继承 FatherClass 类时保留父类的泛型类型,需要在继承时指定,否则直接使用 extends FatherClass 语句进行继承操作,此时 T1、T2 和 T3 都会自动变为 Object,所以一般情况下都将父类的泛型类型保留。

    下面的示例代码演示了如何在泛型中实现接口。

     
    1. interface interface1<T1>{}
    2. interface SubClass<T1,T2,T3> implements
    3. Interface1<T2>{}
    展开全文
  • Java泛型集合理解

    千次阅读 2018-07-19 12:50:47
    1.只读集合 使用&lt;? extends T&gt;定义的集合,只能读取,不能插入。原因是什么呢?我们从头开始分析: 首先,我们知道,&lt;? extends T&gt;修饰的集合,表示该集合内部的元素类型只能是T或者...

    1.只读集合

    使用<? extends T>定义的集合,只能读取,不能插入。原因是什么呢?我们从头开始分析:

    首先,我们知道,<? extends T>修饰的集合,表示该集合内部的元素类型只能是T或者是T的子类,比如,有A,B,C三个类,B类和C类继承了A类,<? extends A>的集合,可以插入A,B,C三个子类的实例。那么,当我们插入这个三个实例之后,list里面的值为[a,b,c],分别对应A,B,C的对象。此时,有两种情况来获取值:

    1)通过A类的引用获取

    A a = list.get(0);

    A b = list.get(1);

    A c = list.get(2);

    此时,根据多态,三种方式都可以正确的获取到值

    2)通过子类获取

    如果此时想用B的引用获取对象,就会产生问题。

    B a = (B) list.get(0);就会报错,因为父类对象不能用子类来接收。同样的,B c = (B)list.get(2)也会报错,因为类B和类C没有任何关系。换句话说,此时集合里面存了很多不同的类型,如果我想用某个特定的引用获取值时,就有可能会报错,此时只能使用父类的引用从集合中获取值。

    综上所述,在集合中添加对象有可能会存在报错的风险,所以,直接在语法层面,禁止添加元素。只读集合可以作为某个方法的参数,在方法体内,无法再向集合中添加元素了,可以作为一种保护措施。同时 ,要求列表里面的数据类型都是一致的,这样才可以从列表中读取数据。

    2.只写集合

    使用<? super T>修饰的集合。其实该集合也是可以读取的,但是可能读取的时候会报错,所以不建议使用它读取数据。下面我们来分析一下,该中集合可以存放什么样的数据

    首先,<? super T>定义了,集合里面的元素,要么是T类型,要么是T类型的父类。那么集合里面可以插入T的父类吗?答案是不能。还是考虑上面的A,B,C三个类。我们定义了List<? super A> 这个列表,如果此时放进去一个Object类型,那么当我用A的引用去接收值时,就会报错:A a = (A)list.get(0);因为Object类型无法转换成A类型。如果不用A类型的引用,我们又无法知道列表里面到底存储了什么类型的数据。所以,Java在语法层面直接规定了该列表只能存储A或者A的子类,这样,我们就可以使用A的引用去获取列表里面的数据了。

    其次,既然可以用A的引用去获取数据,那为什么还叫只写集合呢?这个问题的原因和上面的只读集合是一样的,假如列表里面存储了A,B,C三个类的对象,我们只能通过A的引用来获取数据,要是使用B或者C的引用获取数据的话,可能会报错。换句话说,列表中的存储的数据,类型可能是不一致的,读取数据可能会出现问题,所以最好不要从集合中读取数据。

    3.PECS原则

    请记住PECS原则:生产者(Producer)使用extends,消费者(Consumer)使用super。

    • 生产者使用extends

    如果你需要一个列表提供T类型的元素(即你想从列表中读取T类型的元素),你需要把这个列表声明成<? extends T>,比如List<? extends Integer>,因此你不能往该列表中添加任何元素。

    • 消费者使用super

    如果需要一个列表使用T类型的元素(即你想把T类型的元素加入到列表中),你需要把这个列表声明成<? super T>,比如List<? super Integer>,因此你不能保证从中读取到的元素的类型。

    • 即是生产者,也是消费者

    如果一个列表即要生产,又要消费,你不能使用泛型通配符声明列表,比如List<Integer>。

    例子

    请参考java.util.Collections里的copy方法(JDK1.7):

    展开全文
  • Java泛型集合

    2016-04-22 16:13:15
    Java Generics and Collections 英文版,详细描述java 泛型技术
  • java泛型集合 java集合 集合 java Collection 排序 集合排序
  • Java泛型集合]-英文版
  • Java_泛型集合的定义及使用

    千次阅读 2020-06-21 11:18:49
    泛型集合的定义及使用 引入 什么是泛型、为什么要引入泛型、泛型类和泛型方法的使用 实例泛型: ​ 创建对象时,为类所定义的泛型,进行参数化赋值。 类:创建对象时,为类所定义的泛型,进行参数化赋值 接口:...

    泛型集合的定义及使用

    引入

    什么是泛型、为什么要引入泛型、泛型类和泛型方法的使用

    实例泛型:

    ​ 创建对象时,为类所定义的泛型,进行参数化赋值。

    • 类:创建对象时,为类所定义的泛型,进行参数化赋值
    • 接口:实现接口时,为接口所定义的泛型,进行参数化赋值

    静态泛型:

    • 定义在方法的返回值类型前面:、、<T extends Comparable>、<T extends Comparable<? super T>> 可应用在形参列表、返回值两种场景上,不单单可以规范泛型,还可以语义化返回值。
    • 定义在方法的形参列表当中:<?>、<? extends Object>、<? super Integer>,不支持使用& 只能应用在形参列表上,规范泛型。

    1 概述

              一种约束—规范类型(常用名字:E = Elememt、T = Type、K = Key、V = Value),将类型的明确工作提前到对象的创建以及方法调用,防止程序不安全泛型 :将类型的明确工作提前到对象的创建以及方法调用,防止程序不安全;参数化类型、类型安全的集合,强制集合的类型必须一致;

    特点:

    1. 编译时即可检查,而非运行时抛出异常
    2. 访问时,不必类型转换也就是拆箱
    3. 不同泛型之间引用不能相互赋值,泛型不存在多态。(左泛型不可为右父类)

    2 泛型的好处

    1. 将运行时期异常提前到了编译时期;
    2. 在遍历集合时,避免了强制类型转换;
    3. 解决了程序黄色警告线的问题------>提高了程序的安全性;
    public static void main(String[] args) {
    		//创建一个ArrayList集合对象
    		ArrayList<String> array = new ArrayList<String>() ;//后面:泛型推断
    		
    		//添加元素
    		array.add("kaka") ;
    		array.add("hello") ;
    		array.add("java") ;
    		array.add("javaee") ;
    		
    		//遍历
    		Iterator<String> it = array.iterator() ;
    		while(it.hasNext()) {
    			String s = it.next() ;
    			System.out.println(s);
    		}
    	}
    
    • 使用泛型集合时注意类型要保持一致,否则会出现类型转化异常(ClassCastException)

    2.1 ArrayList集合存储自定义对象,加入泛型

    需求:使用ArrayList集合存储自定义对象Student,加入泛型

    1)定义一个学生类

    2)创建集合对象 ArrayList

    3)创建5个学生

    5)将5个学生添加到集合中

    6)创建迭代器

    7)利用迭代器遍历集合

    8)利用get(int index)+size()相结合的方式遍历

    /*
     * 学生类
     */
    public class Student {
    	private String name ;
    	private int age ;
    	public Student() {
    		super();
    		// TODO Auto-generated constructor stub
    	}
    	public Student(String name, int age) {
    		super();
    		this.name = name;
    		this.age = age;
    	}
    	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;
    	}
    	@Override
    	public String toString() {
    		return "Student [name=" + name + ", age=" + age + "]";
    	}
    }
    
    public static void main(String[] args){
    		//创建一个ArrayList集合
    		ArrayList<Student> array = new ArrayList<Student>() ;
    		
    		//创建学生对象
    		Student s1 = new Student("曹操",35) ;//后知后觉
    		Student s2 = new Student("蒋干",25) ;//不知不觉
    		Student s3 = new Student("诸葛亮",30) ;//先知先觉
    		
    		array.add(s1) ;
    		array.add(s2) ;
    		array.add(s3) ;
    		
    		//迭代器
    		Iterator<Student> it = array.iterator() ;
    		while(it.hasNext()) {
    			Student s = it.next() ;
    			System.out.println(s.getName()+"---"+s.getAge());
    		}
    		System.out.println("----------------------------");
    		
    		//普通for循环:get(int index)+size()相结合
    		for(int x = 0 ; x < array.size() ; x ++) {
    			Student s = array.get(x) ;
    			System.out.println(s.getName()+"---"+s.getAge());
    		}
    	}
    

    3 泛型的应用

    泛型主要应用在集合中:

    • 定义在类中
    • 定义在接口中
    • 定义在方法中

    3.1 泛型类

    把泛型定义在类上

    格式:

    • public class 类名<泛型类型1,…>

      泛型类型必须是引用类型

    /*
     * 使用泛型:提高程序的安全性:将泛型定义类上
     */
    public class ObjectTool<T>{
    	//成员变量
    	private  T obj ;
    	
    	//获取功能
    	public T get() {
    		return obj ;
    	}
    	
    	//设置功能
    	public void set(T obj) {
    		this.obj = obj ;
    	}
    }
    
    
    /*
     * 将泛型定义在类上 	测试类
     */
     public static void main(String[] args) {
    			//创建ObjectTool类的对象
    			ObjectTool<String> ot = new ObjectTool<String>() ;
    			
    			//设置数据
    			ot.set("卡卡"); 
    			//获取数据
    			String s = ot.get() ;
    			System.out.println("姓名是:"+s);
    			
    			ObjectTool<Integer> ot2 = new ObjectTool<Integer>() ;
    			
    			//设置数据
    			ot2.set(28);
    			Integer i = ot2.get() ;
    			System.out.println("年龄是:"+i);
    		}
    

    3.2 泛型方法

    把泛型定义在方法上

    格式:

    • public <泛型类型> 返回类型 方法名(泛型类型 .)
    public class ObjectTool<T>{		
    	//将泛型定义在方法上
    	public <T> void show(T t) {
    		System.out.println(t);
    	}
    }
    
    public static void main(String[] args) {
    		//创建ObjectTool类的对象
    		ObjectTool ot = new ObjectTool() ;
    		ot.show("hello");
    		ot.show(true);
    		ot.show(100);
    		ot.show(12.34);
    	}
    

    3.3 泛型接口

    把泛型定义在接口上

    格式:

    • public interface 接口名<泛型类型1…>

    3.1 实现类已经明确数据类型

    /*
     * 定义在接口上
     */
    public interface Inter<T> {
    	public abstract void show(T t);
    }
    
    /*
     * 测试类
     */
    public class InterDemo {
    	public static void main(String[] args) {
    		//接口多态
    		//第一种
    		Inter i = new InterImpl();
    		i.show("kaka");//kaka
        }
    }
    
    /*
     * 接口子实现类
     */
    public class InterImpl implements Inter<String>{
    
    	public void show(String t) {
    		// TODO Auto-generated method stub
    		System.out.println(t);
    	}
    }
    

    3.2 子实现类没有明确数据类型

    /*
     * 定义在接口上
     */
    public interface Inter<T> {
    	public abstract void show(T t);
    }
    
    /*
     * 测试类
     */
    public class InterDemo {
    	public static void main(String[] args) {
    		//不明确数据类型
    		Inter<Integer> i1 = new InterImpl<Integer>();
    		i1.show(100);//100
    		Inter<String> i2 = new InterImpl<String>();
    		i2.show("kaka");//kaka
        }
    }
    
    /*
     * 接口子实现类
     */
    public class InterImpl<T> implements Inter<T>{
    
    	@Override
    	public void show(T t) {
    		// TODO Auto-generated method stub
    		System.out.println(t);
    	}
    }
    

    4. 高级泛型_通配符

    关于泛型的通配符号:

    • <?>:任意Java类型(Object),可以自定义的类型,或者是JDK提供的任意Java类;
    • <? extends E>:向下限定E类型以及其他子类;
    • <? super E>:向上限定E类型以及其他的父类;
    public class Generic{
    	public static void main(String[] args) {
    		//<?>
    		//创建集合类型Collection集合
    		Collection<?> c1 = new ArrayList<Object>();
    		Collection<?> c2 = new ArrayList<Animal>();
    		Collection<?> c3 = new ArrayList<Dog>();
    		Collection<?> c4 = new ArrayList<Cat>();
    		
    		//<? extends E>
    		Collection<? extends Animal> c5 = new ArrayList<Animal>();
    		Collection<? extends Animal> c6 = new ArrayList<Dog>();
    		Collection<? extends Animal> c7 = new ArrayList<Cat>();
    //		Collection<? extends Animal> c8 = new ArrayList<Object>();错误
    		
    		//<? super E>
    		Collection<? super Animal> c9 = new ArrayList<Object>();
    		Collection<? super Dog> c10 = new ArrayList<Animal>();
    		Collection<? super Cat> c11 = new ArrayList<Animal>();
    //		Collection<? super Animal> c12 = new ArrayList<Dog>();错误
    		
    		
    	}
    }
    class Animal{}
    class Dog extends Animal{}
    class Cat extends Animal{}
    
    
    • 注:在开发过程中,直接在创建集合的时候给定具体的存储类型
      • Collection<String> c = new ArrayList<String>();
    展开全文
  • 泛型是从Java 1.5就开始提供了的,那么下面的文章内容,就要重点的来给大家讲解一下java泛型,主要就是要介绍泛型集合方面的内容。泛型能够在编译时检查类型安全,并且所有的强制转换都是自动和隐式的,提高了代码的...
  • java泛型集合

    2021-03-14 13:02:44
    但是这样的话就不能表示摸一个确定的类型因为object是所有类的父类所以它是一个表示所有类型java中加入了泛型以后所有的集合框架都重新写了使它们支持泛型,这样你就可以这样写ArrayList al=new ArrayList();...
  • 集合容器类在设计阶段/声明阶段不能确定这个容器到底实际存的是什么类型的对象,所以在JDK1.5之前只能把元素类型设计为Object,JDK1.5之后使用泛型来解决。因为这个时候除了元素的类型不确定,其他的部分
  • Java泛型集合源代码

    2018-09-05 09:20:25
    图书《Java泛型集合》配套的完整的源代码资料,配合图书使用
  • 我正在学习Java泛型,我正在尝试调整我开发的一些代码作为练习.特别是,我开发了一个ArrayVisualizer类,它使用Sedgewick的StdDraw库来可视化和动画化动态数组的行为.我有自己的动态数组类,它支持泛型,我试图将...
  • JAVA泛型简单排序实例

    2018-04-22 10:21:40
    JAVA泛型源代码实现以下功能:返回数组元素的最大值/最小值下标;判断数组元素是否按升序排列;T对象数组排序;二分法查找key元素;
  • 为何会这样,全是因为java泛型是伪泛型,假设说迷茫点A b = a是成功的(a = b成功是不可能的,即使在普通类型也需要强制转换),那么我们来分析一些过程。 a的引用使用了泛型,当a被编译了以后,生成的class中,a...
  • Java泛型集合.pdf

    2011-09-26 15:16:29
    [Java泛型集合].(Java.Generics.and.Collections).Maurice.Naftalin&Philip.Wadler.文字版.pdf
  • java泛型集合

    2012-12-30 10:41:40
    泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的...
  • JAVA泛型集合。递归

    2020-04-08 21:49:21
    泛型集合 什么是泛型 所谓泛型就是允许在定义类、接口时指定类型形参,这个类型形参将在声明变量、创建对象时确定。增加了泛型支持后的集合,完全可以记住集合中元素的类型,并可以在编译时检查集合中元素的类型。...
  • 常见的形式有泛型类、泛型接口、泛型方法、泛型集合; 语法: ​< T > T 称之为类型占位符,表示一种引用类型,(当然<>里边可以是其他字母,在实际应用中会转为具体的类型); 好处: 提高代码的重用...
  • 假设我们有一个泛型类型,有两个方法typeLTget();voidset(T);假设我们有一个超级类型P,而且它有子类型C1, C2 ... Cn..(为了方便起见,我们说P是自身的一个子类型,实际上是Ci)现在我们也有n混凝土类型L, L ... L,...
  • java集合里的泛型

    2021-03-13 23:59:00
    /** 泛型java jdk1.5新特性。* 泛型的好处 :* 1。将运行时的错诶提前到编译时。* 2.避免无谓的强制类型转换。** 自定义方法泛型: 自定义泛型就是一个数据类型的占位或一个数据类型变量, 一般T type或E ...
  • java泛型,泛型类详解

    2021-03-11 17:35:52
    之前给大家介绍了一下java泛型集合方面的内容,下面要给大家介绍的就是泛型类方面的知识,一起通过简单的文章来进行一下了解吧。泛型类除了能够定义泛型集合之外,还能够直接限定泛型类的类型参数。语法格式:...
  • 10 * Map接口的主要方法 方法名 功能说明 Object put(Object key,Object value) 插入新的对象并用key作为其键字 void putAll(Map t) 将另一个Map中的所有对象复制进来 Set entrySet) 返回映射中的关键字值对的集合 ...
  • 泛型集合

    2021-04-24 12:34:47
    有一个小误点: 二分查找 在计算机科学中,二分搜索(英语:binary search),也称折半搜索(英语:half-... } } 编译运行: $ javac BinarySearch.java $ java BinarySearch 4 本代码中如果查询为1,则返回的为-1
  • 一、重点内容泛型1.增加了代码安全性 * 2.省去了强制转换的麻烦(向下转型) */public class Demo01 { public static void main(String[] args) { // fun1(); // fun2(); // fun3(); // 泛型类 // 泛型类是在...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 121,665
精华内容 48,666
关键字:

java泛型集合

java 订阅
友情链接: xu.rar