“”"
original author: jacky Li
Email : 3435673055@qq.com
Last edited: 2022.11.8
“”"

头歌上有关java作业

java常用集合

初识Collection

任务描述
本关任务:初识collection,向ArrayList对象添加一个数据:hello,world

相关知识

1.集合类概述
在程序中可以通过数组来保存多个对象,但在某些情况下开发人员无法预先确定需要保存对象的个数,此时数组将不再适用,因为数组的长度不可变。例如,要保存一个学校的学生信息,由于不停有新生来报道,同时也有学生毕业离开学校,这时学生的数目就很难确定。为了在程序中可以保存这些数目不确定的对象,JDK中提供了一系列特殊的类,这些类可以存储任意类型的对象,并且长度可变,在Java中这些类被统称为集合。集合类都位于java.util包中,在使用时一定要注意导包的问题,否则会出现异常。

2.3 集合类的特点

集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。

  1. Collection接口概述
    Collection:单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两个重要的子接口,分别是List和Set。其中,List的特点是元素有序、元素可重复。Set的特点是元素无序,而且不可重复。List接口的主要实现类有ArrayList和LinkedList,Set接口的主要实现类有HashSet和TreeSet。

Collection 层次结构中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。

  1. Collection接口成员方法
    集合层次结构中的根接口。Collection表示一组对象,这些对象也称为Collection的元素。一些Collection允许有重复的元素,而另一些则不允许。一些Collection是有序的,而另一些则是无序的。

添加功能
方法声明 功能描述
add() 添加元素
addAll() 添加一个集合的元素
删除功能
方法声明 功能描述
remove() 删除元素
removeAll() 删除一个集合的元素
clear() 清空集合
判断功能
方法声明 功能描述
contains() 判断集合是否包含指定的元素
containsAll() 判断一个集合是否包含一个集合的元素
isEmpty() 判断集合是否为空
获取功能
方法声明 功能描述
size() 获取集合的长度
retainAll() 取两个集合的交集
其他功能
方法声明 功能描述
toArray() 把集合转成数组,可以实现集合的遍历
iterator() 迭代器,集合的专用遍历方式
编程要求
根据提示,在右侧编辑器补充代码,向ArrayList对象添加一个数据:hello,world

测试说明
平台会对你编写的代码进行测试:

无输入

package step1;
import java.util.ArrayList;
public class HelloCollections {
    public ArrayList run(){
        // ---------------------Begin------------------------
        ArrayList<Object> list = new ArrayList<>();
        list.add("hello,world");
// ---------------------End------------------------
        return list;
    }
}
集合遍历方法

任务描述

本关任务:熟悉集合遍历的方法,采用常见的集合遍历方法打印输出给出的collection对象

相关知识
1.Iterator迭代器遍历
在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,JDK专门提供了一个接口Iterator。Iterator接口也是Java集合中的一员,但它与Collection、Map接口有所不同,Collection接口与Map接口主要用于存储元素,而Iterator主要用于迭代访问(即遍历)Collection中的元素,因此Iterator对象也被称为迭代器。

Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素,为了让初学者能更好地理解迭代器的工作原理,接下来通过一个图例来演示Iterator对象迭代元素的过程,如下图所示。

656
图中,在调用Iterator的next()方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next()方法后,迭代器的索引会向后移动一位,指向第一个元素并将该元素返回,当再次调用next()方法时,迭代器的索引会指向第二个元素并将该元素返回,依此类推,直到hasNext()方法返回false,表示到达了集合的末尾,终止对元素的遍历。

需要特别说明的是,当通过迭代器获取ArrayList集合中的元素时,都会将这些元素当做Object类型来看待,如果想得到特定类型的元素,则需要进行强制类型转换。

迭代:是取出集合中元素的一种方式。

而每一个容器的数据结构不同,所以取出的动作细节也不一样。但是都具有共性内容: 判断和取出。那么就可以将这些共性抽取。那么这些内部类都符合一个规则(或者说都抽取出来一个规则)。该规则就是Iterator。通过一个对外提供的方法:iterator();,来获取集合的取出对象。因为Collection中有iterator方法,所以每一个子类集合对象都具备迭代器。

迭代的常见操作

fgf
PS:在迭代时循环中next调用一次,就要hasNext判断一次。

