Java中的非泛型与泛型集合的区别

首先来了解什么是泛型集合和非泛型集合,最重要的是处理实现部分,因为在实现过程中才能真正理解概念和它们之间的差异。
泛型基本上是编译时出现的错误,而不是运行时出现的错误。 泛型相对于非泛型有以下优势:

  • 代码重用:在泛型的帮助下,只需编写一次方法/类/接口并将其用于任何类型,而在非泛型中,代码需要在需要时一次又一次地编写。
  • 类型安全:泛型使错误在编译时出现而不是在运行时出现(在编译时知道代码中的问题总是比让代码在运行时失败更好)。

    示例:要创建一个存储学生姓名的 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

(0)
上一篇 2022年6月7日
下一篇 2022年6月7日

相关推荐

发表回复

登录后才能评论