为什么要使用泛型

    从开发第一个系统,一直在使用泛型。那么为什么要使用泛型呢?或者说泛型有什么好处。

   先来看官方的的解释:

    

    泛型类和泛型方法同时具备可重用性、类型安全和效率,这是非泛型类和非泛型方法无法具备的。 泛型通常用与集合以及作用于集合的方法一起使用。 .NET Framework 2.0 版类库提供一个新的命名空间 System.Collections.Generic,其中包含几个新的基于泛型的集合类。 建议面向 .NET Framework 2.0 及更高版本的所有应用程序都使用新的泛型集合类,而不要使用旧的非泛型集合类如 ArrayList。 有关更多信息,请参见 .NET Framework 类库中的泛型

   首先第一句话,就清晰的告诉大家了,使用泛型就是这么好,重用,类型安全,效率。那么泛型为什么就有这么些好处了呢。

可重用性:

现在我们要返回两个信息,一种是字符串类型的信息,一种是数值类型的信息。

不使用泛型的话我们可以这么做,直接添加两个方法,一个返回字符串,另一个返回数值类型 。

 public string getString(string stringMessage)
        {
            return stringMessage;
        }

        public int getIng(int intMessage)
        {
            return intMessage;
        }


而使用泛型的话:只需要一个方法,很简单T就是我们泛型
 public T getWord<T>(T t)
        {
            return t;
        }

当然了,有些人说了字符串和数值可以相互转换,一个方法也可以,拜托了,这只是个例子,平常使用的话,泛型多用于IList。而且强制转换容易出运行时的问题。好的,问题来了,强制转换,说到强制转换,可以可以说下List,这就说到接下来的泛型的两个优点:类型安全和高效率。


    类型安全:

    List里面可以添加各种数据类型,它可以说是个异类集合。但是它容易数据类型转换时的运行时错误,也就是说类型不安全。

这得说到List的实现方式了。在List中可以放各种各样的数据类型,不论你push中的元素是什么东东,统统的变为Object类型。而且值类型向Object转换时,还得采取装箱操作,拿出来还得拆箱操作,很容易出现InvalidCastException异常,这有说到了程序员的习惯,对于获取的数据,判null的操作是很必要的。

引用类型向Object的转换应该不用什么消耗资源的操作。毕竟所有的对象都继承Object类型嘛。这一点小编还不太了解呢。这点还望大家都多多指点。

但是如果list中的对象不是某个子类对象的实例,那么强制类型转换就会出现错误,类型安全就会出现问题了。看下面的一段代码,某个程序员一不小心写成了Message类的强制转换。这就出问题了呀

 class Program
    {
        static void Main(string[] args)
        {
           System.Collections.ArrayList list = new System.Collections.ArrayList();
           PersonModel person = new PersonModel();
            person.Age = 23;
            person.Name ="张三";
            list.Add(person);
            PersonModel pserson2 = new PersonModel();
            if(list[0].GetType() == typeof(PersonModel)){
               //某个程序员,一不小心写成了Message类的强制转换
                Message message = (Message)list[0];
            }

         
            Console.WriteLine(pserson2);

            Console.Read();

        }

    }
    class PersonModel
    {
        string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        int age;

        public int Age
        {
            get { return age; }
            set { age = value; }
        }
        public override string ToString()
        {
            return this.name + "," + this.age;
        }
    }
    class MessageModel
    {
    }

而泛型呢,泛型解决了类型转换的根本问题,第一它用不着类型的强制转换。第二泛型集合一旦声明了是何种数据类型的集合,就不再允许其他类型加进去List。最后一旦出现类型转换的错误时,无需运行,编译就通不过。

看下面的使用泛型强制PersonModel的泛型集合,在编译时就提示错误

            List<PersonModel> personList = new List<PersonModel>();
            personList.Add(person);
            Message message2 =(Message)personList[0]; //提示错误,类型转换通不过

高效率

    最后还有效率的问题。

    很简单,泛型集合一旦声明了是何种数据类型的集合,就只能添加何种数据类型。添加去也不会转换成Object,它是运行时动态的获取类型参数。也就是说没有装箱和拆箱这些操作。减少了处理器的资源浪费。


总结:泛型是一种思想,也是一种技术,动态的获取参数类型,让编程更加的灵活。那么问题来了,怎么实现动态的获取参数类型呢?毫无疑问,使用反射。



### 无法构造数组的原因 在Java中,无法直接创建数组的主要原因与类擦除(type erasure)机制有关。由于信息在编译时会被擦除,运行时将不再保留具体的类信息[^1]。因此,当尝试创建一个数组时,编译器无法验证数组元素的类安全性。例如,如果尝试执行 `new T[]`,编译器会报错,因为运行时无法确定 `T` 的具体类。 此外,数组是协变的(covariant),这意味着父类类的数组可以引用子类类的数组。然而,这种协变性与的安全性要求相冲突。例如,以下代码会导致潜在的运行时错误: ```java Object[] objects = new String[1]; objects[0] = new Integer(42); // 编译时不会报错,但运行时会抛出 ArrayStoreException ``` 对于数组,类似的错误可能会被隐藏,直到运行时才暴露,这违背了设计的核心目标——确保类安全[^2]。 --- ### 解决方案 尽管不能直接创建数组,但可以通过以下几种方法实现类似的功能: #### 1. 使用 `ArrayList` 或其他集合类替代数组 `ArrayList` 是一种更灵活且类安全的选择,因为它完全避免了数组的协变问题。例如: ```java import java.util.ArrayList; public class Example { public static <T> ArrayList<T> createArrayList(int size) { return new ArrayList<>(size); } } ``` 这种方式不仅解决了类擦除的问题,还提供了更多的功能,如动态调整大小[^3]。 #### 2. 使用数组并进行强制类转换 如果必须使用数组,可以通过创建一个非数组并将其强制转换为数组。需要注意的是,这种方法会产生一个未检查的类转换警告(unchecked cast warning)。例如: ```java public class Example { public static <T> T[] createGenericArray(Class<T> clazz, int size) { @SuppressWarnings("unchecked") T[] array = (T[]) java.lang.reflect.Array.newInstance(clazz, size); return array; } } ``` 上述代码通过反射创建了一个指定类的数组,并进行了强制类转换。虽然这种方式可行,但需要开发者确保类安全[^4]。 #### 3. 使用原始类数组 另一种方法是直接使用原始类数组(raw type array),但这会失去提供的类安全性和编译时检查。例如: ```java public class Example { public static LinkedList[] createLinkedListArray(int size) { @SuppressWarnings("unchecked") LinkedList[] array = new LinkedList[size]; return array; } } ``` 尽管这种方式简单直接,但由于缺少类检查,可能导致运行时错误。 --- ### 总结 无法构造数组的根本原因是类擦除和数组协变之间的冲突。推荐的解决方案包括使用 `ArrayList` 替代数组、通过反射创建数组或使用原始类数组。每种方法都有其优缺点,开发者应根据具体需求选择合适的方式[^5]。 ---
评论 42
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值