并发修改异常,原因:迭代器依赖于集合存在,修改集合元素而迭代器却不知道。

解决方法:

A:迭代器迭代元素,迭代器修改。因为Iterator没有添加功能,所以使用其子接口ListIterator,元素在迭代元素的后面添加。
B:集合遍历元素,集合修改元素(普通for和get(index)结合),元素在最后添加

package cn.itcast;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
/*

  • 问题:有一个集合,如下,请问,我想判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现。
  • ConcurrentModificationException:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。
  • 产生的原因:
  • 迭代器是依赖于集合而存在的,在判断成功后,集合的中新添加了元素,而迭代器却不知道,所以就报错了,这个错叫并发修改异常。
  • 其实这个问题描述的是:迭代器遍历元素的时候,通过集合是不能修改元素的。
  • 如何解决呢?
  • A:迭代器迭代元素,迭代器修改元素,元素是跟在刚才迭代的元素后面的。
  • B:集合遍历元素,集合修改元素(普通for),元素在最后添加的。
    */
    public class ListIteratorDemo {
    public static void main(String[] args) {
    // 创建List集合对象
    List list = new ArrayList();
    // 添加元素
    list.add(“hello”);
    list.add(“world”);
    list.add(“java”);
    // 迭代器遍历
    // Iterator it = list.iterator();
    // while (it.hasNext()) {
    // String s = (String) it.next();
    // if (“world”.equals(s)) {
    // list.add(“javaee”);
    // }
    // }
    // 方式1:迭代器迭代元素,迭代器修改元素
    // 而Iterator迭代器却没有添加功能,所以我们使用其子接口ListIterator
    ListIterator lit = list.listIterator();
    while (lit.hasNext()) {
    String s = (String) lit.next();
    if (“world”.equals(s)) {
    lit.add(“javaee”);
    }
    }
    // 方式2:集合遍历元素,集合修改元素(普通for)
    for (int x = 0; x < list.size(); x++) {
    String s = (String) list.get(x);
    if (“world”.equals(s)) {
    list.add(“javaee”);
    }
    }
    System.out.println(“list:” + list);
    }
    }
    2.foreach
    Java的foreach是一种增强的for结构,其形式如下

for (variable : collection) statement
例如遍历数组:

public class Client {
public static void main(String[] args) {
String[] names = {“beibei”, “jingjing”};
for (String name : names) {
System.out.println(name);
}
}
}
遍历list:

/**

  • 描述:
  • Created by ascend on 2016/7/8.
    */
    public class Client {
    public static void main(String[] args) {
    List list = new ArrayList();
    list.add(“a”);
    list.add(“b”);
    list.add(“c”);
    for(String str : list){
    System.out.println(str);
    }
    }
    }
    编程要求
    根据提示,在右侧编辑器补充代码,使用forEach和 iterator方法遍历ArrayList

测试说明
平台会对你编写的代码进行测试:

无输入

开始你的任务吧,祝你成功!

package step2;
import java.util.ArrayList;
import java.util.Iterator;
public class WalkCollection {
    public static void main(String[] args) {
        WalkCollection_src walkCollection_src = new WalkCollection_src();
        ArrayList arrayListExample = walkCollection_src.getArrayListExample();
        // ---------------------Begin------------------------
        //使用迭代器iterator遍历arrayListExample集合
        Iterator iterator = arrayListExample.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        //使用foreach遍历arrayListExample集合
        for (Object ele : arrayListExample) {
            System.out.println(ele);
        }
// ---------------------End------------------------
    }
}
Set接口

任务描述

本关任务:练习HashSet的增删改查

1.添加值为helloHashSet的元素

2.更改元素值,将cat改成fish

3.删除值为apple的元素

相关知识
1.Set接口概述
一个不包含重复元素的 collection,无序。

哈希表确定元素是否相同

1、 判断的是两个元素的哈希值是否相同。
如果相同,再判断两个对象的内容是否相同。

2、 判断哈希值相同,其实判断的是对象的HashCode方法。判断内容相同,用的是equals方法。

