首先来了解什么是泛型集合和非泛型集合,最重要的是处理实现部分,因为在实现过程中才能真正理解概念和它们之间的差异。
泛型基本上是编译时出现的错误,而不是运行时出现的错误。 泛型相对于非泛型有以下优势:
- 代码重用:在泛型的帮助下,只需编写一次方法/类/接口并将其用于任何类型,而在非泛型中,代码需要在需要时一次又一次地编写。
- 类型安全:泛型使错误在编译时出现而不是在运行时出现(在编译时知道代码中的问题总是比让代码在运行时失败更好)。
示例:要创建一个存储学生姓名的
ArrayList
,如果程序员错误地添加了一个整数对象而不是字符串,编译器允许这样做。 但是,当从ArrayList
检索此数据时,它会在运行时导致非泛型ArrayList
出现问题。
示例1
// Java program to Demonstrate that Not Using Generics // Can cause Run Time Exceptions // Importing all utility classes import java.util.*; // Main class class YBA { // Main driver method public static void main(String[] args) { // Creating an ArrayList // Declaring object without any type specified ArrayList al = new ArrayList(); // Adding elements to the above object // Custom input elements al.add("Sachin"); al.add("Rahul"); // Compiler will allows this operation al.add(10); String s1 = (String)al.get(0); String s2 = (String)al.get(1); // Try block to check for exceptions try { // Causes Runtime Exception String s3 = (String)al.get(2); } // Catch block to handle the exceptions catch (Exception e) { // Display the exception System.out.println("Exception: " + e); } } }
运行结果如下:
prog.java:19: warning: [unchecked] unchecked call to add(E) as a member of the raw type ArrayList al.add("Sachin"); ^ where E is a type-variable: E extends Object declared in class ArrayList prog.java:20: warning: [unchecked] unchecked call to add(E) as a member of the raw type ArrayList al.add("Rahul"); ^ where E is a type-variable: E extends Object declared in class ArrayList prog.java:23: warning: [unchecked] unchecked call to add(E) as a member of the raw type ArrayList al.add(10); ^ where E is a type-variable: E extends Object declared in class ArrayList 3 warnings
泛型如何解决这个问题?
如果这个列表是通用的,那么它只需要 String
对象并在任何其他情况下抛出编译时错误。
示例2:
// Java Program to Illustrate Conversion of // Runitime Exceptions into compile time errors // Using generics // Importing all utility classes import java.util.*; // Main class class GFG { // Main driver method public static void main(String[] args) { // Creating an ArrayList // Declaring object of string type ArrayList<String> al = new ArrayList<String>(); // Adding elements to the ArrayList // Custom input elements al.add("Sachin"); al.add("Rahul"); // Now compiler does not allow this operation al.add(10); String s1 = al.get(0); String s2 = al.get(1); String s3 = al.get(2); } }
运行结果:
prog.java:24: error: incompatible types: int cannot be converted to String al.add(10); ^ Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output 1 error
下面继续,不需要单独的类型转换。
如果不需要泛型,那么在上面的示例中,每次要从 ArrayList
中检索数据时,都需要对其进行类型转换。 每次检索操作的类型转换都是一件令人头疼的事情。 如果以某种方式已知列表仅包含字符串数据,则可以避免这种情况。
示例3
/* * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license * Click nbfs://nbhost/SystemFileSystem/Templates/Project/Maven2/JavaApp/src/main/java/${packagePath}/${mainClassName}.java to edit this template */ package com.yzinfo.demo; import java.util.ArrayList; /** * * @author Administrator */ public class YBA { public static void main(String[] args) { // Creating an ArrayList // Declaring object without any type specified ArrayList al = new ArrayList(); // Adding elements to the above object // using add() method al.add(10); al.add("Sachin"); al.add("Rahul"); // For every retrieval, // it needs to be casted to String for use String s1 = (String) al.get(0); String s2 = (String) al.get(1); System.out.print(s1); } }
运行结果:
--- exec-maven-plugin:3.0.0:exec (default-cli) @ project1 --- Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at com.yzinfo.project1.Project1.main(Project1.java:28) Command execution failed. org.apache.commons.exec.ExecuteException: Process exited with an error: 1 (Exit value: 1) at org.apache.commons.exec.DefaultExecutor.executeInternal (DefaultExecutor.java:404) at org.apache.commons.exec.DefaultExecutor.execute (DefaultExecutor.java:166) at org.codehaus.mojo.exec.ExecMojo.executeCommandLine (ExecMojo.java:982) at org.codehaus.mojo.exec.ExecMojo.executeCommandLine (ExecMojo.java:929)
现在来看看泛型是如何解决这个问题?
如果这个列表是通用的,那么它只需要 String
对象,并且在检索时只返回 String
对象。 因此不需要单独的类型转换。 上述说法是有道理的。
示例4
// A Simple Java program to demonstrate that // type casting is not needed in Generic import java.util.*; class Test { public static void main(String[] args) { // Creating an ArrayList // Declaring object of type String ArrayList<String> al = new ArrayList<String>(); // Custom input elements al.add("Sachin"); al.add("Rahul"); // Retrieval can be easily // without the trouble of casting String s1 = al.get(0); String s2 = al.get(1); // Print and display out the elements in objects System.out.print(al); } }
运行结果:
[Sachin, Rahul]
注意:在泛型的帮助下,虽然可以实现算法实现泛型算法,但可以在不同类型的对象上工作,同时它们也是类型安全的。
请记住,有些要点将描述泛型和非泛型之间的区别,下表列出了它们之间的清晰理解。
基础 | 非通用集合 | 通用集合 |
---|---|---|
语法 | ArrayList list = new ArrayList(); |
ArrayList<ReferenceType> list = new ArrayList<ReferenceType>(); |
类型安全 | 可以保存任何类型的数据,因此不是类型安全的。 | 只能保存定义类型的数据,因此类型安全。 |
类型转换 | 每次检索都需要进行单独的类型转换。 | 不需要类型转换。 |
编译时检查 | 在运行时检查类型安全。 | 在编译时检查类型安全。 |
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/264235.html