2 HashSet类概述
不保证 set 的迭代顺序,特别是它不保证该顺序恒久不变。
HashSet如何保证元素唯一性
底层数据结构是哈希表(元素是链表的数组)
哈希表依赖于哈希值存储
添加功能底层依赖两个方法:int hashCode()、boolean equals(Object obj)
HashSet集合之所以能确保不出现重复的元素,是因为它在存入元素时做了很多工作。当调用HashSet集合的add()方法存入元素时,首先调用当前存入对象的hashCode()方法获得对象的哈希值,然后根据对象的哈希值计算出一个存储位置。如果该位置上没有元素,则直接将元素存入,如果该位置上有元素存在,则会调用equals()方法让当前存入的元素依次和该位置上的元素进行比较,如果返回的结果为false就将该元素存入集合,返回的结果为true则说明有重复元素,就将该元素舍弃。整个存储的流程如下图所示。

fdhfg
HashSet存储元素保证唯一性的代码及图解:

fgh

2.1 删除元素
// 引入 HashSet 类
import java.util.HashSet;
public class RunoobTest {
public static void main(String[] args) {
HashSet sites = new HashSet();
sites.add(“Google”);
sites.add(“Runoob”);
sites.add(“Taobao”);
sites.add(“Zhihu”);
sites.add(“Runoob”); // 重复的元素不会被添加
sites.remove(“Taobao”); // 删除元素,删除成功返回 true,否则为 false
System.out.println(sites);
}
}
删除集合中所有元素可以使用 clear 方法

2.2 添加元素
// 引入 HashSet 类
import java.util.HashSet;
public class RunoobTest {
public static void main(String[] args) {
HashSet sites = new HashSet();
sites.add(“Google”);
sites.add(“Runoob”);
sites.add(“Taobao”);
sites.add(“Zhihu”);
sites.add(“Runoob”); // 重复的元素不会被添加
System.out.println(sites);
}
}
2.3遍历元素
// 引入 HashSet 类
import java.util.HashSet;
public class RunoobTest {
public static void main(String[] args) {
HashSet sites = new HashSet();
sites.add(“Google”);
sites.add(“Runoob”);
sites.add(“Taobao”);
sites.add(“Zhihu”);
sites.add(“Runoob”); // 重复的元素不会被添加
for (String i : sites) {
System.out.println(i);
}
}
}
2.4 判断元素是否存在
// 引入 HashSet 类
import java.util.HashSet;
public class RunoobTest {
public static void main(String[] args) {
HashSet sites = new HashSet();
sites.add(“Google”);
sites.add(“Runoob”);
sites.add(“Taobao”);
sites.add(“Zhihu”);
sites.add(“Runoob”); // 重复的元素不会被添加
System.out.println(sites.contains(“Taobao”));
}
}
2.5修改元素
HashSet并没有提高修改元素的方法,直接修改元素可能会导致重复项,与HashSet的特点违背,因此要实现修改元素可采用如下方法:判断元素是否存在,存在则删除,之后添加新元素,最终实现修改元素的效果。

编程要求
根据提示,在右侧编辑器补充代码,操作HashSet完成以下任务:

1.添加值为helloHashSet的元素

2.更改元素值,将cat改成fish

3.删除值为apple的元素

测试说明
平台会对你编写的代码进行测试:

无输入

开始你的任务吧,祝你成功!

package step3;
import java.util.HashSet;
import java.util.Scanner;
public class HelloSet {
    public static void main(String[] args) {
        HashSet<Object> hashSet = new HashSet<>();
        Scanner scanner = new Scanner(System.in);
        for (int i = 0; i < 5; i++) {
            hashSet.add(scanner.next());
        }
// ---------------------Begin------------------------
        hashSet.add("helloHashSet");
        hashSet.remove("apple");
        if(hashSet.contains("cat")){
            hashSet.remove("cat");
            hashSet.add("fish");
        }
// ---------------------End------------------------
        hashSet.forEach(ele -> System.out.println(ele));
    }
}
Map接口

任务描述
本关任务:了解Map接口,完成HashMap的增删改查

1.增加key为name,value为lihong的元素

2.删除key为firstkey的元素

3.修改key为secondkey的元素值为educode

4.打印输出HashMap

相关知识
1.Map接口概述
Map:双列集合类的根接口,用于存储具有键(Key)、值(Value)映射关系的元素,每个元素都包含一对键值,在使用Map集合时可以通过指定的Key找到对应的Value,例如根据一个学生的学号就可以找到对应的学生。Map接口的主要实现类有HashMap和TreeMap。

将键映射到值的对象,一个映射不能包含重复的键,每个键最多只能映射到一个值。其实Map集合中存储的就是键值对。map集合中必须保证键的唯一性。

Map接口和Collection接口的不同

Map是双列的,Collection是单列的
Map的键唯一,Collection的子体系Set是唯一的
Map集合的数据结构值针对键有效,跟值无关
Collection集合的数据结构是针对元素有效
Map常用的子类:

Hashtable:内部结构是哈希表,是同步的。不允许null作为键,null作为值。
Properties:用来存储键值对型的配置文件的信息,可以和IO技术相结合。
HashMap:内部结构式哈希表,不是同步的。允许null作为键,null作为值。
TreeMap:内部结构式二叉树,不是同步的。可以对Map结合中的键进行排序。
HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持。
2.Map接口常用方法
方法声明 功能描述
put(K key, V value) 有添加和替换功能
putAll(Map m) 添加一个Map的元素
clear() 清空集合
remove(Object key) 根据键删除一个元素
containsKey() 判断集合是否包含指定的键
containsValue() 判断集合是否包含指定的值
isEmpty() 判断集合是否为空
get(Object key) 根据键获取值
keySet() 获取所有的键
values() 获取所有的值
entrySet() 获取所有的Entry
size() 获取集合元素的个数
3.常见的几种Map接口的实现类
HashMap

键是哈希表结构,可以保证键的唯一性

LinkedHashMap

Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。

TreeMap

键是红黑树结构,可以保证键的排序和唯一性,自然排序,比较器排序。

4.HashMap(重点)
HashMap是基于哈希表的Map接口的非同步实现(Hashtable跟HashMap很像,唯一的区别是Hashtalbe中的方法是线程安全的,也就是同步的)。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

4.1添加元素
// 引入 HashMap 类
import java.util.HashMap;
public class RunoobTest {
public static void main(String[] args) {
// 创建 HashMap 对象 Sites
HashMap<Integer, String> Sites = new HashMap<Integer, String>();
// 添加键值对
Sites.put(1, “Google”);
Sites.put(2, “Runoob”);
Sites.put(3, “Taobao”);
Sites.put(4, “Zhihu”);
System.out.println(Sites);
}
}
4.2 访问元素
// 引入 HashMap 类
import java.util.HashMap;
public class RunoobTest {
public static void main(String[] args) {
// 创建 HashMap 对象 Sites
HashMap<Integer, String> Sites = new HashMap<Integer, String>();
// 添加键值对
Sites.put(1, “Google”);
Sites.put(2, “Runoob”);
Sites.put(3, “Taobao”);
Sites.put(4, “Zhihu”);
System.out.println(Sites.get(3));
}
}
4.3 删除元素
// 引入 HashMap 类
import java.util.HashMap;
public class RunoobTest {
public static void main(String[] args) {
// 创建 HashMap 对象 Sites
HashMap<Integer, String> Sites = new HashMap<Integer, String>();
// 添加键值对
Sites.put(1, “Google”);
Sites.put(2, “Runoob”);
Sites.put(3, “Taobao”);
Sites.put(4, “Zhihu”);
Sites.remove(4);
System.out.println(Sites);
}
}
4.4 迭代元素
// 引入 HashMap 类
import java.util.HashMap;
public class RunoobTest {
public static void main(String[] args) {
// 创建 HashMap 对象 Sites
HashMap<Integer, String> Sites = new HashMap<Integer, String>();
// 添加键值对
Sites.put(1, “Google”);
Sites.put(2, “Runoob”);
Sites.put(3, “Taobao”);
Sites.put(4, “Zhihu”);
// 输出 key 和 value
for (Integer i : Sites.keySet()) {
System.out.println("key: " + i + " value: " + Sites.get(i));
}
// 返回所有 value 值
for(String value: Sites.values()) {
// 输出每一个value
System.out.print(value + ", ");
}
}
}
4.5 修改元素
put的方法即是添加也是修改。它没有update方法,所以当要修改一个元素的时候首先一定要先判断这个元素是否存在于hashmap中然后再修改。不然一旦没有该元素,那么put就实现了添加的作用。

编程要求
根据提示,在右侧编辑器补充代码,完成以下任务:

1.增加key为name,value为lihong的元素

2.删除key为firstkey的元素

3.修改key为secondkey的元素值为educode

4.打印输出HashMap

测试说明
平台会对你编写的代码进行测试:

无输入

开始你的任务吧,祝你成功!

package step4;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Scanner;
public class HelloHashMap {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        HashMap hashMapExample = new HashMap<>();
        for (int i = 0; i < 2; i++) {
            hashMapExample.put(scanner.next(), scanner.next());
        }
// ---------------------Begin------------------------
        hashMapExample.put("secondkey", "educode");
        hashMapExample.remove("firstkey");
        hashMapExample.put("name", "lihong");
        System.out.println(hashMapExample);
// ---------------------End------------------------
    }
}
泛型

任务描述
本关任务:使用泛型创建一个储存元素类型为String的ArrayList,完成:

1.添加String类型内容为educode的元素

2.遍历输出ArrayList

相关知识
1.泛型概述
泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去除掉“类型”信息,使程序运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样。由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其它类型的数据,例如,用反射得到集合,再调用其add方法即可。

泛型引用和创建两端,给出的泛型变量必须相同。

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

泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。

在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。

泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,以提高代码的重用率。

可以在集合框架(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 值。这可以让您消除代码中的强制类型转换,同时获得一个附加的类型检查层,该检查层可以防止有人将错误类型的键或值保存在集合中。这就是泛型所做的工作。

泛型:是一种把类型明确的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型。参数化类型,把类型当作参数一样的传递。

package cn.itcast_01;
import java.util.ArrayList;
import java.util.Iterator;
/*

  • ArrayList存储字符串并遍历
  • 我们按照正常的写法来写这个程序, 结果确出错了。
  • 为什么呢?
  •     因为我们开始存储的时候,存储了String和Integer两种类型的数据。
    
  •     而在遍历的时候,我们把它们都当作String类型处理的,做了转换,所以就报错了。
    
  • 但是呢,它在编译期间却没有告诉我们。
  • 所以,我就觉得这个设计的不好。
  • 回想一下,我们的数组
  •     String[] strArray = new String[3];
    
  •     strArray[0] = "hello";
    
  •     strArray[1] = "world";
    
  •     strArray[2] = 10;
    
  • 集合也模仿着数组的这种做法,在创建对象的时候明确元素的数据类型。这样就不会在有问题了。
  • 而这种技术被称为:泛型。
  • 泛型:是一种把类型明确的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型。参数化类型,把类型当作参数一样的传递。
  • 格式:
  •     <数据类型>
    
  •     此处的数据类型只能是引用类型。
    
  • 好处:
  •     A:把运行时期的问题提前到了编译期间
    
  •     B:避免了强制类型转换
    
  •     C:优化了程序设计,解决了黄色警告线
    

*/
public class GenericDemo {
public static void main(String[] args) {
// 创建
ArrayList array = new ArrayList();
// 添加元素
array.add(“hello”);
array.add(“world”);
array.add(“java”);
// array.add(new Integer(100));
//array.add(10); // JDK5以后的自动装箱
// 等价于:array.add(Integer.valueOf(10));
// 遍历
Iterator it = array.iterator();
while (it.hasNext()) {
// ClassCastException
// String s = (String) it.next();
String s = it.next();
System.out.println(s);
}
// 看下面这个代码
// String[] strArray = new String[3];
// strArray[0] = “hello”;
// strArray[1] = “world”;
// strArray[2] = 10;
}
}
2. 泛型的好处
简言之,泛型能够使类型(类和接口)在定义类,接口和方法的时候参数化。非常像方法定义时用到的形式参数(formal parameters),类型参数提供了一种你可以通过不同的输入来复用同一段代码的方法。不同点是,形式参数输入的是值,而类型参数输入的是类型。

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

编译时更强大的类型检测
消除类型转换(Elimination of casts)
使开发者实现泛型算法
2.1 类型安全
泛型的主要目标是提高 Java 程序的类型安全。通过知道使用泛型定义的变量的类型限制,编译器可以在一个高得多的程度上验证类型假设。没有泛型,这些假设就只存在于程序员的头脑中(或者如果幸运的话,还存在于代码注释中)。

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

2.2 消除强制类型转换
泛型的一个附带好处是,消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。
尽管减少强制类型转换可以降低使用泛型类的代码的罗嗦程度,但是声明泛型变量会带来相应的罗嗦。

2.3 优化了程序设计,解决了黄色警告线
3 泛型的内部原理
泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入。但是,编译器编译带类型说明的集合时会去除掉“类型”信息,目的就是使程序运行效率不受影响。因此,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样。

package com.itheima.day2;
import java.util.ArrayList;
public class GenericTest {
public static void main(String[] args) {
ArrayList collection1 = new ArrayList();
ArrayList collection2 = new ArrayList();
System. out.println(collection1.getClass() == collection2.getClass());
//结果:true
}
}
由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其它类型的数据,例如,用反射得到集合,再调用其add方法即可。

package com.itheima.day2;
import java.util.ArrayList;
public class GenericTest {
public static void main(String[] args) throws Exception {
ArrayList collection1 = new ArrayList();
collection1.getClass().getMethod( “add”,Object.class).invoke(collection1, “abc”);
System. out.println(collection1.get(0));
}
}
ArrayList类定义和ArrayList类引用中涉及如下术语:

整个称为ArrayList泛型类型
ArrayList中的E称为类型变量或类型参数
整个ArrayList称为参数化的类型
ArrayList中的Integer称为类型参数的实例或实际类型参数
ArrayList中的<>念着typeof
ArrayList称为原始类型
参数化类型与原始类型的兼容性:参数化类型可以引用一个原始类型的对象,编译报告警告,例如

Collection c = new Vector();//考虑到对以前代码的兼容性,编译器是可以通过的
原始类型可以引用一个参数化类型的对象,编译报告警告,例如

Collection c = new Vector();//原来的方法接受一个集合参数,新的类型也要能传进去
参数化类型不考虑类型参数的继承关系:

Vector v = new Vector(); //错误!不写没错,写了就是明知故犯
Vector v = new Vector(); //也错误!
注意:

假设Vector v = new Vector();可以的话,那么以后从v中取出的对象当作String用,而v实际指向的对象中可以加入任意的类型对象;

假设Vector v = new Vector();可以的话,那么以后可以向v中加入任意的类型对象,而v实际指向的集合中只能装String类型的对象。

编译器不允许创建泛型变量的数组。即在创建数组实例时,数组的元素不能使用参数化的类型。

例如,下面语句有错误:
Vector vectorList[] = new Vector[10];
思考题:
下面的代码会报错误吗?

Vector v1 = new Vector();
Vector v = v1;

答案:编译的时候是不会报错的,因为编译器是一行一行按照语法检查代码的,因此不会出错。

编程要求
根据提示,在右侧编辑器补充代码,完成一下任务:

1.添加String类型内容为educode的元素

2.遍历输出ArrayList

测试说明
补充完代码后,点击测评,平台会对你编写的代码进行测试,当你的结果与预期输出一致时,即为通过。

测试输入:
张三
李四
王五
预期输出:
第1个元素为:张三
第2个元素为:李四
第3个元素为:王五
第4个元素为:educode
开始你的任务吧,祝你成功!

package step5;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Scanner;
public class Genericity {
    public static void main(String[] args) {
        // ---------------------Begin------------------------
        Scanner scanner = new Scanner(System.in);
        ArrayList<String> stringArrayList = new ArrayList<>();
        while (scanner.hasNext()){
            stringArrayList.add(scanner.next());
        }
        stringArrayList.add("educode");
        Iterator<String> iterator = stringArrayList.iterator();
        int i = 1;
        while (iterator.hasNext()){
            System.out.println(String.format("第%d个元素为:%s", i, iterator.next()));
            i++;
        }
        // ---------------------End------------------------
    }
}
知识回顾

任务描述
本关任务:对本章主要理论知识点进行回顾复习。

相关知识
为了完成本关任务,你需要对之前完成的关卡进行复习。

编程要求
根据相关知识,按照要求完成选择题任务,包含单选题和多选题。

测试说明
平台会对你选择的答案进行判断,全对则通过测试。

开始你的任务吧,祝你成功!
头歌上有关java作业

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。